Add option to disable connections by some protocols

Mostly useful to forbid connections without 'dd' secret
parent 9b11341f
......@@ -9,9 +9,11 @@ Features
* Promoted channels! See `mtproto_proxy_app.src` `tag` option.
* "secure" randomized-packet-size protocol (34-symbol secrets starting with 'dd')
to prevent detection by DPI
* Secure-only mode (only allow connections with 'dd'-secrets). See `allowed_protocols` option.
* Multiple ports with unique secret and promo tag for each port
* Automatic configuration reload (no need for restarts once per day)
* Very high performance - can handle tens of thousands connections!
* Most of the configuration options might be updated without service restart
* Very high performance - can handle tens of thousands connections! Scales to all CPU cores.
* Small codebase compared to oficial one
* A lots of metrics could be exported (optional)
......@@ -118,10 +120,13 @@ and then re-install proxy by
```
sudo make uninstall && make && sudo make install
```
There are other ways as well. It's even possible to update configuration options
without service restart / without downtime, but it's a bit trickier.
### Change default port / secret / ad tag
To change default settings, change `mtproto_proxy` section as:
To change default settings, change `mtproto_proxy` section of `prod-sys.config` as:
```
{mtproto_proxy,
%% see src/mtproto_proxy.app.src for examples.
......@@ -171,6 +176,21 @@ To do so, just add more configs to `ports` section, separated by comma, eg:
Each section should have unique `name`!
### Only allow connections with 'dd'-secrets
It might be useful in Iran, where proxies are detected by DPI.
You should disable all protocols other than `mtp_secure` by providing `allowed_protocols` option:
```
{mtproto_proxy,
[
{allowed_protocols, [mtp_secure]},
{ports,
[#{name => mtp_handler_1,
<..>
```
Helpers
-------
......
......@@ -226,9 +226,9 @@ handle_upstream_data(<<Header:64/binary, Rest/binary>>, #state{stage = init, sta
S#state{up_codec = UpCodec,
up_acc = Rest,
stage_state = undefined});
{error, unknown_protocol} = Err ->
{error, Reason} = Err ->
metric:count_inc([?APP, protocol_error, total],
1, #{labels => [unknown]}),
1, #{labels => [Reason]}),
Err
end;
handle_upstream_data(Bin, #state{stage = init, stage_state = <<>>} = S) ->
......
......@@ -60,25 +60,25 @@ init_down_encrypt(<<_:8/binary, Key:32/binary, IV:16/binary, _/binary>>) ->
%% @doc creates new obfuscated stream (MTProto proxy format)
-spec from_header(binary(), binary()) -> {ok, integer(), mtp_layer:codec(), codec()}.
-spec from_header(binary(), binary()) -> {ok, integer(), mtp_layer:codec(), codec()}
| {error, unknown_protocol | disabled_protocol}.
from_header(Header, Secret) when byte_size(Header) == 64 ->
{EncKey, EncIV} = init_up_encrypt(Header, Secret),
{DecKey, DecIV} = init_up_decrypt(Header, Secret),
St = new(EncKey, EncIV, DecKey, DecIV),
{<<_:56/binary, Bin1:8/binary, _/binary>>, St1} = decrypt(Header, St),
case Bin1 of
<<16#ef, 16#ef, 16#ef, 16#ef, _/binary>> ->
case get_protocol(Bin1) of
{error, unknown_protocol} = Err ->
Err;
Protocol ->
{ok, AllowedProtocols} = application:get_env(?APP, allowed_protocols),
case lists:member(Protocol, AllowedProtocols) of
true ->
DcId = get_dc(Bin1),
{ok, DcId, mtp_abridged, St1};
<<16#ee, 16#ee, 16#ee, 16#ee, _/binary>> ->
DcId = get_dc(Bin1),
{ok, DcId, mtp_intermediate, St1};
<<16#dd, 16#dd, 16#dd, 16#dd, _/binary>> ->
DcId = get_dc(Bin1),
{ok, DcId, mtp_secure, St1};
_ ->
metric:count_inc([?APP, protocol_error, total], 1, #{labels => [unknown]}),
{error, unknown_protocol}
{ok, DcId, Protocol, St1};
false ->
{error, disabled_protocol}
end
end.
init_up_encrypt(Bin, Secret) ->
......@@ -94,6 +94,15 @@ init_up_decrypt(Bin, Secret) ->
KeyHash = crypto:hash('sha256', <<Key/binary, Secret/binary>>),
{KeyHash, IV}.
get_protocol(<<16#ef, 16#ef, 16#ef, 16#ef, _/binary>>) ->
mtp_abridged;
get_protocol(<<16#ee, 16#ee, 16#ee, 16#ee, _/binary>>) ->
mtp_intermediate;
get_protocol(<<16#dd, 16#dd, 16#dd, 16#dd, _/binary>>) ->
mtp_secure;
get_protocol(_) ->
{error, unknown_protocol}.
get_dc(<<_:4/binary, DcId:16/signed-little-integer, _/binary>>) ->
DcId.
......
......@@ -44,7 +44,13 @@
%% tag is what you get from @MTProxybot
tag => <<"dcbe8f1493fa4cd9ab300891c0b5b326">>}]},
{num_acceptors, 60},
{max_connections, 40960}
{max_connections, 40960},
%% It's possible to forbid connection from telegram client to proxy
%% with some of the protocols. Might be useful to set this to
%% only `{allowed_protocols, [mtp_secure]}` if you want to only allow
%% connections to this proxy with "dd"-secrets. Connections by other
%% protocols will be immediately closed.
{allowed_protocols, [mtp_abridged, mtp_intermediate, mtp_secure]}
]},
{modules, []},
......
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