Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mtproto_proxy
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
mtproto_proxy
Commits
41870920
Unverified
Commit
41870920
authored
Jul 27, 2019
by
Sergey Prokhorov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cosmetic changes: README, docker, dialyzer fixes
parent
0a1604d4
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
80 additions
and
63 deletions
+80
-63
README.md
README.md
+25
-2
mtp_aes_cbc.erl
src/mtp_aes_cbc.erl
+0
-1
mtp_handler.erl
src/mtp_handler.erl
+21
-30
mtp_obfuscated.erl
src/mtp_obfuscated.erl
+7
-18
mtproto_proxy.app.src
src/mtproto_proxy.app.src
+5
-5
start.sh
start.sh
+20
-5
prop_mtp_obfuscated.erl
test/prop_mtp_obfuscated.erl
+2
-2
No files found.
README.md
View file @
41870920
...
@@ -9,7 +9,9 @@ Features
...
@@ -9,7 +9,9 @@ Features
*
Promoted channels! See
`mtproto_proxy_app.src`
`tag`
option.
*
Promoted channels! See
`mtproto_proxy_app.src`
`tag`
option.
*
"secure" randomized-packet-size protocol (34-symbol secrets starting with 'dd')
*
"secure" randomized-packet-size protocol (34-symbol secrets starting with 'dd')
to prevent detection by DPI
to prevent detection by DPI
*
Secure-only mode (only allow connections with 'dd'-secrets). See
`allowed_protocols`
option.
*
Fake-TLS protocol (base64 secrets) - another protocol to prevent DPI detection
*
Secure-only mode (only allow connections with 'dd' or fake-tls-base64-secrets).
See
`allowed_protocols`
option.
*
Multiple ports with unique secret and promo tag for each port
*
Multiple ports with unique secret and promo tag for each port
*
Very high performance - can handle tens of thousands connections! Scales to all CPU cores.
*
Very high performance - can handle tens of thousands connections! Scales to all CPU cores.
1Gbps, 90k connections on 4-core/8Gb RAM cloud server.
1Gbps, 90k connections on 4-core/8Gb RAM cloud server.
...
@@ -47,7 +49,10 @@ Where
...
@@ -47,7 +49,10 @@ Where
*
`-p 443`
/
`MTP_PORT=…`
proxy port
*
`-p 443`
/
`MTP_PORT=…`
proxy port
*
`-s d0d6e111bada5511fcce9584deadbeef`
/
`MTP_SECRET=…`
proxy secret (don't append
`dd`
! it should be 32 chars long!)
*
`-s d0d6e111bada5511fcce9584deadbeef`
/
`MTP_SECRET=…`
proxy secret (don't append
`dd`
! it should be 32 chars long!)
*
`-t dcbe8f1493fa4cd9ab300891c0b5b326`
/
`MTP_TAG=…`
ad-tag that you get from
[
@MTProxybot
](
https://t.me/MTProxybot
)
*
`-t dcbe8f1493fa4cd9ab300891c0b5b326`
/
`MTP_TAG=…`
ad-tag that you get from
[
@MTProxybot
](
https://t.me/MTProxybot
)
*
`-d`
/
`MTP_DD_ONLY=t`
only allow "secure" connections (dd-secrets)
*
`-a dd`
/
`MTP_DD_ONLY=t`
only allow "secure" connections (dd-secrets)
*
`-a tls`
/
`MTP_TLS_ONLY=t`
only allow "fake-TLS" connections (base64 secrets)
It's ok to provide both
`-a dd -a tls`
to allow both protocols. If no
`-a`
option provided, all protocols will be allowed.
### To run with custom config-file
### To run with custom config-file
...
@@ -234,6 +239,8 @@ Each section should have unique `name`!
...
@@ -234,6 +239,8 @@ Each section should have unique `name`!
### Only allow connections with 'dd'-secrets
### Only allow connections with 'dd'-secrets
This protocol uses randomized packet sizes, so it's more difficult to detect on DPI by
packet sizes.
It might be useful in Iran, where proxies are detected by DPI.
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:
You should disable all protocols other than
`mtp_secure`
by providing
`allowed_protocols`
option:
...
@@ -246,6 +253,22 @@ You should disable all protocols other than `mtp_secure` by providing `allowed_p
...
@@ -246,6 +253,22 @@ You should disable all protocols other than `mtp_secure` by providing `allowed_p
<
..
>
<
..
>
```
```
### Only allow fake-TLS connections with base64-secrets
Another censorship circumvention technique. MTPRoto proxy protocol pretends to be
HTTPS web traffic (technically speaking, TLSv1.3 + HTTP/2).
It's possible to only allow connections with this protocol by changing
`allowed_protocols`
to
be list with only
`mtp_fake_tls`
:
```
erlang
{
mtproto_proxy
,
[
{
allowed_protocols
,
[
mtp_fake_tls
]},
{
ports
,
[
#
{
name
=>
mtp_handler_1
,
<
..
>
```
### IPv6
### IPv6
Currently proxy only supports client connections via IPv6, but can only connect to Telegram servers
Currently proxy only supports client connections via IPv6, but can only connect to Telegram servers
...
...
src/mtp_aes_cbc.erl
View file @
41870920
...
@@ -67,7 +67,6 @@ do_decrypt(Data, Tail, #baes_st{decrypt = {DecKey, DecIv}} = S) ->
...
@@ -67,7 +67,6 @@ do_decrypt(Data, Tail, #baes_st{decrypt = {DecKey, DecIv}} = S) ->
NewDecIv
=
crypto
:
next_iv
(
aes_cbc
,
Data
),
NewDecIv
=
crypto
:
next_iv
(
aes_cbc
,
Data
),
{
Decrypted
,
Tail
,
S
#baes_st
{
decrypt
=
{
DecKey
,
NewDecIv
}}}.
{
Decrypted
,
Tail
,
S
#baes_st
{
decrypt
=
{
DecKey
,
NewDecIv
}}}.
%% To comply mtp_layer interface
try_decode_packet
(
Bin
,
S
)
->
try_decode_packet
(
Bin
,
S
)
->
case
decrypt
(
Bin
,
S
)
of
case
decrypt
(
Bin
,
S
)
of
{
<<>>
,
_
Tail
,
S1
}
->
{
<<>>
,
_
Tail
,
S1
}
->
...
...
src/mtp_handler.erl
View file @
41870920
...
@@ -180,10 +180,7 @@ handle_info({tcp, Sock, Data}, #state{sock = Sock, transport = Transport,
...
@@ -180,10 +180,7 @@ handle_info({tcp, Sock, Data}, #state{sock = Sock, transport = Transport,
{
ok
,
S1
}
->
{
ok
,
S1
}
->
ok
=
Transport
:
setopts
(
Sock
,
[{
active
,
once
}]),
ok
=
Transport
:
setopts
(
Sock
,
[{
active
,
once
}]),
%% Consider checking health here as well
%% Consider checking health here as well
{
noreply
,
bump_timer
(
S1
)};
{
noreply
,
bump_timer
(
S1
)}
{
error
,
Reason
}
->
?
log
(
info
,
"handle_data error
~p
"
,
[
Reason
]),
{
stop
,
normal
,
S
}
catch
error
:{
protocol_error
,
Type
,
Extra
}
->
catch
error
:{
protocol_error
,
Type
,
Extra
}
->
mtp_metric
:
count_inc
([
?
APP
,
protocol_error
,
total
],
1
,
#
{
labels
=>
[
Type
]}),
mtp_metric
:
count_inc
([
?
APP
,
protocol_error
,
total
],
1
,
#
{
labels
=>
[
Type
]}),
?
log
(
warning
,
"
~s
: protocol_error
~p
~p
"
,
[
inet
:
ntoa
(
Ip
),
Type
,
Extra
]),
?
log
(
warning
,
"
~s
: protocol_error
~p
~p
"
,
[
inet
:
ntoa
(
Ip
),
Type
,
Extra
]),
...
@@ -265,11 +262,9 @@ state_timeout(stop) ->
...
@@ -265,11 +262,9 @@ state_timeout(stop) ->
%% Handle telegram client -> proxy stream
%% Handle telegram client -> proxy stream
handle_upstream_data
(
Bin
,
#state
{
stage
=
tunnel
,
handle_upstream_data
(
Bin
,
#state
{
stage
=
tunnel
,
codec
=
UpCodec
}
=
S
)
->
codec
=
UpCodec
}
=
S
)
->
?
log
(
debug
,
"tunneling
~p
; codec=
~p
"
,
[
Bin
,
UpCodec
]),
{
ok
,
S3
,
UpCodec1
}
=
{
ok
,
S3
,
UpCodec1
}
=
mtp_codec
:
fold_packets
(
mtp_codec
:
fold_packets
(
fun
(
Decoded
,
S1
,
Codec1
)
->
fun
(
Decoded
,
S1
,
Codec1
)
->
?
log
(
debug
,
"raw tunneled packet
~p
"
,
[
Decoded
]),
mtp_metric
:
histogram_observe
(
mtp_metric
:
histogram_observe
(
[
?
APP
,
tg_packet_size
,
bytes
],
[
?
APP
,
tg_packet_size
,
bytes
],
byte_size
(
Decoded
),
byte_size
(
Decoded
),
...
@@ -279,20 +274,16 @@ handle_upstream_data(Bin, #state{stage = tunnel,
...
@@ -279,20 +274,16 @@ handle_upstream_data(Bin, #state{stage = tunnel,
end
,
S
,
Bin
,
UpCodec
),
end
,
S
,
Bin
,
UpCodec
),
{
ok
,
S3
#state
{
codec
=
UpCodec1
}};
{
ok
,
S3
#state
{
codec
=
UpCodec1
}};
handle_upstream_data
(
Bin
,
#state
{
codec
=
Codec0
}
=
S0
)
->
handle_upstream_data
(
Bin
,
#state
{
codec
=
Codec0
}
=
S0
)
->
?
log
(
debug
,
"Codec0:
~p
"
,
[
Codec0
]),
{
ok
,
S
,
Codec
}
=
{
ok
,
S
,
Codec
}
=
mtp_codec
:
fold_packets
(
mtp_codec
:
fold_packets
(
fun
(
Decoded
,
S1
,
Codec1
)
->
fun
(
Decoded
,
S1
,
Codec1
)
->
?
log
(
debug
,
"Codec1:
~p
, unfolded:
~p
"
,
[
Codec1
,
Decoded
]),
case
parse_upstream_data
(
Decoded
,
S1
#state
{
codec
=
Codec1
})
of
case
parse_upstream_data
(
Decoded
,
S1
#state
{
codec
=
Codec1
})
of
{
ok
,
S2
}
->
{
ok
,
S2
}
->
?
log
(
debug
,
"Codec2:
~p
"
,
[
S2
#state.codec
]),
{
S2
,
S2
#state.codec
};
{
S2
,
S2
#state.codec
};
{
error
,
Err
}
->
{
error
,
Err
}
->
error
(
Err
)
error
(
Err
)
end
end
end
,
S0
,
Bin
,
Codec0
),
end
,
S0
,
Bin
,
Codec0
),
?
log
(
debug
,
"Codec:
~p
"
,
[
Codec
]),
case
mtp_codec
:
is_empty
(
Codec
)
of
case
mtp_codec
:
is_empty
(
Codec
)
of
true
->
true
->
{
ok
,
S
#state
{
codec
=
Codec
}};
{
ok
,
S
#state
{
codec
=
Codec
}};
...
@@ -304,20 +295,14 @@ handle_upstream_data(Bin, #state{codec = Codec0} = S0) ->
...
@@ -304,20 +295,14 @@ handle_upstream_data(Bin, #state{codec = Codec0} = S0) ->
parse_upstream_data
(
<<?
TLS_START
,
_
/
binary
>>
=
AllData
,
parse_upstream_data
(
<<?
TLS_START
,
_
/
binary
>>
=
AllData
,
#state
{
stage
=
tls_hello
,
secret
=
Secret
,
codec
=
Codec0
}
=
S
)
when
#state
{
stage
=
tls_hello
,
secret
=
Secret
,
codec
=
Codec0
}
=
S
)
when
byte_size
(
AllData
)
>=
(
?
TLS_CLIENT_HELLO_LEN
+
5
)
->
byte_size
(
AllData
)
>=
(
?
TLS_CLIENT_HELLO_LEN
+
5
)
->
{
ok
,
AllowedProtocols
}
=
application
:
get_env
(
?
APP
,
allowed_protocols
),
assert_protocol
(
mtp_fake_tls
),
lists
:
member
(
mtp_fake_tls
,
AllowedProtocols
)
orelse
error
({
protocol_error
,
disabled_protocol
,
mtp_fake_tls
}),
<<
Data
:(
?
TLS_CLIENT_HELLO_LEN
+
5
)
/
binary
,
Tail
/
binary
>>
=
AllData
,
<<
Data
:(
?
TLS_CLIENT_HELLO_LEN
+
5
)
/
binary
,
Tail
/
binary
>>
=
AllData
,
case
mtp_fake_tls
:
from_client_hello
(
Data
,
Secret
)
of
{
ok
,
Response
,
SessionId
,
Timestamp
,
TlsCodec
}
=
mtp_fake_tls
:
from_client_hello
(
Data
,
Secret
),
{
ok
,
Response
,
SessionId
,
Timestamp
,
TlsCodec
}
->
maybe_check_tls_replay
(
SessionId
,
Timestamp
),
maybe_check_tls_replay
(
SessionId
,
Timestamp
),
Codec1
=
mtp_codec
:
replace
(
tls
,
true
,
TlsCodec
,
Codec0
),
Codec1
=
mtp_codec
:
replace
(
tls
,
true
,
TlsCodec
,
Codec0
),
Codec
=
mtp_codec
:
push_back
(
tls
,
Tail
,
Codec1
),
Codec
=
mtp_codec
:
push_back
(
tls
,
Tail
,
Codec1
),
ok
=
up_send_raw
(
Response
,
S
),
ok
=
up_send_raw
(
Response
,
S
),
{
ok
,
S
#state
{
codec
=
Codec
,
stage
=
init
}};
{
ok
,
S
#state
{
codec
=
Codec
,
stage
=
init
}};
{
error
,
_}
=
Err
->
Err
end
;
parse_upstream_data
(
<<?
TLS_START
,
_
/
binary
>>
=
Data
,
#state
{
stage
=
init
}
=
S
)
->
parse_upstream_data
(
<<?
TLS_START
,
_
/
binary
>>
=
Data
,
#state
{
stage
=
init
}
=
S
)
->
parse_upstream_data
(
Data
,
S
#state
{
stage
=
tls_hello
});
parse_upstream_data
(
Data
,
S
#state
{
stage
=
tls_hello
});
parse_upstream_data
(
<<
Header
:
64
/
binary
,
Rest
/
binary
>>
,
parse_upstream_data
(
<<
Header
:
64
/
binary
,
Rest
/
binary
>>
,
...
@@ -326,19 +311,20 @@ parse_upstream_data(<<Header:64/binary, Rest/binary>>,
...
@@ -326,19 +311,20 @@ parse_upstream_data(<<Header:64/binary, Rest/binary>>,
case
mtp_obfuscated
:
from_header
(
Header
,
Secret
)
of
case
mtp_obfuscated
:
from_header
(
Header
,
Secret
)
of
{
ok
,
DcId
,
PacketLayerMod
,
CryptoCodecSt
}
->
{
ok
,
DcId
,
PacketLayerMod
,
CryptoCodecSt
}
->
maybe_check_replay
(
Header
),
maybe_check_replay
(
Header
),
ProtoToReport
=
case
mtp_codec
:
info
(
tls
,
Codec0
)
of
ProtoToReport
=
{
true
,
_}
when
PacketLayerMod
==
mtp_secure
->
case
mtp_codec
:
info
(
tls
,
Codec0
)
of
mtp_secure_fake_tls
;
{
true
,
_}
when
PacketLayerMod
==
mtp_secure
->
{
false
,
_}
->
mtp_secure_fake_tls
;
PacketLayerMod
{
false
,
_}
->
end
,
assert_protocol
(
PacketLayerMod
),
PacketLayerMod
end
,
mtp_metric
:
count_inc
([
?
APP
,
protocol_ok
,
total
],
mtp_metric
:
count_inc
([
?
APP
,
protocol_ok
,
total
],
1
,
#
{
labels
=>
[
Listener
,
ProtoToReport
]}),
1
,
#
{
labels
=>
[
Listener
,
ProtoToReport
]}),
Codec1
=
mtp_codec
:
replace
(
crypto
,
mtp_obfuscated
,
CryptoCodecSt
,
Codec0
),
Codec1
=
mtp_codec
:
replace
(
crypto
,
mtp_obfuscated
,
CryptoCodecSt
,
Codec0
),
PacketCodec
=
PacketLayerMod
:
new
(),
PacketCodec
=
PacketLayerMod
:
new
(),
Codec2
=
mtp_codec
:
replace
(
packet
,
PacketLayerMod
,
PacketCodec
,
Codec1
),
Codec2
=
mtp_codec
:
replace
(
packet
,
PacketLayerMod
,
PacketCodec
,
Codec1
),
Codec
=
mtp_codec
:
push_back
(
crypto
,
Rest
,
Codec2
),
Codec
=
mtp_codec
:
push_back
(
crypto
,
Rest
,
Codec2
),
?
log
(
debug
,
"Hdr=
~p
, codec=
~p
"
,
[
Header
,
Codec
]),
Opts
=
#
{
ad_tag
=>
Tag
,
Opts
=
#
{
ad_tag
=>
Tag
,
addr
=>
Addr
},
addr
=>
Addr
},
{
RealDcId
,
Pool
,
Downstream
}
=
mtp_config
:
get_downstream_safe
(
DcId
,
Opts
),
{
RealDcId
,
Pool
,
Downstream
}
=
mtp_config
:
get_downstream_safe
(
DcId
,
Opts
),
...
@@ -358,6 +344,11 @@ parse_upstream_data(Bin, #state{stage = Stage, codec = Codec0} = S) when Stage =
...
@@ -358,6 +344,11 @@ parse_upstream_data(Bin, #state{stage = Stage, codec = Codec0} = S) when Stage =
Codec
=
mtp_codec
:
push_back
(
first
,
Bin
,
Codec0
),
Codec
=
mtp_codec
:
push_back
(
first
,
Bin
,
Codec0
),
{
ok
,
S
#state
{
codec
=
Codec
}}.
{
ok
,
S
#state
{
codec
=
Codec
}}.
assert_protocol
(
Protocol
)
->
{
ok
,
AllowedProtocols
}
=
application
:
get_env
(
?
APP
,
allowed_protocols
),
lists
:
member
(
Protocol
,
AllowedProtocols
)
orelse
error
({
protocol_error
,
disabled_protocol
,
Protocol
}).
maybe_check_replay
(
Packet
)
->
maybe_check_replay
(
Packet
)
->
%% Check for session replay attack: attempt to connect with the same 1st 64byte packet
%% Check for session replay attack: attempt to connect with the same 1st 64byte packet
case
application
:
get_env
(
?
APP
,
replay_check_session_storage
,
off
)
of
case
application
:
get_env
(
?
APP
,
replay_check_session_storage
,
off
)
of
...
...
src/mtp_obfuscated.erl
View file @
41870920
...
@@ -10,7 +10,6 @@
...
@@ -10,7 +10,6 @@
-
export
([
client_create
/
3
,
-
export
([
client_create
/
3
,
client_create
/
4
,
client_create
/
4
,
from_header
/
2
,
from_header
/
2
,
from_header
/
3
,
new
/
4
,
new
/
4
,
encrypt
/
2
,
encrypt
/
2
,
decrypt
/
2
,
decrypt
/
2
,
...
@@ -38,7 +37,7 @@ client_create(Secret, Protocol, DcId) ->
...
@@ -38,7 +37,7 @@ client_create(Secret, Protocol, DcId) ->
client_create
(
crypto
:
strong_rand_bytes
(
58
),
client_create
(
crypto
:
strong_rand_bytes
(
58
),
Secret
,
Protocol
,
DcId
).
Secret
,
Protocol
,
DcId
).
-
spec
client_create
(
binary
(),
binary
(),
mtp_
layer
:
codec
(),
integer
())
->
-
spec
client_create
(
binary
(),
binary
(),
mtp_
codec
:
packet_
codec
(),
integer
())
->
{
Packet
,
{
Packet
,
{
EncKey
,
EncIv
},
{
EncKey
,
EncIv
},
{
DecKey
,
DecIv
},
{
DecKey
,
DecIv
},
...
@@ -93,13 +92,9 @@ encode_dc_id(DcId) ->
...
@@ -93,13 +92,9 @@ encode_dc_id(DcId) ->
<<
DcId
:
16
/
signed
-
little
-
integer
>>
.
<<
DcId
:
16
/
signed
-
little
-
integer
>>
.
%% @doc creates new obfuscated stream (MTProto proxy format)
%% @doc creates new obfuscated stream (MTProto proxy format)
from_header
(
Header
,
Secret
)
->
-
spec
from_header
(
binary
(),
binary
())
->
{
ok
,
integer
(),
mtp_codec
:
packet_codec
(),
codec
()}
{
ok
,
AllowedProtocols
}
=
application
:
get_env
(
?
APP
,
allowed_protocols
),
|
{
error
,
unknown_protocol
}.
from_header
(
Header
,
Secret
,
AllowedProtocols
).
from_header
(
Header
,
Secret
)
when
byte_size
(
Header
)
==
64
->
-
spec
from_header
(
binary
(),
binary
())
->
{
ok
,
integer
(),
mtp_layer
:
codec
(),
codec
()}
|
{
error
,
unknown_protocol
|
disabled_protocol
}.
from_header
(
Header
,
Secret
,
AllowedProtocols
)
when
byte_size
(
Header
)
==
64
->
%% 1) Encryption key
%% 1) Encryption key
%% [--- _: 8b ----|---------- b: 48b -------------|-- _: 8b --] = header: 64b
%% [--- _: 8b ----|---------- b: 48b -------------|-- _: 8b --] = header: 64b
%% b_r: 48b = reverse([---------- b ------------------])
%% b_r: 48b = reverse([---------- b ------------------])
...
@@ -124,13 +119,8 @@ from_header(Header, Secret, AllowedProtocols) when byte_size(Header) == 64 ->
...
@@ -124,13 +119,8 @@ from_header(Header, Secret, AllowedProtocols) when byte_size(Header) == 64 ->
{
error
,
unknown_protocol
}
=
Err
->
{
error
,
unknown_protocol
}
=
Err
->
Err
;
Err
;
Protocol
->
Protocol
->
case
lists
:
member
(
Protocol
,
AllowedProtocols
)
of
DcId
=
get_dc
(
Bin1
),
true
->
{
ok
,
DcId
,
Protocol
,
St1
}
DcId
=
get_dc
(
Bin1
),
{
ok
,
DcId
,
Protocol
,
St1
};
false
->
{
error
,
disabled_protocol
}
end
end
.
end
.
init_up_encrypt
(
Bin
,
Secret
)
->
init_up_encrypt
(
Bin
,
Secret
)
->
...
@@ -173,7 +163,6 @@ decrypt(Encrypted, #st{decrypt = Dec} = St) ->
...
@@ -173,7 +163,6 @@ decrypt(Encrypted, #st{decrypt = Dec} = St) ->
{
Dec1
,
Data
}
=
crypto
:
stream_encrypt
(
Dec
,
Encrypted
),
{
Dec1
,
Data
}
=
crypto
:
stream_encrypt
(
Dec
,
Encrypted
),
{
Data
,
<<>>
,
St
#st
{
decrypt
=
Dec1
}}.
{
Data
,
<<>>
,
St
#st
{
decrypt
=
Dec1
}}.
%% To comply with mtp_layer interface
-
spec
try_decode_packet
(
iodata
(),
codec
())
->
{
ok
,
Decoded
::
binary
(),
Tail
::
binary
(),
codec
()}
-
spec
try_decode_packet
(
iodata
(),
codec
())
->
{
ok
,
Decoded
::
binary
(),
Tail
::
binary
(),
codec
()}
|
{
incomplete
,
codec
()}.
|
{
incomplete
,
codec
()}.
try_decode_packet
(
Encrypted
,
St
)
->
try_decode_packet
(
Encrypted
,
St
)
->
...
@@ -198,7 +187,7 @@ client_server_test() ->
...
@@ -198,7 +187,7 @@ client_server_test() ->
DcId
=
4
,
DcId
=
4
,
Protocol
=
mtp_secure
,
Protocol
=
mtp_secure
,
{
Packet
,
_,
_,
_
CliCodec
}
=
client_create
(
Secret
,
Protocol
,
DcId
),
{
Packet
,
_,
_,
_
CliCodec
}
=
client_create
(
Secret
,
Protocol
,
DcId
),
Srv
=
from_header
(
Packet
,
Secret
,
[
Protocol
]
),
Srv
=
from_header
(
Packet
,
Secret
),
?
assertMatch
({
ok
,
DcId
,
Protocol
,
_},
Srv
).
?
assertMatch
({
ok
,
DcId
,
Protocol
,
_},
Srv
).
-
endif
.
-
endif
.
src/mtproto_proxy.app.src
View file @
41870920
...
@@ -52,11 +52,11 @@
...
@@ -52,11 +52,11 @@
{num_acceptors, 60},
{num_acceptors, 60},
{max_connections, 40960},
{max_connections, 40960},
%% It's possible to forbid connection from telegram client to proxy
%% It's possible to forbid connection from telegram client to proxy
%% with some of the protocols.
Might be useful
to set this to
%% with some of the protocols.
Ti's recommended
to set this to
%% only `{allowed_protocols, [mtp_secure
]}` if you want to only allow
%% only `{allowed_protocols, [mtp_secure
, mtp_fake_tls]}` because those
%%
connections to this proxy with "dd"-secrets
. Connections by other
%%
protocols are more resistant to DPI detection
. Connections by other
%% protocols will be immediately
clos
ed.
%% protocols will be immediately
disallow
ed.
{allowed_protocols, [mtp_
abridged, mtp_intermediate, mtp_secure, mtp_fake_tls
]},
{allowed_protocols, [mtp_
fake_tls, mtp_secure, mtp_abridged, mtp_intermediate
]},
{init_dc_connections, 2},
{init_dc_connections, 2},
{clients_per_dc_connection, 300},
{clients_per_dc_connection, 300},
...
...
start.sh
View file @
41870920
...
@@ -34,6 +34,7 @@ PORT=${MTP_PORT:-""}
...
@@ -34,6 +34,7 @@ PORT=${MTP_PORT:-""}
SECRET
=
${
MTP_SECRET
:-
""
}
SECRET
=
${
MTP_SECRET
:-
""
}
TAG
=
${
MTP_TAG
:-
""
}
TAG
=
${
MTP_TAG
:-
""
}
DD_ONLY
=
${
MTP_DD_ONLY
:-
""
}
DD_ONLY
=
${
MTP_DD_ONLY
:-
""
}
TLS_ONLY
=
${
MTP_TLS_ONLY
:-
""
}
# check command line options
# check command line options
while
getopts
"p:s:t:dh"
o
;
do
while
getopts
"p:s:t:dh"
o
;
do
...
@@ -47,7 +48,17 @@ while getopts "p:s:t:dh" o; do
...
@@ -47,7 +48,17 @@ while getopts "p:s:t:dh" o; do
t
)
t
)
TAG
=
${
OPTARG
}
TAG
=
${
OPTARG
}
;;
;;
a
)
if
[
"
${
OPTARG
}
"
-e
"dd"
]
;
then
DD_ONLY
=
"y"
elif
[
"
${
OPTARG
}
"
-eq
"tls"
]
;
then
TLS_ONLY
=
"y"
else
error
"Invalid -a value: '
${
OPTARG
}
'"
fi
;;
d
)
d
)
echo
"Warning: -d is deprecated! use '-a dd' instead"
DD_ONLY
=
"y"
DD_ONLY
=
"y"
;;
;;
h
)
h
)
...
@@ -56,10 +67,14 @@ while getopts "p:s:t:dh" o; do
...
@@ -56,10 +67,14 @@ while getopts "p:s:t:dh" o; do
esac
esac
done
done
DD
_ARG
=
""
PROTO
_ARG
=
""
if
[
-n
"
${
DD_ONLY
}
"
]
;
then
if
[
-n
"
${
DD_ONLY
}
"
-a
-n
"
${
TLS_ONLY
}
"
]
;
then
DD_ARG
=
'-mtproto_proxy allowed_protocols [mtp_secure]'
PROTO_ARG
=
"-mtproto_proxy allowed_protocols [mtp_fake_tls, mtp_secure]"
elif
[
-n
"
${
DD_ONLY
}
"
]
;
then
PROTO_ARG
=
'-mtproto_proxy allowed_protocols [mtp_secure]'
elif
[
-n
"
${
TLS_ONLY
}
"
]
;
then
PROTO_ARG
=
'-mtproto_proxy allowed_protocols [mtp_fake_tls]'
fi
fi
# if at least one option is set...
# if at least one option is set...
...
@@ -76,7 +91,7 @@ if [ -n "${PORT}" -o -n "${SECRET}" -o -n "${TAG}" ]; then
...
@@ -76,7 +91,7 @@ if [ -n "${PORT}" -o -n "${SECRET}" -o -n "${TAG}" ]; then
[
-n
"
`
echo
$TAG
|
grep
-x
'[[:xdigit:]]\{32\}'
`
"
]
||
\
[
-n
"
`
echo
$TAG
|
grep
-x
'[[:xdigit:]]\{32\}'
`
"
]
||
\
error
"Invalid tag. Should be 32 chars of 0-9 a-f"
error
"Invalid tag. Should be 32 chars of 0-9 a-f"
exec
$CMD
$
DD
_ARG
-mtproto_proxy
ports
"[#{name => mtproto_proxy, port =>
$PORT
, secret => <<
\"
$SECRET
\"
>>, tag => <<
\"
$TAG
\"
>>}]"
exec
$CMD
$
PROTO
_ARG
-mtproto_proxy
ports
"[#{name => mtproto_proxy, port =>
$PORT
, secret => <<
\"
$SECRET
\"
>>, tag => <<
\"
$TAG
\"
>>}]"
else
else
exec
$CMD
$
DD
_ARG
exec
$CMD
$
PROTO
_ARG
fi
fi
test/prop_mtp_obfuscated.erl
View file @
41870920
...
@@ -52,7 +52,7 @@ cs_hs_exchange(Secret, DcId, Protocol) ->
...
@@ -52,7 +52,7 @@ cs_hs_exchange(Secret, DcId, Protocol) ->
%% io:format("Secret: ~p; DcId: ~p, Protocol: ~p~n",
%% io:format("Secret: ~p; DcId: ~p, Protocol: ~p~n",
%% [Secret, DcId, Protocol]),
%% [Secret, DcId, Protocol]),
{
Packet
,
_,
_,
_
CliCodec
}
=
mtp_obfuscated
:
client_create
(
Secret
,
Protocol
,
DcId
),
{
Packet
,
_,
_,
_
CliCodec
}
=
mtp_obfuscated
:
client_create
(
Secret
,
Protocol
,
DcId
),
case
mtp_obfuscated
:
from_header
(
Packet
,
Secret
,
[
Protocol
]
)
of
case
mtp_obfuscated
:
from_header
(
Packet
,
Secret
)
of
{
ok
,
DcId
,
Protocol
,
_
SrvCodec
}
->
{
ok
,
DcId
,
Protocol
,
_
SrvCodec
}
->
true
;
true
;
_
->
_
->
...
@@ -78,7 +78,7 @@ cs_stream_exchange(Secret, DcId, Protocol, Stream) ->
...
@@ -78,7 +78,7 @@ cs_stream_exchange(Secret, DcId, Protocol, Stream) ->
%% io:format("Secret: ~p; DcId: ~p, Protocol: ~p~n",
%% io:format("Secret: ~p; DcId: ~p, Protocol: ~p~n",
%% [Secret, DcId, Protocol]),
%% [Secret, DcId, Protocol]),
{
Header
,
_,
_,
CliCodec
}
=
mtp_obfuscated
:
client_create
(
Secret
,
Protocol
,
DcId
),
{
Header
,
_,
_,
CliCodec
}
=
mtp_obfuscated
:
client_create
(
Secret
,
Protocol
,
DcId
),
{
ok
,
DcId
,
Protocol
,
SrvCodec
}
=
mtp_obfuscated
:
from_header
(
Header
,
Secret
,
[
Protocol
]
),
{
ok
,
DcId
,
Protocol
,
SrvCodec
}
=
mtp_obfuscated
:
from_header
(
Header
,
Secret
),
%% Client to server
%% Client to server
{
CliCodec1
,
{
CliCodec1
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment