-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhttps_proxy_s.erl
More file actions
103 lines (95 loc) · 3.58 KB
/
https_proxy_s.erl
File metadata and controls
103 lines (95 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
-module(https_proxy_s).
-export([start/0]).
-define(PROXY_S_PORT, 10099).
-define(PROXY_C_S_KEY, "your-secret-password").
start() ->
{ok, Lsock} = gen_tcp:listen(?PROXY_S_PORT, [binary, {packet, 4}, {active, false}, {reuseaddr, true}]),
io:format("listen sock: ~w~n", [Lsock]),
accept(Lsock).
tunnel(Sock, Tsock) ->
Pid1 = spawn(fun F() ->
case gen_tcp:recv(Sock, 0) of
{ok, B} ->
io:format("data from sock arrive ~w ~w ~w~n", [byte_size(B), Sock, Tsock]),
case gen_tcp:send(Tsock, B) of
ok -> F();
{error, R} ->
io:format("error from tsock: ~p ~w ~w~n", [R, Tsock, Sock]),
gen_tcp:close(Tsock), gen_tcp:close(Sock)
end;
{error, R} ->
io:format("error from sock: ~p ~w ~w~n", [R, Sock, Tsock]),
gen_tcp:close(Sock), gen_tcp:close(Tsock)
end end),
gen_tcp:controlling_process(Sock, Pid1),
Pid2 = spawn(fun F() ->
case gen_tcp:recv(Tsock, 0) of
{ok, B} ->
io:format("data from tsock arrive ~w ~w ~w~n", [byte_size(B), Tsock, Sock]),
case gen_tcp:send(Sock, B) of
ok -> F();
{error, R} ->
io:format("error from sock: ~p ~w ~w~n", [R, Sock, Tsock]),
gen_tcp:close(Sock), gen_tcp:close(Tsock)
end;
{error, R} ->
io:format("error from tsock: ~p ~w ~w~n", [R, Tsock, Sock]),
gen_tcp:close(Tsock), gen_tcp:close(Sock)
end end),
gen_tcp:controlling_process(Tsock, Pid2).
encrypt_binary(Bin) ->
Seeds = [29,220,39,154,155,183,36,101,240,97,60,232,246,60,81,32,173,79,158,172],
fun F(_, <<>>) -> <<>>; F(Idx, Rest) ->
Seed = lists:nth(Idx rem 20 + 1, Seeds),
<<H, R/binary>> = Rest,
Val = (H + Seed) rem 256,
<<Val, (F(Idx + 1, R))/binary>>
end(0, Bin).
decrypt_binary(Bin) ->
Seeds = [29,220,39,154,155,183,36,101,240,97,60,232,246,60,81,32,173,79,158,172],
fun F(_, <<>>) -> <<>>; F(Idx, Rest) ->
Seed = lists:nth(Idx rem 20 + 1, Seeds),
<<H, R/binary>> = Rest,
if
H - Seed < 0 -> Val = 256 + H - Seed;
true -> Val = H - Seed
end,
<<Val, (F(Idx + 1, R))/binary>>
end(0, Bin).
recv(Sock) ->
inet:setopts(Sock, [{active, once}]),
receive
{tcp, Sock, Bin} ->
Data = decrypt_binary(Bin),
InitReq = {init, TargetHost, 443, Proxy_CS_key} = binary_to_term(Data),
case Proxy_CS_key of
?PROXY_C_S_KEY ->
io:format("recv init req from proxy clientt: ~p ~w~n", [InitReq, Sock]),
case gen_tcp:connect(TargetHost, 443, [binary, {active, false}, {packet, 0}]) of
{ok, Tsock} ->
io:format("connect to target host success: ~p ~w ~w~n", [TargetHost, Tsock, Sock]),
InitRsp = {init, TargetHost, ok},
ok = gen_tcp:send(Sock, term_to_binary(InitRsp)),
tunnel(Sock, Tsock);
{error, R} ->
io:format("connect to target host failed: ~p ~p ~w~n", [R, TargetHost, Sock]),
gen_tcp:close(Sock)
end;
_ ->
io:format("proxy cs key not match: ~w~n", [Sock]),
gen_tcp:close(Sock)
end;
{tcp_passive, Sock} -> io:format("tcp passive: ~w~n", [Sock]);
{tcp_closed, Sock} ->
io:format("tcp closed: ~w~n", [Sock]);
{tcp_error, Sock, Reason} ->
io:format("tcp error reason: ~p ~w~n", [Reason, Sock]),
gen_tcp:close(Sock);
Other -> io:format("other in recv: ~p ~w~n", [Other, Sock])
end.
accept(Lsock) ->
{ok, Sock} = gen_tcp:accept(Lsock),
io:format("accept sock: ~w~n", [Sock]),
Pid = spawn(fun() -> recv(Sock) end),
gen_tcp:controlling_process(Sock, Pid),
accept(Lsock).