-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathserver.nim
197 lines (151 loc) · 6.21 KB
/
server.nim
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import std/[asyncdispatch, strformat]
import overrides/[asyncnet]
import times, print, connection, pipe
from globals import nil
type
ServerConnectionPoolContext = object
listener: Connection
inbound: Connections
outbound: Connections
var context = ServerConnectionPoolContext()
proc monitorData(data: string): tuple[trust: bool, port: uint32] =
var port: uint32
try:
if len(data) < 16: return (false, port)
var sh1_c: uint32
var sh2_c: uint32
copyMem(unsafeAddr sh1_c, unsafeAddr data[0], 4)
copyMem(unsafeAddr sh2_c, unsafeAddr data[4], 4)
copyMem(unsafeAddr port, unsafeAddr data[8], 4)
let chk1 = sh1_c == globals.sh1
let chk2 = sh2_c == globals.sh2
return (chk1 and chk2, port)
except:
return (false, port)
proc processConnection(client_a: Connection) {.async.} =
# var remote: Connection
var client: Connection = client_a
var remote: Connection
proc proccessRemote() {.async.}
proc proccessClient() {.async.}
proc remoteTrusted(): Future[Connection]{.async.} =
var new_remote = newConnection()
new_remote.trusted = TrustStatus.yes
new_remote.estabilished = false
return new_remote
proc remoteUnTrusted(): Future[Connection]{.async.} =
var new_remote = newConnection()
new_remote.trusted = TrustStatus.no
await new_remote.socket.connect(globals.final_target_ip, globals.final_target_port.Port)
if globals.log_conn_create: echo "connected to ", globals.final_target_ip, ":", $globals.final_target_port
return new_remote
var closed = false
proc close() =
if not closed:
closed = true
if globals.log_conn_destory: echo "[processRemote] closed client & remote"
client.close()
remote.close()
proc proccessRemote() {.async.} =
var data = ""
while not remote.isClosed:
try:
data = await remote.recv(globals.chunk_size)
if globals.log_data_len: echo &"[proccessRemote] {data.len()} bytes from remote"
except:
if client.isTrusted():
if remote.estabilished:
close()
break
else:
if globals.log_conn_destory: echo "[processRemote] closed remote"
break
else:
close()
break
if data.len() == 0:
close()
break
try:
if not client.isClosed():
if client.isTrusted():
normalSend(data)
await client.send(data)
if globals.log_data_len: echo &"[proccessRemote] Sent {data.len()} bytes -> client"
except:
close()
break
try:
remote = await remoteUnTrusted()
asyncCheck proccessRemote()
except:
echo &"[Error] Failed to connect to the Target {globals.final_target_ip}:{globals.final_target_port}"
client.close()
return
proc proccessClient() {.async.} =
var data = ""
while not client.isClosed:
try:
data = await client.recv(globals.chunk_size)
if globals.log_data_len: echo &"[proccessClient] {data.len()} bytes from client"
except:
break
if data == "":
break
if (remote.isTrusted()) and (not remote.estabilished):
remote.estabilished = true
try:
await remote.socket.connect(globals.next_route_addr, client.port.Port)
asyncCheck proccessRemote()
except:
break
if client.trusted == TrustStatus.pending:
var (trust, port) = monitorData(data)
if trust:
if globals.multi_port:
echo "multi-port target:" , port
client.port = port
else:
client.port = globals.next_route_port.uint32
client.trusted = TrustStatus.yes
print "Fake Handshake Complete !"
remote.close()
asyncdispatch.poll()
try:
remote = await remoteTrusted()
except:
echo &"[Error] Failed to connect to the Target {globals.next_route_addr}:{globals.next_route_port}"
break
continue
elif (epochTime().uint - client.creation_time) > globals.trust_time:
echo "[proccessClient] non-client connection detected ! forwarding to real website."
client.trusted = TrustStatus.no
try:
if client.isTrusted():
normalRead(data)
if not remote.isClosed():
await remote.send(data)
if globals.log_data_len: echo &"[proccessClient] {data.len()} bytes -> remote "
except: break
close()
try:
asyncCheck proccessClient()
except:
echo "[Server] root level exception"
print getCurrentExceptionMsg()
proc start*(){.async.} =
proc start_server(){.async.} =
context.listener = newConnection()
context.listener.socket.setSockOpt(OptReuseAddr, true)
context.listener.socket.bindAddr(globals.listen_port.Port, globals.listen_addr)
echo &"Started tcp server... {globals.listen_addr}:{globals.listen_port}"
context.listener.socket.listen()
if globals.multi_port:
echo "Multi port mode!"
while true:
let (address, client) = await context.listener.socket.acceptAddr()
let con = newConnection(client)
if globals.log_conn_create: print "Connected client: ", address
asyncCheck processConnection(con)
echo &"Mode Server: {globals.listen_addr} <-> ({globals.final_target_domain} with ip {globals.final_target_ip})"
asyncCheck start_server()