Add "secure" protocol with padding

parent 32e1dc91
...@@ -215,6 +215,8 @@ handle_upstream_data(<<Header:64/binary, Rest/binary>>, #state{stage = init, sta ...@@ -215,6 +215,8 @@ handle_upstream_data(<<Header:64/binary, Rest/binary>>, #state{stage = init, sta
secret = Secret} = S) -> secret = Secret} = S) ->
case mtp_obfuscated:from_header(Header, Secret) of case mtp_obfuscated:from_header(Header, Secret) of
{ok, DcId, PacketLayerMod, ObfuscatedCodec} -> {ok, DcId, PacketLayerMod, ObfuscatedCodec} ->
metric:count_inc([?APP, protocol_ok, total],
1, #{labels => [PacketLayerMod]}),
ObfuscatedLayer = mtp_layer:new(mtp_obfuscated, ObfuscatedCodec), ObfuscatedLayer = mtp_layer:new(mtp_obfuscated, ObfuscatedCodec),
PacketLayer = mtp_layer:new(PacketLayerMod, PacketLayerMod:new()), PacketLayer = mtp_layer:new(PacketLayerMod, PacketLayerMod:new()),
UpCodec = mtp_layer:new(mtp_wrap, mtp_wrap:new(PacketLayer, UpCodec = mtp_layer:new(mtp_wrap, mtp_wrap:new(PacketLayer,
...@@ -224,7 +226,9 @@ handle_upstream_data(<<Header:64/binary, Rest/binary>>, #state{stage = init, sta ...@@ -224,7 +226,9 @@ handle_upstream_data(<<Header:64/binary, Rest/binary>>, #state{stage = init, sta
S#state{up_codec = UpCodec, S#state{up_codec = UpCodec,
up_acc = Rest, up_acc = Rest,
stage_state = undefined}); stage_state = undefined});
Err -> {error, unknown_protocol} = Err ->
metric:count_inc([?APP, protocol_error, total],
1, #{labels => [unknown]}),
Err Err
end; end;
handle_upstream_data(Bin, #state{stage = init, stage_state = <<>>} = S) -> handle_upstream_data(Bin, #state{stage = init, stage_state = <<>>} = S) ->
......
...@@ -10,12 +10,14 @@ ...@@ -10,12 +10,14 @@
-behaviour(mtp_layer). -behaviour(mtp_layer).
-export([new/0, -export([new/0,
new/1,
try_decode_packet/2, try_decode_packet/2,
encode_packet/2]). encode_packet/2]).
-export_type([codec/0]). -export_type([codec/0]).
-record(int_st, -record(int_st,
{buffer = <<>> :: binary()}). {padding = false :: boolean(),
buffer = <<>> :: binary()}).
-define(MAX_PACKET_SIZE, 1 * 1024 * 1024). % 1mb -define(MAX_PACKET_SIZE, 1 * 1024 * 1024). % 1mb
-define(APP, mtproto_proxy). -define(APP, mtproto_proxy).
-define(MAX_SIZE, 16#80000000). -define(MAX_SIZE, 16#80000000).
...@@ -23,7 +25,10 @@ ...@@ -23,7 +25,10 @@
-opaque codec() :: #int_st{}. -opaque codec() :: #int_st{}.
new() -> new() ->
#int_st{}. new(#{}).
new(Opts) ->
#int_st{padding = maps:get(padding, Opts, false)}.
-spec try_decode_packet(binary(), codec()) -> {ok, binary(), codec()} -spec try_decode_packet(binary(), codec()) -> {ok, binary(), codec()}
| {incomplete, codec()}. | {incomplete, codec()}.
...@@ -45,9 +50,14 @@ try_decode_packet(Bin, #int_st{buffer = Buf} = St) when byte_size(Buf) > 0 -> ...@@ -45,9 +50,14 @@ try_decode_packet(Bin, #int_st{buffer = Buf} = St) when byte_size(Buf) > 0 ->
try_decode_packet(Bin, #int_st{buffer = <<>>} = St) -> try_decode_packet(Bin, #int_st{buffer = <<>>} = St) ->
{incomplete, St#int_st{buffer = Bin}}. {incomplete, St#int_st{buffer = Bin}}.
try_decode_packet_len(Len, Data, St) -> try_decode_packet_len(Len, Data, #int_st{padding = Pad} = St) ->
Padding = case Pad of
true -> Len rem 4;
false -> 0
end,
NopadLen = Len - Padding,
case Data of case Data of
<<_:4/binary, Packet:Len/binary, Rest/binary>> -> <<_:4/binary, Packet:NopadLen/binary, _Padding:Padding/binary, Rest/binary>> ->
{ok, Packet, St#int_st{buffer = Rest}}; {ok, Packet, St#int_st{buffer = Rest}};
_ -> _ ->
{incomplete, St#int_st{buffer = Data}} {incomplete, St#int_st{buffer = Data}}
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
| mtp_abridged | mtp_abridged
| mtp_full | mtp_full
| mtp_obfuscated | mtp_obfuscated
| mtp_intermediate
| mtp_secure
| mtp_rpc | mtp_rpc
| mtp_wrap. | mtp_wrap.
-type layer() :: {codec(), state()} | ident. -type layer() :: {codec(), state()} | ident.
......
...@@ -75,6 +75,9 @@ from_header(Header, Secret) when byte_size(Header) == 64 -> ...@@ -75,6 +75,9 @@ from_header(Header, Secret) when byte_size(Header) == 64 ->
<<_:56/binary, 16#ee, 16#ee, 16#ee, 16#ee, _/binary>> -> <<_:56/binary, 16#ee, 16#ee, 16#ee, 16#ee, _/binary>> ->
DcId = get_dc(NewHeader), DcId = get_dc(NewHeader),
{ok, DcId, mtp_intermediate, St1}; {ok, DcId, mtp_intermediate, St1};
<<_:56/binary, 16#dd, 16#dd, 16#dd, 16#dd, _/binary>> ->
DcId = get_dc(NewHeader),
{ok, DcId, mtp_secure, St1};
_ -> _ ->
metric:count_inc([?APP, protocol_error, total], 1, #{labels => [unknown]}), metric:count_inc([?APP, protocol_error, total], 1, #{labels => [unknown]}),
{error, unknown_protocol} {error, unknown_protocol}
......
%%% @author Sergey <me@seriyps.ru>
%%% @copyright (C) 2018, Sergey
%%% @doc
%%% MTProto intermediate protocol with random padding ("secure")
%%% @end
%%% Created : 29 Jun 2018 by Sergey <me@seriyps.ru>
-module(mtp_secure).
-behaviour(mtp_layer).
-export([new/0,
try_decode_packet/2,
encode_packet/2]).
-export_type([codec/0]).
-opaque codec() :: mtp_intermediate:codec().
new() ->
mtp_intermediate:new(#{padding => true}).
-spec try_decode_packet(binary(), codec()) -> {ok, binary(), codec()}
| {incomplete, codec()}.
try_decode_packet(Data, St) ->
mtp_intermediate:try_decode_packet(Data, St).
-spec encode_packet(iodata(), codec()) -> iodata().
encode_packet(Data, St) ->
mtp_intermediate:encode_packet(Data, St).
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment