girl 0.88.0 → 0.93.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of girl might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/girl/head.rb +40 -29
- data/lib/girl/proxy.rb +46 -92
- data/lib/girl/proxy_worker.rb +926 -838
- data/lib/girl/proxyd.rb +6 -25
- data/lib/girl/proxyd_worker.rb +676 -624
- data/lib/girl/udp.rb +37 -47
- data/lib/girl/udpd.rb +26 -36
- data/lib/girl/version.rb +1 -1
- metadata +2 -2
data/lib/girl/proxyd.rb
CHANGED
@@ -13,23 +13,20 @@ module Girl
|
|
13
13
|
class Proxyd
|
14
14
|
|
15
15
|
def initialize( config_path = nil )
|
16
|
-
if config_path
|
17
|
-
unless File.exist?( config_path )
|
18
|
-
raise "not found config file #{ config_path }"
|
19
|
-
end
|
20
|
-
|
16
|
+
if config_path then
|
17
|
+
raise "not found config file #{ config_path }" unless File.exist?( config_path )
|
21
18
|
conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
|
22
19
|
proxyd_port = conf[ :proxyd_port ]
|
23
20
|
worker_count = conf[ :worker_count ]
|
24
21
|
end
|
25
22
|
|
26
|
-
unless proxyd_port
|
23
|
+
unless proxyd_port then
|
27
24
|
proxyd_port = 6060
|
28
25
|
end
|
29
26
|
|
30
27
|
nprocessors = Etc.nprocessors
|
31
28
|
|
32
|
-
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors
|
29
|
+
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
|
33
30
|
worker_count = nprocessors
|
34
31
|
end
|
35
32
|
|
@@ -38,25 +35,9 @@ module Girl
|
|
38
35
|
puts "proxyd port #{ proxyd_port }"
|
39
36
|
puts "worker count #{ worker_count }"
|
40
37
|
|
41
|
-
|
42
|
-
PACK_SIZE
|
43
|
-
READ_SIZE
|
44
|
-
WMEMS_LIMIT
|
45
|
-
RESUME_BELOW
|
46
|
-
EXPIRE_NEW
|
47
|
-
EXPIRE_AFTER
|
48
|
-
CHECK_EXPIRE_INTERVAL
|
49
|
-
CHECK_STATUS_INTERVAL
|
50
|
-
SEND_STATUS_UNTIL
|
51
|
-
MULTI_MISS_SIZE
|
52
|
-
MISS_RANGE_LIMIT
|
53
|
-
CONFUSE_UNTIL
|
54
|
-
RESOLV_CACHE_EXPIRE
|
55
|
-
]
|
56
|
-
|
57
|
-
len = names.map{ | name | name.size }.max
|
38
|
+
len = CONSTS.map{ | name | name.size }.max
|
58
39
|
|
59
|
-
|
40
|
+
CONSTS.each do | name |
|
60
41
|
puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
|
61
42
|
end
|
62
43
|
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -9,11 +9,11 @@ module Girl
|
|
9
9
|
@mutex = Mutex.new
|
10
10
|
@reads = []
|
11
11
|
@writes = []
|
12
|
-
@
|
13
|
-
@roles = {} # sock => :dotr / :proxyd / :dst / :tund
|
14
|
-
@dst_infos = {} # dst => {}
|
15
|
-
@tunds = {} # port => tund
|
12
|
+
@roles = {} # sock => :dotr / :proxyd / :dst / :tund / :tcpd / :streamd
|
16
13
|
@tund_infos = {} # tund => {}
|
14
|
+
@tcpd_infos = {} # tcpd => {}
|
15
|
+
@dst_infos = {} # dst => {}
|
16
|
+
@streamd_infos = {} # streamd => {}
|
17
17
|
@tunneling_tunds = {} # tunneling_addr => tund
|
18
18
|
@resolv_caches = {} # domain => [ ip, created_at ]
|
19
19
|
|
@@ -29,32 +29,40 @@ module Girl
|
|
29
29
|
def looping
|
30
30
|
puts "p#{ Process.pid } #{ Time.new } looping"
|
31
31
|
loop_check_expire
|
32
|
-
|
32
|
+
loop_check_resume
|
33
33
|
|
34
34
|
loop do
|
35
35
|
rs, ws = IO.select( @reads, @writes )
|
36
36
|
|
37
37
|
@mutex.synchronize do
|
38
|
-
#
|
39
|
-
ws.each do | sock |
|
40
|
-
case @roles[ sock ]
|
41
|
-
when :dst
|
42
|
-
write_dst( sock )
|
43
|
-
when :tund
|
44
|
-
write_tund( sock )
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
38
|
+
# 先读,再写,避免打上关闭标记后读到
|
48
39
|
rs.each do | sock |
|
49
40
|
case @roles[ sock ]
|
50
|
-
when :dotr
|
41
|
+
when :dotr then
|
51
42
|
read_dotr( sock )
|
52
|
-
when :proxyd
|
43
|
+
when :proxyd then
|
53
44
|
read_proxyd( sock )
|
54
|
-
when :
|
55
|
-
read_dst( sock )
|
56
|
-
when :tund
|
45
|
+
when :tund then
|
57
46
|
read_tund( sock )
|
47
|
+
when :tcpd then
|
48
|
+
read_tcpd( sock )
|
49
|
+
when :dst then
|
50
|
+
read_dst( sock )
|
51
|
+
when :streamd then
|
52
|
+
read_streamd( sock )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ws.each do | sock |
|
57
|
+
case @roles[ sock ]
|
58
|
+
when :proxyd then
|
59
|
+
write_proxyd( sock )
|
60
|
+
when :tund then
|
61
|
+
write_tund( sock )
|
62
|
+
when :dst then
|
63
|
+
write_dst( sock )
|
64
|
+
when :streamd then
|
65
|
+
write_streamd( sock )
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
@@ -71,7 +79,7 @@ module Girl
|
|
71
79
|
data = [ 0, TUND_FIN ].pack( 'Q>C' )
|
72
80
|
|
73
81
|
@tund_infos.each do | tund, tund_info |
|
74
|
-
if !tund.closed? && tund_info[ :tun_addr ]
|
82
|
+
if !tund.closed? && tund_info[ :tun_addr ] then
|
75
83
|
# puts "debug1 send tund fin"
|
76
84
|
tund.sendmsg( data, 0, tund_info[ :tun_addr ] )
|
77
85
|
end
|
@@ -83,6 +91,230 @@ module Girl
|
|
83
91
|
|
84
92
|
private
|
85
93
|
|
94
|
+
##
|
95
|
+
# add proxyd ctlmsg
|
96
|
+
#
|
97
|
+
def add_proxyd_ctlmsg_tund_port( tund_info )
|
98
|
+
data = [ 0, TUND_PORT, tund_info[ :port ], tund_info[ :tcpd_port ] ].pack( 'Q>Cnn' )
|
99
|
+
@proxyd_info[ :ctlmsgs ] << [ data, tund_info[ :tun_addr ] ]
|
100
|
+
add_write( @proxyd )
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# add ctlmsg
|
105
|
+
#
|
106
|
+
def add_ctlmsg( tund, data )
|
107
|
+
tund_info = @tund_infos[ tund ]
|
108
|
+
tund_info[ :ctlmsgs ] << data
|
109
|
+
add_write( tund )
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# add read
|
114
|
+
#
|
115
|
+
def add_read( sock, role = nil )
|
116
|
+
unless @reads.include?( sock ) then
|
117
|
+
@reads << sock
|
118
|
+
|
119
|
+
if role then
|
120
|
+
@roles[ sock ] = role
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# add write
|
127
|
+
#
|
128
|
+
def add_write( sock )
|
129
|
+
unless @writes.include?( sock ) then
|
130
|
+
@writes << sock
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# close dst
|
136
|
+
#
|
137
|
+
def close_dst( dst )
|
138
|
+
# puts "debug1 close dst"
|
139
|
+
close_sock( dst )
|
140
|
+
del_dst_info( dst )
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# close read dst
|
145
|
+
#
|
146
|
+
def close_read_dst( dst )
|
147
|
+
return if dst.closed?
|
148
|
+
# puts "debug1 close read dst"
|
149
|
+
dst.close_read
|
150
|
+
@reads.delete( dst )
|
151
|
+
|
152
|
+
if dst.closed? then
|
153
|
+
# puts "debug1 delete dst info"
|
154
|
+
@roles.delete( dst )
|
155
|
+
dst_info = del_dst_info( dst )
|
156
|
+
else
|
157
|
+
dst_info = @dst_infos[ dst ]
|
158
|
+
end
|
159
|
+
|
160
|
+
dst_info[ :paused ] = false
|
161
|
+
dst_info
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# close read streamd
|
166
|
+
#
|
167
|
+
def close_read_streamd( streamd )
|
168
|
+
return if streamd.closed?
|
169
|
+
# puts "debug1 close read streamd"
|
170
|
+
streamd.close_read
|
171
|
+
@reads.delete( streamd )
|
172
|
+
|
173
|
+
if streamd.closed? then
|
174
|
+
# puts "debug1 delete streamd info"
|
175
|
+
@roles.delete( streamd )
|
176
|
+
streamd_info = @streamd_infos.delete( streamd )
|
177
|
+
else
|
178
|
+
streamd_info = @streamd_infos[ streamd ]
|
179
|
+
end
|
180
|
+
|
181
|
+
streamd_info
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# close sock
|
186
|
+
#
|
187
|
+
def close_sock( sock )
|
188
|
+
sock.close
|
189
|
+
@reads.delete( sock )
|
190
|
+
@writes.delete( sock )
|
191
|
+
@roles.delete( sock )
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# close streamd
|
196
|
+
#
|
197
|
+
def close_streamd( streamd )
|
198
|
+
# puts "debug1 close streamd"
|
199
|
+
close_sock( streamd )
|
200
|
+
@streamd_infos.delete( streamd )
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# close tund
|
205
|
+
#
|
206
|
+
def close_tund( tund )
|
207
|
+
# puts "debug1 close tund"
|
208
|
+
close_sock( tund )
|
209
|
+
tund_info = @tund_infos.delete( tund )
|
210
|
+
tcpd = tund_info[ :tcpd ]
|
211
|
+
close_sock( tcpd )
|
212
|
+
@tcpd_infos.delete( tcpd )
|
213
|
+
tund_info[ :dsts ].each{ | _, dst | set_dst_closing( dst ) }
|
214
|
+
@tunneling_tunds.delete( tund_info[ :tun_addr ] )
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# close write dst
|
219
|
+
#
|
220
|
+
def close_write_dst( dst )
|
221
|
+
return if dst.closed?
|
222
|
+
# puts "debug1 close write dst"
|
223
|
+
dst.close_write
|
224
|
+
@writes.delete( dst )
|
225
|
+
|
226
|
+
if dst.closed? then
|
227
|
+
# puts "debug1 delete dst info"
|
228
|
+
@roles.delete( dst )
|
229
|
+
dst_info = del_dst_info( dst )
|
230
|
+
else
|
231
|
+
dst_info = @dst_infos[ dst ]
|
232
|
+
end
|
233
|
+
|
234
|
+
dst_info
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# close write streamd
|
239
|
+
#
|
240
|
+
def close_write_streamd( streamd )
|
241
|
+
return if streamd.closed?
|
242
|
+
# puts "debug1 close write streamd"
|
243
|
+
streamd.close_write
|
244
|
+
@writes.delete( streamd )
|
245
|
+
|
246
|
+
if streamd.closed? then
|
247
|
+
# puts "debug1 delete streamd info"
|
248
|
+
@roles.delete( streamd )
|
249
|
+
streamd_info = @streamd_infos.delete( streamd )
|
250
|
+
else
|
251
|
+
streamd_info = @streamd_infos[ streamd ]
|
252
|
+
end
|
253
|
+
|
254
|
+
streamd_info
|
255
|
+
end
|
256
|
+
|
257
|
+
##
|
258
|
+
# deal with destination addr
|
259
|
+
#
|
260
|
+
def deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
261
|
+
dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
262
|
+
dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
263
|
+
|
264
|
+
begin
|
265
|
+
dst.connect_nonblock( destination_addr )
|
266
|
+
rescue IO::WaitWritable
|
267
|
+
rescue Exception => e
|
268
|
+
puts "p#{ Process.pid } #{ Time.new } connect destination #{ domain_port } #{ e.class }"
|
269
|
+
return false
|
270
|
+
end
|
271
|
+
|
272
|
+
dst_id = dst.local_address.ip_port
|
273
|
+
|
274
|
+
@dst_infos[ dst ] = {
|
275
|
+
id: dst_id, # id
|
276
|
+
tund: tund, # 对应tund
|
277
|
+
domain_port: domain_port, # 目的地和端口
|
278
|
+
rbuff: '', # 对应的streamd没准备好,暂存读到的流量
|
279
|
+
streamd: nil, # 对应的streamd
|
280
|
+
wbuff: '', # 从streamd读到的流量
|
281
|
+
src_id: src_id, # 近端src id
|
282
|
+
created_at: Time.new, # 创建时间
|
283
|
+
last_recv_at: nil, # 上一次收到新流量(由streamd收到)的时间
|
284
|
+
last_sent_at: nil, # 上一次发出流量(由streamd发出)的时间
|
285
|
+
paused: false, # 是否已暂停读
|
286
|
+
closing: false, # 准备关闭
|
287
|
+
closing_write: false # 准备关闭写
|
288
|
+
}
|
289
|
+
|
290
|
+
add_read( dst, :dst )
|
291
|
+
|
292
|
+
tund_info = @tund_infos[ tund ]
|
293
|
+
tund_info[ :dst_ids ][ src_id ] = dst_id
|
294
|
+
tund_info[ :dsts ][ dst_id ] = dst
|
295
|
+
|
296
|
+
data = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
297
|
+
# puts "debug1 add ctlmsg paired #{ src_id } #{ dst_id }"
|
298
|
+
add_ctlmsg( tund, data )
|
299
|
+
true
|
300
|
+
end
|
301
|
+
|
302
|
+
##
|
303
|
+
# del dst info
|
304
|
+
#
|
305
|
+
def del_dst_info( dst )
|
306
|
+
dst_info = @dst_infos.delete( dst )
|
307
|
+
tund = dst_info[ :tund ]
|
308
|
+
|
309
|
+
unless tund.closed? then
|
310
|
+
tund_info = @tund_infos[ tund ]
|
311
|
+
tund_info[ :dsts ].delete( dst_info[ :id ] )
|
312
|
+
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
313
|
+
end
|
314
|
+
|
315
|
+
dst_info
|
316
|
+
end
|
317
|
+
|
86
318
|
##
|
87
319
|
# loop check expire
|
88
320
|
#
|
@@ -96,137 +328,107 @@ module Girl
|
|
96
328
|
now = Time.new
|
97
329
|
|
98
330
|
@tund_infos.each do | tund, tund_info |
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
trigger = true
|
106
|
-
else
|
107
|
-
data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
|
108
|
-
# puts "debug1 #{ Time.new } #{ tund_info[ :port ] } heartbeat"
|
109
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
110
|
-
del_dst_ids = []
|
111
|
-
|
112
|
-
tund_info[ :dsts ].each do | dst_id, dst |
|
113
|
-
if dst.closed?
|
114
|
-
dst_info = @dst_infos[ dst ]
|
115
|
-
|
116
|
-
if dst_info && ( now - dst_info[ :last_continue_at ] > EXPIRE_AFTER )
|
117
|
-
puts "p#{ Process.pid } #{ Time.new } expire dst ext #{ dst_info[ :domain_port ] }"
|
118
|
-
tund_info[ :wmems ].delete_if { | dst_id_pack_id, _ | dst_id_pack_id.first == dst_id }
|
119
|
-
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
120
|
-
@dst_infos.delete( dst )
|
121
|
-
del_dst_ids << dst_id
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
if del_dst_ids.any?
|
127
|
-
tund_info[ :dsts ].delete_if { | dst_id, _ | del_dst_ids.include?( dst_id ) }
|
128
|
-
end
|
129
|
-
end
|
331
|
+
last_recv_at = tund_info[ :last_recv_at ] || tund_info[ :created_at ]
|
332
|
+
|
333
|
+
if tund_info[ :dsts ].empty? && ( now - last_recv_at >= EXPIRE_AFTER ) then
|
334
|
+
puts "p#{ Process.pid } #{ Time.new } expire tund #{ tund_info[ :port ] }"
|
335
|
+
set_tund_closing( tund )
|
336
|
+
trigger = true
|
130
337
|
end
|
131
338
|
end
|
132
339
|
|
133
340
|
@dst_infos.each do | dst, dst_info |
|
134
|
-
|
341
|
+
last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
|
342
|
+
last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
|
343
|
+
|
344
|
+
if ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
|
135
345
|
puts "p#{ Process.pid } #{ Time.new } expire dst #{ dst_info[ :domain_port ] }"
|
136
|
-
|
346
|
+
set_dst_closing( dst )
|
137
347
|
trigger = true
|
138
348
|
end
|
139
349
|
end
|
140
350
|
|
141
|
-
if trigger
|
142
|
-
next_tick
|
143
|
-
end
|
351
|
+
next_tick if trigger
|
144
352
|
end
|
145
353
|
end
|
146
354
|
end
|
147
355
|
end
|
148
356
|
|
149
357
|
##
|
150
|
-
# loop check
|
358
|
+
# loop check resume
|
151
359
|
#
|
152
|
-
def
|
360
|
+
def loop_check_resume
|
153
361
|
Thread.new do
|
154
362
|
loop do
|
155
|
-
sleep
|
363
|
+
sleep CHECK_RESUME_INTERVAL
|
156
364
|
|
157
365
|
@mutex.synchronize do
|
158
|
-
|
159
|
-
@tunds.each do | tund_port, tund |
|
160
|
-
tund_info = @tund_infos[ tund ]
|
161
|
-
|
162
|
-
if tund_info[ :dsts ].any?
|
163
|
-
now = Time.new
|
164
|
-
|
165
|
-
tund_info[ :dsts ].each do | dst_id, dst |
|
166
|
-
dst_info = @dst_infos[ dst ]
|
167
|
-
|
168
|
-
if dst_info && ( now - dst_info[ :last_continue_at ] < SEND_STATUS_UNTIL )
|
169
|
-
data = [ 0, DEST_STATUS, dst_id, dst_info[ :biggest_pack_id ], dst_info[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
170
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
if @pause_dsts.any?
|
178
|
-
resume_dsts = []
|
179
|
-
ignore_dsts = []
|
180
|
-
|
181
|
-
@pause_dsts.each do | dst |
|
182
|
-
dst_info = @dst_infos[ dst ]
|
183
|
-
|
184
|
-
if dst_info
|
185
|
-
tund = dst_info[ :tund ]
|
186
|
-
|
187
|
-
if tund.closed?
|
188
|
-
ignore_dsts << dst
|
189
|
-
else
|
190
|
-
tund_info = @tund_infos[ tund ]
|
191
|
-
|
192
|
-
if tund_info[ :wmems ].size < RESUME_BELOW
|
193
|
-
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
|
194
|
-
resume_dsts << dst
|
195
|
-
end
|
196
|
-
end
|
197
|
-
else
|
198
|
-
ignore_dsts << dst
|
199
|
-
end
|
200
|
-
end
|
366
|
+
trigger = false
|
201
367
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
end
|
368
|
+
@dst_infos.select{ | _, dst_info | dst_info[ :paused ] }.each do | dst, dst_info |
|
369
|
+
streamd = dst_info[ :streamd ]
|
370
|
+
streamd_info = @streamd_infos[ streamd ]
|
206
371
|
|
207
|
-
|
208
|
-
|
372
|
+
if streamd_info[ :wbuff ].size < RESUME_BELOW then
|
373
|
+
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
|
374
|
+
dst_info[ :paused ] = false
|
375
|
+
add_read( dst )
|
376
|
+
trigger = true
|
209
377
|
end
|
378
|
+
end
|
210
379
|
|
211
|
-
|
212
|
-
|
380
|
+
@streamd_infos.select{ | _, streamd_info | streamd_info[ :paused ] }.each do | streamd, streamd_info |
|
381
|
+
dst = streamd_info[ :dst ]
|
382
|
+
dst_info = @dst_infos[ dst ]
|
383
|
+
|
384
|
+
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
385
|
+
puts "p#{ Process.pid } #{ Time.new } resume streamd #{ streamd_info[ :domain_port ] }"
|
386
|
+
streamd_info[ :paused ] = false
|
387
|
+
add_read( streamd )
|
388
|
+
trigger = true
|
213
389
|
end
|
214
390
|
end
|
391
|
+
|
392
|
+
next_tick if trigger
|
215
393
|
end
|
216
394
|
end
|
217
395
|
end
|
218
396
|
end
|
219
397
|
|
398
|
+
##
|
399
|
+
# new a proxyd
|
400
|
+
#
|
401
|
+
def new_a_proxyd( proxyd_port )
|
402
|
+
proxyd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
403
|
+
proxyd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
404
|
+
proxyd.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
|
405
|
+
|
406
|
+
puts "p#{ Process.pid } #{ Time.new } proxyd bind on #{ proxyd_port }"
|
407
|
+
@proxyd = proxyd
|
408
|
+
@proxyd_info = {
|
409
|
+
ctlmsgs: [] # [ ctlmsg, to_addr ]
|
410
|
+
}
|
411
|
+
|
412
|
+
add_read( proxyd, :proxyd )
|
413
|
+
end
|
414
|
+
|
415
|
+
##
|
416
|
+
# next tick
|
417
|
+
#
|
418
|
+
def next_tick
|
419
|
+
@dotw.write( '.' )
|
420
|
+
end
|
421
|
+
|
220
422
|
##
|
221
423
|
# resolve domain
|
222
424
|
#
|
223
425
|
def resolve_domain( tund, src_id, domain_port )
|
224
426
|
resolv_cache = @resolv_caches[ domain_port ]
|
225
427
|
|
226
|
-
if resolv_cache
|
428
|
+
if resolv_cache then
|
227
429
|
destination_addr, created_at = resolv_cache
|
228
430
|
|
229
|
-
if Time.new - created_at < RESOLV_CACHE_EXPIRE
|
431
|
+
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
230
432
|
# puts "debug1 #{ domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
|
231
433
|
deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
232
434
|
return
|
@@ -239,7 +441,7 @@ module Girl
|
|
239
441
|
Thread.new do
|
240
442
|
colon_idx = domain_port.rindex( ':' )
|
241
443
|
|
242
|
-
if colon_idx
|
444
|
+
if colon_idx then
|
243
445
|
destination_domain = domain_port[ 0...colon_idx ]
|
244
446
|
destination_port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
|
245
447
|
|
@@ -251,12 +453,12 @@ module Girl
|
|
251
453
|
end
|
252
454
|
|
253
455
|
@mutex.synchronize do
|
254
|
-
if destination_addr
|
456
|
+
if destination_addr then
|
255
457
|
# puts "debug1 resolved #{ domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
|
256
458
|
@resolv_caches[ domain_port ] = [ destination_addr, Time.new ]
|
257
459
|
|
258
|
-
unless tund.closed?
|
259
|
-
if deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
460
|
+
unless tund.closed? then
|
461
|
+
if deal_with_destination_addr( tund, src_id, destination_addr, domain_port ) then
|
260
462
|
next_tick
|
261
463
|
end
|
262
464
|
end
|
@@ -266,316 +468,353 @@ module Girl
|
|
266
468
|
end
|
267
469
|
|
268
470
|
##
|
269
|
-
#
|
471
|
+
# send data
|
270
472
|
#
|
271
|
-
def
|
272
|
-
dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
273
|
-
dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
274
|
-
|
473
|
+
def send_data( sock, data, to_addr )
|
275
474
|
begin
|
276
|
-
|
277
|
-
rescue IO::WaitWritable
|
278
|
-
|
279
|
-
|
280
|
-
|
475
|
+
written = sock.sendmsg_nonblock( data, 0, to_addr )
|
476
|
+
rescue IO::WaitWritable, Errno::EINTR
|
477
|
+
return :wait
|
478
|
+
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
479
|
+
puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
|
480
|
+
return :fatal
|
281
481
|
end
|
282
482
|
|
283
|
-
|
284
|
-
|
285
|
-
@dst_infos[ dst ] = {
|
286
|
-
id: dst_id, # id
|
287
|
-
tund: tund, # 对应tund
|
288
|
-
domain_port: domain_port, # 域名和端口
|
289
|
-
biggest_pack_id: 0, # 最大包号码
|
290
|
-
wbuff: '', # 写前
|
291
|
-
src_id: src_id, # 近端src id
|
292
|
-
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
293
|
-
continue_src_pack_id: 0, # 收到几
|
294
|
-
pieces: {}, # 跳号包 src_pack_id => data
|
295
|
-
is_src_closed: false, # src是否已关闭
|
296
|
-
biggest_src_pack_id: 0, # src最大包号码
|
297
|
-
completed_pack_id: 0, # 完成到几(对面收到几)
|
298
|
-
last_continue_at: Time.new, # 上一次发生流量的时间
|
299
|
-
is_closing: false # 是否准备关闭
|
300
|
-
}
|
301
|
-
|
302
|
-
add_read( dst, :dst )
|
303
|
-
|
304
|
-
tund_info = @tund_infos[ tund ]
|
305
|
-
tund_info[ :dst_ids ][ src_id ] = dst_id
|
306
|
-
tund_info[ :dsts ][ dst_id ] = dst
|
307
|
-
|
308
|
-
data = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
309
|
-
# puts "debug1 send paired #{ data.inspect }"
|
310
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
311
|
-
|
312
|
-
true
|
483
|
+
written
|
313
484
|
end
|
314
485
|
|
315
486
|
##
|
316
|
-
#
|
487
|
+
# set dst closing
|
317
488
|
#
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
@proxyd = proxyd
|
325
|
-
add_read( proxyd, :proxyd )
|
489
|
+
def set_dst_closing( dst )
|
490
|
+
return if dst.closed?
|
491
|
+
dst_info = @dst_infos[ dst ]
|
492
|
+
dst_info[ :closing ] = true
|
493
|
+
@reads.delete( dst )
|
494
|
+
add_write( dst )
|
326
495
|
end
|
327
496
|
|
328
497
|
##
|
329
|
-
#
|
498
|
+
# set dst closing write
|
330
499
|
#
|
331
|
-
def
|
332
|
-
if
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
@roles[ sock ] = role
|
337
|
-
end
|
338
|
-
end
|
500
|
+
def set_dst_closing_write( dst )
|
501
|
+
return if dst.closed?
|
502
|
+
dst_info = @dst_infos[ dst ]
|
503
|
+
dst_info[ :closing_write ] = true
|
504
|
+
add_write( dst )
|
339
505
|
end
|
340
506
|
|
341
507
|
##
|
342
|
-
#
|
508
|
+
# set streamd closing
|
343
509
|
#
|
344
|
-
def
|
345
|
-
if
|
346
|
-
|
347
|
-
|
510
|
+
def set_streamd_closing( streamd )
|
511
|
+
return if streamd.closed?
|
512
|
+
streamd_info = @streamd_infos[ streamd ]
|
513
|
+
streamd_info[ :closing ] = true
|
514
|
+
@reads.delete( streamd )
|
515
|
+
add_write( streamd )
|
348
516
|
end
|
349
517
|
|
350
518
|
##
|
351
|
-
#
|
519
|
+
# set streamd closing write
|
352
520
|
#
|
353
|
-
def
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
end
|
521
|
+
def set_streamd_closing_write( streamd )
|
522
|
+
return if streamd.closed?
|
523
|
+
streamd_info = @streamd_infos[ streamd ]
|
524
|
+
streamd_info[ :closing_write ] = true
|
525
|
+
add_write( streamd )
|
359
526
|
end
|
360
527
|
|
361
528
|
##
|
362
|
-
# set is closing
|
529
|
+
# set tund is closing
|
363
530
|
#
|
364
|
-
def
|
365
|
-
if
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
dst_info = @dst_infos[ sock ]
|
372
|
-
dst_info[ :is_closing ] = true
|
373
|
-
when :tund
|
374
|
-
tund_info = @tund_infos[ sock ]
|
375
|
-
tund_info[ :is_closing ] = true
|
376
|
-
end
|
531
|
+
def set_tund_closing( tund )
|
532
|
+
return if tund.closed?
|
533
|
+
tund_info = @tund_infos[ tund ]
|
534
|
+
tund_info[ :closing ] = true
|
535
|
+
@reads.delete( tund )
|
536
|
+
add_write( tund )
|
537
|
+
end
|
377
538
|
|
378
|
-
|
379
|
-
|
380
|
-
|
539
|
+
##
|
540
|
+
# read dotr
|
541
|
+
#
|
542
|
+
def read_dotr( dotr )
|
543
|
+
dotr.read( 1 )
|
381
544
|
end
|
382
545
|
|
383
546
|
##
|
384
|
-
#
|
547
|
+
# read proxyd
|
385
548
|
#
|
386
|
-
def
|
387
|
-
|
388
|
-
|
549
|
+
def read_proxyd( proxyd )
|
550
|
+
data, addrinfo, rflags, *controls = proxyd.recvmsg
|
551
|
+
from_addr = addrinfo.to_sockaddr
|
389
552
|
|
390
|
-
if
|
391
|
-
|
392
|
-
|
553
|
+
if @tunneling_tunds.include?( from_addr ) then
|
554
|
+
tund = @tunneling_tunds[ from_addr ]
|
555
|
+
tund_info = @tund_infos[ tund ]
|
556
|
+
puts "p#{ Process.pid } #{ Time.new } resend tund port #{ tund_info[ :port ] }, #{ tund_info[ :stream_port ] }"
|
557
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
393
558
|
return
|
394
559
|
end
|
395
560
|
|
396
|
-
|
397
|
-
tund_info = @tund_infos[ tund ]
|
398
|
-
dst_id = dst_info[ :id ]
|
399
|
-
pack_id = dst_info[ :biggest_pack_id ]
|
400
|
-
idx = 0
|
401
|
-
len = data.bytesize
|
402
|
-
|
403
|
-
while idx < len
|
404
|
-
chunk = data[ idx, PACK_SIZE ]
|
405
|
-
pack_id += 1
|
406
|
-
|
407
|
-
if pack_id <= CONFUSE_UNTIL
|
408
|
-
chunk = @custom.encode( chunk )
|
409
|
-
# puts "debug1 encoded chunk #{ pack_id }"
|
410
|
-
end
|
561
|
+
result = @custom.check( data, addrinfo )
|
411
562
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
tund_info[ :wmems ][ [ dst_id, pack_id ] ] = data2
|
416
|
-
dst_info[ :send_ats ][ pack_id ] = now
|
417
|
-
idx += PACK_SIZE
|
563
|
+
if result != :success then
|
564
|
+
puts "p#{ Process.pid } #{ Time.new } #{ result }"
|
565
|
+
return
|
418
566
|
end
|
419
567
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
if tund_info[ :wmems ].size >= WMEMS_LIMIT
|
425
|
-
puts "p#{ Process.pid } #{ Time.new } pause dst #{ dst_id } #{ dst_info[ :domain_port ] } #{ dst_info[ :biggest_pack_id ] }"
|
426
|
-
add_pause_dst( dst )
|
427
|
-
end
|
428
|
-
end
|
568
|
+
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
569
|
+
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
570
|
+
tund_port = tund.local_address.ip_port
|
571
|
+
add_read( tund, :tund )
|
429
572
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
573
|
+
tcpd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
574
|
+
tcpd.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
|
575
|
+
tcpd.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
576
|
+
tcpd_port = tcpd.local_address.ip_port
|
577
|
+
tcpd.listen( 127 )
|
578
|
+
add_read( tcpd, :tcpd )
|
579
|
+
|
580
|
+
tund_info = {
|
581
|
+
port: tund_port, # 端口
|
582
|
+
tcpd: tcpd, # 对应的tcpd
|
583
|
+
tcpd_port: tcpd_port, # tcpd端口
|
584
|
+
ctlmsgs: [], # [ ctlmsg, to_addr ]
|
585
|
+
tun_addr: from_addr, # tun地址
|
586
|
+
dsts: {}, # dst_id => dst
|
587
|
+
dst_ids: {}, # src_id => dst_id
|
588
|
+
created_at: Time.new, # 创建时间
|
589
|
+
last_recv_at: nil, # 上一次收到流量的时间
|
590
|
+
closing: false, # 准备关闭
|
591
|
+
changed_tun_addr: nil # 记录到和tun addr不符的来源地址
|
592
|
+
}
|
437
593
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
if @roles[ sock ] == :tund
|
444
|
-
puts "#{ Time.new } #{ e.class }, close tund"
|
445
|
-
close_tund( sock )
|
446
|
-
return false
|
447
|
-
end
|
448
|
-
end
|
594
|
+
@tunneling_tunds[ from_addr ] = tund
|
595
|
+
@tund_infos[ tund ] = tund_info
|
596
|
+
@tcpd_infos[ tcpd ] = {
|
597
|
+
tund: tund
|
598
|
+
}
|
449
599
|
|
450
|
-
|
600
|
+
puts "p#{ Process.pid } #{ Time.new } a new tunnel #{ addrinfo.ip_unpack.inspect } - #{ tund_port }, #{ tcpd_port }, #{ @tund_infos.size } tunds"
|
601
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
451
602
|
end
|
452
603
|
|
453
604
|
##
|
454
|
-
#
|
605
|
+
# read tund
|
455
606
|
#
|
456
|
-
def
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
tund = dst_info[ :tund ]
|
462
|
-
|
463
|
-
if tund.closed?
|
464
|
-
@dst_infos.delete( dst )
|
607
|
+
def read_tund( tund )
|
608
|
+
begin
|
609
|
+
data, addrinfo, rflags, *controls = tund.recvmsg_nonblock
|
610
|
+
rescue IO::WaitReadable, Errno::EINTR
|
611
|
+
print 'r'
|
465
612
|
return
|
466
613
|
end
|
467
614
|
|
615
|
+
from_addr = addrinfo.to_sockaddr
|
468
616
|
tund_info = @tund_infos[ tund ]
|
469
|
-
dst_id = dst_info[ :id ]
|
470
617
|
|
471
|
-
if
|
472
|
-
#
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
data = [ 0, FIN1, dst_id, dst_info[ :biggest_pack_id ], dst_info[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
618
|
+
if from_addr != tund_info[ :tun_addr ] then
|
619
|
+
# 通常是光猫刷新ip和端口,但万一不是,为了避免脏数据注入,关闭tund
|
620
|
+
puts "p#{ Process.pid } #{ Time.new } from #{ addrinfo.inspect } not match tun addr #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
|
621
|
+
tund_info[ :changed_tun_addr ] = from_addr
|
622
|
+
set_tund_closing( tund )
|
623
|
+
return
|
478
624
|
end
|
479
625
|
|
480
|
-
|
481
|
-
|
626
|
+
pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
|
627
|
+
return if pack_id != 0
|
482
628
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
629
|
+
tund_info[ :last_recv_at ] = Time.new
|
630
|
+
ctl_num = data[ 8 ].unpack( 'C' ).first
|
631
|
+
|
632
|
+
case ctl_num
|
633
|
+
when A_NEW_SOURCE then
|
634
|
+
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
635
|
+
dst_id = tund_info[ :dst_ids ][ src_id ]
|
636
|
+
|
637
|
+
if dst_id then
|
638
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
639
|
+
return unless dst
|
640
|
+
|
641
|
+
if dst.closed? then
|
642
|
+
dst_id = 0
|
643
|
+
end
|
644
|
+
|
645
|
+
# puts "debug1 resend paired #{ dst_id }"
|
646
|
+
data2 = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
647
|
+
add_ctlmsg( tund, data2 )
|
648
|
+
return
|
649
|
+
end
|
650
|
+
|
651
|
+
data = data[ 17..-1 ]
|
652
|
+
domain_port = @custom.decode( data )
|
653
|
+
# puts "debug1 a new source #{ src_id } #{ domain_port }"
|
654
|
+
resolve_domain( tund, src_id, domain_port )
|
655
|
+
when TUN_FIN then
|
656
|
+
puts "p#{ Process.pid } #{ Time.new } recv tun fin"
|
657
|
+
set_tund_closing( tund )
|
658
|
+
end
|
493
659
|
end
|
494
660
|
|
495
661
|
##
|
496
|
-
#
|
662
|
+
# read tcpd
|
497
663
|
#
|
498
|
-
def
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
664
|
+
def read_tcpd( tcpd )
|
665
|
+
begin
|
666
|
+
streamd, addrinfo = tcpd.accept_nonblock
|
667
|
+
rescue IO::WaitReadable, Errno::EINTR
|
668
|
+
print 'r'
|
669
|
+
return
|
670
|
+
end
|
671
|
+
|
672
|
+
# puts "debug1 accept a streamd"
|
673
|
+
tcpd_info = @tcpd_infos[ tcpd ]
|
674
|
+
tund = tcpd_info[ :tund ]
|
675
|
+
|
676
|
+
@streamd_infos[ streamd ] = {
|
677
|
+
tund: tund, # 对应tund
|
678
|
+
dst: nil, # 对应dst
|
679
|
+
domain_port: nil, # dst的目的地和端口
|
680
|
+
wbuff: '', # 写前,写往近端stream
|
681
|
+
paused: false # 是否已暂停读
|
682
|
+
}
|
683
|
+
|
684
|
+
add_read( streamd, :streamd )
|
503
685
|
end
|
504
686
|
|
505
687
|
##
|
506
|
-
#
|
688
|
+
# read dst
|
507
689
|
#
|
508
|
-
def
|
509
|
-
|
690
|
+
def read_dst( dst )
|
691
|
+
begin
|
692
|
+
data = dst.read_nonblock( READ_SIZE )
|
693
|
+
rescue IO::WaitReadable, Errno::EINTR
|
694
|
+
print 'r'
|
695
|
+
return
|
696
|
+
rescue Exception => e
|
697
|
+
# puts "debug1 read dst #{ e.class }"
|
698
|
+
dst_info = close_read_dst( dst )
|
699
|
+
streamd = dst_info[ :streamd ]
|
700
|
+
set_streamd_closing_write( streamd ) if streamd
|
701
|
+
return
|
702
|
+
end
|
510
703
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
704
|
+
dst_info = @dst_infos[ dst ]
|
705
|
+
streamd = dst_info[ :streamd ]
|
706
|
+
|
707
|
+
if streamd then
|
708
|
+
unless streamd.closed? then
|
709
|
+
streamd_info = @streamd_infos[ streamd ]
|
710
|
+
data = @custom.encode( data )
|
711
|
+
# puts "debug2 add streamd.wbuff encoded #{ data.bytesize }"
|
712
|
+
streamd_info[ :wbuff ] << data
|
713
|
+
add_write( streamd )
|
714
|
+
|
715
|
+
if streamd_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
716
|
+
puts "p#{ Process.pid } #{ Time.new } pause dst #{ dst_info[ :domain_port ] }"
|
717
|
+
dst_info[ :paused ] = true
|
718
|
+
@reads.delete( dst )
|
719
|
+
end
|
720
|
+
end
|
721
|
+
else
|
722
|
+
dst_info[ :rbuff ] << data
|
515
723
|
|
516
|
-
if dst_info
|
517
|
-
|
724
|
+
if dst_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
|
725
|
+
# puts "debug1 dst.rbuff full"
|
726
|
+
set_dst_closing( dst )
|
518
727
|
end
|
519
728
|
end
|
520
729
|
end
|
521
730
|
|
522
731
|
##
|
523
|
-
#
|
732
|
+
# read streamd
|
524
733
|
#
|
525
|
-
def
|
526
|
-
|
527
|
-
|
734
|
+
def read_streamd( streamd )
|
735
|
+
begin
|
736
|
+
data = streamd.read_nonblock( READ_SIZE )
|
737
|
+
rescue IO::WaitReadable, Errno::EINTR
|
738
|
+
print 'r'
|
739
|
+
return
|
740
|
+
rescue Exception => e
|
741
|
+
# puts "debug1 read streamd #{ e.class }"
|
742
|
+
streamd_info = close_read_streamd( streamd )
|
743
|
+
dst = streamd_info[ :dst ]
|
744
|
+
set_dst_closing_write( dst ) if dst
|
745
|
+
return
|
746
|
+
end
|
528
747
|
|
529
|
-
|
748
|
+
streamd_info = @streamd_infos[ streamd ]
|
749
|
+
dst = streamd_info[ :dst ]
|
530
750
|
|
531
|
-
|
532
|
-
|
533
|
-
|
751
|
+
unless dst then
|
752
|
+
dst_id = data[ 0, 2 ].unpack( 'n' ).first
|
753
|
+
tund = streamd_info[ :tund ]
|
754
|
+
|
755
|
+
if tund.closed? then
|
756
|
+
set_streamd_closing( streamd )
|
757
|
+
return
|
534
758
|
end
|
535
759
|
|
536
|
-
|
537
|
-
|
538
|
-
end
|
760
|
+
tund_info = @tund_infos[ tund ]
|
761
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
539
762
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
@dotw.write( '.' )
|
545
|
-
end
|
763
|
+
unless dst then
|
764
|
+
set_streamd_closing( streamd )
|
765
|
+
return
|
766
|
+
end
|
546
767
|
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
dst_info = @dst_infos[ dst ]
|
768
|
+
# puts "debug1 set streamd.dst #{ dst_id }"
|
769
|
+
streamd_info[ :dst ] = dst
|
770
|
+
dst_info = @dst_infos[ dst ]
|
771
|
+
streamd_info[ :domain_port ] = dst_info[ :domain_port ]
|
552
772
|
|
553
|
-
|
554
|
-
|
555
|
-
|
773
|
+
unless dst_info[ :rbuff ].empty? then
|
774
|
+
# puts "debug1 encode and move dst.rbuff to streamd.wbuff"
|
775
|
+
streamd_info[ :wbuff ] << @custom.encode( dst_info[ :rbuff ] )
|
776
|
+
end
|
777
|
+
|
778
|
+
dst_info[ :streamd ] = streamd
|
779
|
+
data = data[ 2..-1 ]
|
780
|
+
|
781
|
+
return if data.empty?
|
556
782
|
end
|
557
783
|
|
558
|
-
|
784
|
+
unless dst.closed? then
|
785
|
+
dst_info = @dst_infos[ dst ]
|
786
|
+
data = @custom.decode( data )
|
787
|
+
# puts "debug2 add dst.wbuff decoded #{ data.bytesize }"
|
788
|
+
dst_info[ :wbuff ] << data
|
789
|
+
dst_info[ :last_recv_at ] = Time.new
|
790
|
+
add_write( dst )
|
559
791
|
|
560
|
-
|
561
|
-
|
562
|
-
|
792
|
+
if dst_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
793
|
+
puts "p#{ Process.pid } #{ Time.new } pause streamd #{ streamd_info[ :domain_port ] }"
|
794
|
+
streamd_info[ :paused ] = true
|
795
|
+
@reads.delete( streamd )
|
796
|
+
end
|
563
797
|
end
|
798
|
+
end
|
564
799
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
800
|
+
##
|
801
|
+
# write proxyd
|
802
|
+
#
|
803
|
+
def write_proxyd( proxyd )
|
804
|
+
# 发ctlmsg
|
805
|
+
while @proxyd_info[ :ctlmsgs ].any? do
|
806
|
+
data, to_addr = @proxyd_info[ :ctlmsgs ].first
|
807
|
+
sent = send_data( proxyd, data, to_addr )
|
808
|
+
|
809
|
+
if sent == :wait then
|
810
|
+
puts "p#{ Process.pid } #{ Time.new } wait proxyd send ctlmsg, left #{ @proxyd_info[ :ctlmsgs ].size }"
|
811
|
+
return
|
812
|
+
else
|
813
|
+
@proxyd_info[ :ctlmsgs ].shift
|
814
|
+
end
|
573
815
|
end
|
574
816
|
|
575
|
-
|
576
|
-
data = data[ written..-1 ]
|
577
|
-
dst_info[ :wbuff ] = data
|
578
|
-
dst_info[ :last_continue_at ] = Time.new
|
817
|
+
@writes.delete( proxyd )
|
579
818
|
end
|
580
819
|
|
581
820
|
##
|
@@ -584,8 +823,9 @@ module Girl
|
|
584
823
|
def write_tund( tund )
|
585
824
|
tund_info = @tund_infos[ tund ]
|
586
825
|
|
587
|
-
|
588
|
-
|
826
|
+
# 处理关闭
|
827
|
+
if tund_info[ :closing ] then
|
828
|
+
if tund_info[ :changed_tun_addr ] then
|
589
829
|
data = [ 0, IP_CHANGED ].pack( 'Q>C' )
|
590
830
|
send_data( tund, data, tund_info[ :changed_tun_addr ] )
|
591
831
|
end
|
@@ -594,319 +834,131 @@ module Girl
|
|
594
834
|
return
|
595
835
|
end
|
596
836
|
|
597
|
-
|
598
|
-
end
|
837
|
+
now = Time.new
|
599
838
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
839
|
+
# 发ctlmsg
|
840
|
+
while tund_info[ :ctlmsgs ].any? do
|
841
|
+
data = tund_info[ :ctlmsgs ].first
|
842
|
+
sent = send_data( tund, data, tund_info[ :tun_addr ] )
|
843
|
+
|
844
|
+
if sent == :fatal then
|
845
|
+
close_tund( tund )
|
846
|
+
return
|
847
|
+
elsif sent == :wait then
|
848
|
+
puts "p#{ Process.pid } #{ Time.new } wait tund #{ tund_info[ :port ] } send ctlmsg, left #{ tund_info[ :ctlmsgs ].size }"
|
849
|
+
return
|
850
|
+
end
|
851
|
+
|
852
|
+
tund_info[ :ctlmsgs ].shift
|
853
|
+
end
|
854
|
+
|
855
|
+
@writes.delete( tund )
|
605
856
|
end
|
606
857
|
|
607
858
|
##
|
608
|
-
#
|
859
|
+
# write dst
|
609
860
|
#
|
610
|
-
def
|
611
|
-
|
612
|
-
|
861
|
+
def write_dst( dst )
|
862
|
+
return if dst.closed?
|
863
|
+
dst_info = @dst_infos[ dst ]
|
864
|
+
streamd = dst_info[ :streamd ]
|
613
865
|
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
port = tund_info[ :port ]
|
618
|
-
data = [ 0, TUND_PORT, port ].pack( 'Q>Cn' )
|
619
|
-
puts "p#{ Process.pid } #{ Time.new } resend tund port #{ port }"
|
620
|
-
send_data( proxyd, data, from_addr )
|
621
|
-
return
|
622
|
-
end
|
866
|
+
# 处理关闭
|
867
|
+
if dst_info[ :closing ] then
|
868
|
+
close_dst( dst )
|
623
869
|
|
624
|
-
|
870
|
+
if streamd then
|
871
|
+
close_read_streamd( streamd )
|
872
|
+
set_streamd_closing_write( streamd )
|
873
|
+
end
|
625
874
|
|
626
|
-
if result != :success
|
627
|
-
puts "p#{ Process.pid } #{ Time.new } #{ result }"
|
628
875
|
return
|
629
876
|
end
|
630
877
|
|
631
|
-
|
632
|
-
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
633
|
-
port = tund.local_address.ip_port
|
634
|
-
|
635
|
-
@tunneling_tunds[ from_addr ] = tund
|
636
|
-
@tunds[ port ] = tund
|
637
|
-
@tund_infos[ tund ] = {
|
638
|
-
port: port, # 端口
|
639
|
-
wbuffs: [], # 写前 [ dst_id, pack_id, data ]
|
640
|
-
wmems: {}, # 写后 [ dst_id, pack_id ] => data
|
641
|
-
tun_addr: from_addr, # tun地址
|
642
|
-
dsts: {}, # dst_id => dst
|
643
|
-
dst_ids: {}, # src_id => dst_id
|
644
|
-
created_at: Time.new, # 创建时间
|
645
|
-
last_recv_at: nil, # 上一次收到流量的时间,过期关闭
|
646
|
-
is_closing: false, # 是否准备关闭
|
647
|
-
changed_tun_addr: nil # 记录到和tun addr不符的来源地址
|
648
|
-
}
|
878
|
+
data = dst_info[ :wbuff ]
|
649
879
|
|
650
|
-
|
880
|
+
# 写前为空,处理关闭写
|
881
|
+
if data.empty? then
|
882
|
+
if dst_info[ :closing_write ] then
|
883
|
+
close_write_dst( dst )
|
884
|
+
else
|
885
|
+
@writes.delete( dst )
|
886
|
+
end
|
651
887
|
|
652
|
-
|
653
|
-
|
654
|
-
send_data( proxyd, data, from_addr )
|
655
|
-
end
|
888
|
+
return
|
889
|
+
end
|
656
890
|
|
657
|
-
|
658
|
-
# read dst
|
659
|
-
#
|
660
|
-
def read_dst( dst )
|
891
|
+
# 写入
|
661
892
|
begin
|
662
|
-
|
663
|
-
rescue IO::
|
893
|
+
written = dst.write_nonblock( data )
|
894
|
+
rescue IO::WaitWritable, Errno::EINTR
|
895
|
+
print 'w'
|
664
896
|
return
|
665
897
|
rescue Exception => e
|
666
|
-
# puts "debug1
|
667
|
-
|
898
|
+
# puts "debug1 write dst #{ e.class }"
|
899
|
+
close_write_dst( dst )
|
900
|
+
close_read_streamd( streamd ) if streamd
|
668
901
|
return
|
669
902
|
end
|
670
903
|
|
671
|
-
|
904
|
+
# puts "debug2 written dst #{ written }"
|
905
|
+
data = data[ written..-1 ]
|
906
|
+
dst_info[ :wbuff ] = data
|
672
907
|
end
|
673
908
|
|
674
909
|
##
|
675
|
-
#
|
910
|
+
# write streamd
|
676
911
|
#
|
677
|
-
def
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
912
|
+
def write_streamd( streamd )
|
913
|
+
return if streamd.closed?
|
914
|
+
streamd_info = @streamd_infos[ streamd ]
|
915
|
+
dst = streamd_info[ :dst ]
|
916
|
+
|
917
|
+
# 处理关闭
|
918
|
+
if streamd_info[ :closing ] then
|
919
|
+
close_streamd( streamd )
|
920
|
+
|
921
|
+
if dst then
|
922
|
+
close_read_dst( dst )
|
923
|
+
set_dst_closing_write( dst )
|
924
|
+
end
|
682
925
|
|
683
|
-
if from_addr != tund_info[ :tun_addr ]
|
684
|
-
# 通常是光猫刷新ip(端口也会变),但万一不是,为了避免脏数据注入,关闭tund
|
685
|
-
puts "p#{ Process.pid } #{ Time.new } from #{ addrinfo.inspect } not match tun addr #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
|
686
|
-
tund_info[ :changed_tun_addr ] = from_addr
|
687
|
-
set_is_closing( tund )
|
688
926
|
return
|
689
927
|
end
|
690
928
|
|
691
|
-
|
692
|
-
pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
|
693
|
-
|
694
|
-
if pack_id == 0
|
695
|
-
ctl_num = data[ 8 ].unpack( 'C' ).first
|
696
|
-
|
697
|
-
case ctl_num
|
698
|
-
when A_NEW_SOURCE
|
699
|
-
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
700
|
-
dst_id = tund_info[ :dst_ids ][ src_id ]
|
701
|
-
|
702
|
-
if dst_id
|
703
|
-
dst = tund_info[ :dsts ][ dst_id ]
|
704
|
-
return unless dst
|
705
|
-
|
706
|
-
if dst.closed?
|
707
|
-
dst_id = 0
|
708
|
-
end
|
709
|
-
|
710
|
-
# puts "debug1 resend paired #{ dst_id }"
|
711
|
-
data2 = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
712
|
-
send_data( tund, data2, tund_info[ :tun_addr ] )
|
713
|
-
return
|
714
|
-
end
|
715
|
-
|
716
|
-
data = data[ 17..-1 ]
|
717
|
-
domain_port = @custom.decode( data )
|
718
|
-
# puts "debug1 a new source #{ src_id } #{ domain_port }"
|
719
|
-
resolve_domain( tund, src_id, domain_port )
|
720
|
-
when SOURCE_STATUS
|
721
|
-
src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
929
|
+
data = streamd_info[ :wbuff ]
|
722
930
|
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
dst_info = @dst_infos[ dst ]
|
730
|
-
return unless dst_info
|
731
|
-
|
732
|
-
# puts "debug2 got source status #{ Time.new }"
|
733
|
-
|
734
|
-
# 消写后
|
735
|
-
release_wmems( tund_info, dst_info, continue_dst_pack_id )
|
736
|
-
|
737
|
-
# 发miss
|
738
|
-
if !dst.closed? && ( dst_info[ :continue_src_pack_id ] < relay_src_pack_id )
|
739
|
-
ranges = []
|
740
|
-
ignored = false
|
741
|
-
curr_pack_id = dst_info[ :continue_src_pack_id ] + 1
|
742
|
-
|
743
|
-
dst_info[ :pieces ].keys.sort.each do | pack_id |
|
744
|
-
if pack_id > curr_pack_id
|
745
|
-
ranges << [ curr_pack_id, pack_id - 1 ]
|
746
|
-
|
747
|
-
if ranges.size >= MISS_RANGE_LIMIT
|
748
|
-
puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
|
749
|
-
ignored = true
|
750
|
-
break
|
751
|
-
end
|
752
|
-
end
|
753
|
-
|
754
|
-
curr_pack_id = pack_id + 1
|
755
|
-
end
|
756
|
-
|
757
|
-
if !ignored && ( curr_pack_id <= relay_src_pack_id )
|
758
|
-
ranges << [ curr_pack_id, relay_src_pack_id ]
|
759
|
-
end
|
760
|
-
|
761
|
-
# puts "debug1 continue/relay #{ dst_info[ :continue_src_pack_id ] }/#{ relay_src_pack_id } send MISS #{ ranges.size }"
|
762
|
-
idx = 0
|
763
|
-
ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
|
764
|
-
|
765
|
-
while idx < ranges.size
|
766
|
-
chunk = ranges[ idx, MULTI_MISS_SIZE ].join
|
767
|
-
data2 = [ [ 0, MULTI_MISS, src_id ].pack( 'Q>CQ>' ), chunk ].join
|
768
|
-
send_data( tund, data2, tund_info[ :tun_addr ] )
|
769
|
-
idx += MULTI_MISS_SIZE
|
770
|
-
end
|
771
|
-
end
|
772
|
-
when MULTI_MISS
|
773
|
-
dst_id, *ranges = data[ 9..-1 ].unpack( 'nQ>*' )
|
774
|
-
|
775
|
-
dst = tund_info[ :dsts ][ dst_id ]
|
776
|
-
return unless dst
|
777
|
-
|
778
|
-
dst_info = @dst_infos[ dst ]
|
779
|
-
return unless dst_info
|
780
|
-
|
781
|
-
return if ranges.empty? || ( ranges.size % 2 != 0 )
|
782
|
-
|
783
|
-
# puts "debug1 got multi miss #{ dst_id } #{ ranges.size }"
|
784
|
-
|
785
|
-
idx = 0
|
786
|
-
|
787
|
-
while idx < ranges.size
|
788
|
-
pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
|
789
|
-
|
790
|
-
( pack_id_begin..pack_id_end ).each do | pack_id |
|
791
|
-
send_at = dst_info[ :send_ats ][ pack_id ]
|
792
|
-
|
793
|
-
if send_at
|
794
|
-
break if now - send_at < CHECK_STATUS_INTERVAL
|
795
|
-
data2 = tund_info[ :wmems ][ [ dst_id, pack_id ] ]
|
796
|
-
|
797
|
-
if data2
|
798
|
-
if send_data( tund, data2, tund_info[ :tun_addr ] )
|
799
|
-
dst_info[ :last_continue_at ] = now
|
800
|
-
end
|
801
|
-
end
|
802
|
-
end
|
803
|
-
end
|
804
|
-
|
805
|
-
idx += 2
|
806
|
-
end
|
807
|
-
when MISS
|
808
|
-
dst_id, pack_id_begin, pack_id_end = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
809
|
-
|
810
|
-
dst = tund_info[ :dsts ][ dst_id ]
|
811
|
-
return unless dst
|
812
|
-
|
813
|
-
dst_info = @dst_infos[ dst ]
|
814
|
-
return unless dst_info
|
815
|
-
|
816
|
-
( pack_id_begin..pack_id_end ).each do | pack_id |
|
817
|
-
send_at = dst_info[ :send_ats ][ pack_id ]
|
818
|
-
|
819
|
-
if send_at
|
820
|
-
break if now - send_at < CHECK_STATUS_INTERVAL
|
821
|
-
data2 = tund_info[ :wmems ][ [ dst_id, pack_id ] ]
|
822
|
-
|
823
|
-
if data2
|
824
|
-
if send_data( tund, data2, tund_info[ :tun_addr ] )
|
825
|
-
dst_info[ :last_continue_at ] = now
|
826
|
-
end
|
827
|
-
end
|
828
|
-
end
|
829
|
-
end
|
830
|
-
when FIN1
|
831
|
-
src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
832
|
-
|
833
|
-
dst_id = tund_info[ :dst_ids ][ src_id ]
|
834
|
-
return unless dst_id
|
835
|
-
|
836
|
-
dst = tund_info[ :dsts ][ dst_id ]
|
837
|
-
return unless dst
|
838
|
-
|
839
|
-
dst_info = @dst_infos[ dst ]
|
840
|
-
return unless dst_info
|
841
|
-
|
842
|
-
# puts "debug1 got fin1 #{ src_id } biggest src pack #{ biggest_src_pack_id } completed dst pack #{ continue_dst_pack_id }"
|
843
|
-
dst_info[ :is_src_closed ] = true
|
844
|
-
dst_info[ :biggest_src_pack_id ] = biggest_src_pack_id
|
845
|
-
release_wmems( tund_info, dst_info, continue_dst_pack_id )
|
846
|
-
|
847
|
-
if biggest_src_pack_id == dst_info[ :continue_src_pack_id ]
|
848
|
-
# puts "debug1 4-1. tund recv fin1 -> all traffic received ? -> close dst after write"
|
849
|
-
set_is_closing( dst )
|
850
|
-
end
|
851
|
-
when FIN2
|
852
|
-
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
853
|
-
|
854
|
-
dst_id = tund_info[ :dst_ids ][ src_id ]
|
855
|
-
return unless dst_id
|
856
|
-
|
857
|
-
# puts "debug1 3-2. tund recv fin2 -> del dst ext"
|
858
|
-
del_dst_ext( tund_info, dst_id )
|
859
|
-
when TUN_FIN
|
860
|
-
puts "p#{ Process.pid } #{ Time.new } recv tun fin"
|
861
|
-
set_is_closing( tund )
|
931
|
+
# 写前为空,处理关闭写
|
932
|
+
if data.empty? then
|
933
|
+
if streamd_info[ :closing_write ] then
|
934
|
+
close_write_streamd( streamd )
|
935
|
+
else
|
936
|
+
@writes.delete( streamd )
|
862
937
|
end
|
863
938
|
|
864
939
|
return
|
865
940
|
end
|
866
941
|
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
return if ( pack_id <= dst_info[ :continue_src_pack_id ] ) || dst_info[ :pieces ].include?( pack_id )
|
879
|
-
|
880
|
-
data = data[ 16..-1 ]
|
881
|
-
# puts "debug2 got pack #{ pack_id }"
|
882
|
-
|
883
|
-
if pack_id <= CONFUSE_UNTIL
|
884
|
-
# puts "debug2 #{ data.inspect }"
|
885
|
-
data = @custom.decode( data )
|
886
|
-
# puts "debug1 decoded pack #{ pack_id }"
|
942
|
+
# 写入
|
943
|
+
begin
|
944
|
+
written = streamd.write_nonblock( data )
|
945
|
+
rescue IO::WaitWritable, Errno::EINTR
|
946
|
+
print 'w'
|
947
|
+
return
|
948
|
+
rescue Exception => e
|
949
|
+
# puts "debug1 write streamd #{ e.class }"
|
950
|
+
close_write_streamd( streamd )
|
951
|
+
close_read_dst( dst ) if dst
|
952
|
+
return
|
887
953
|
end
|
888
954
|
|
889
|
-
#
|
890
|
-
|
891
|
-
|
892
|
-
data << dst_info[ :pieces ].delete( pack_id + 1 )
|
893
|
-
pack_id += 1
|
894
|
-
end
|
895
|
-
|
896
|
-
dst_info[ :continue_src_pack_id ] = pack_id
|
897
|
-
dst_info[ :last_continue_at ] = now
|
898
|
-
dst_info[ :wbuff ] << data
|
899
|
-
add_write( dst )
|
900
|
-
# puts "debug2 update continue src pack #{ pack_id }"
|
955
|
+
# puts "debug2 written streamd #{ written }"
|
956
|
+
data = data[ written..-1 ]
|
957
|
+
streamd_info[ :wbuff ] = data
|
901
958
|
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
set_is_closing( dst )
|
906
|
-
end
|
907
|
-
else
|
908
|
-
dst_info[ :pieces ][ pack_id ] = data
|
909
|
-
dst_info[ :last_continue_at ] = now
|
959
|
+
if dst && !dst.closed? then
|
960
|
+
dst_info = @dst_infos[ dst ]
|
961
|
+
dst_info[ :last_sent_at ] = Time.new
|
910
962
|
end
|
911
963
|
end
|
912
964
|
|