girl 0.83.0 → 0.87.1
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/girl.gemspec +1 -1
- data/lib/girl/head.rb +29 -28
- data/lib/girl/proxy.rb +25 -34
- data/lib/girl/proxy_worker.rb +364 -471
- data/lib/girl/proxyd.rb +23 -24
- data/lib/girl/proxyd_worker.rb +348 -422
- data/lib/girl/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff8fb468e18a12b716f36ad839823c2725a590cc162f896ed43b199297262c01
|
4
|
+
data.tar.gz: 657e28910c1e4303896b7f728760bedf2ba4d23dd1ed021b325cc6545b0050ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c29c0ee44eacc07c1deea70df4433083c45fde0f932c540831a52c0c39e539401b79cd3249190563db3dfc4f33a8b7ac336f95420038ed612abdbe5e3d8a42d
|
7
|
+
data.tar.gz: 72c4374a80e9eb93139cff701436536e99d8843c80a866494d42aee10ff64619b82e4d19b8a0660f44bd1a3b516657221e60d72227a005f96c8410a729eb919e
|
data/girl.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ['qqtakafan@gmail.com']
|
11
11
|
|
12
12
|
spec.summary = %q{妹子}
|
13
|
-
spec.description = %q{
|
13
|
+
spec.description = %q{escape evil.}
|
14
14
|
spec.homepage = 'https://github.com/takafan/girl'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
data/lib/girl/head.rb
CHANGED
@@ -1,32 +1,33 @@
|
|
1
1
|
module Girl
|
2
|
-
PACK_SIZE
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
CONFUSE_UNTIL
|
14
|
-
RESOLV_CACHE_EXPIRE
|
15
|
-
TUND_PORT
|
16
|
-
HEARTBEAT
|
17
|
-
A_NEW_SOURCE
|
18
|
-
PAIRED
|
19
|
-
DEST_STATUS
|
20
|
-
SOURCE_STATUS
|
21
|
-
MISS
|
22
|
-
FIN1
|
23
|
-
GOT_FIN1
|
24
|
-
FIN2
|
25
|
-
GOT_FIN2
|
26
|
-
TUND_FIN
|
27
|
-
TUN_FIN
|
28
|
-
IP_CHANGED
|
29
|
-
|
2
|
+
PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
|
3
|
+
READ_SIZE = PACK_SIZE * 100 # 一次读多少
|
4
|
+
WMEMS_LIMIT = 100_000 # 写后上限,超过上限暂停读src/dst
|
5
|
+
RESUME_BELOW = 50_000 # 降到多少以下恢复读
|
6
|
+
EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
|
7
|
+
EXPIRE_AFTER = 300 # 多久没有新流量,过期
|
8
|
+
CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
|
9
|
+
CHECK_STATUS_INTERVAL = 0.5 # 发送状态间隔
|
10
|
+
SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
|
11
|
+
MULTI_MISS_SIZE = 80 # 几个miss段打一个包
|
12
|
+
MISS_RANGE_LIMIT = MULTI_MISS_SIZE * 10 # miss段上限,达到上限忽略要后面的段
|
13
|
+
CONFUSE_UNTIL = 5 # 混淆前几个包
|
14
|
+
RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
|
15
|
+
TUND_PORT = 1
|
16
|
+
HEARTBEAT = 2
|
17
|
+
A_NEW_SOURCE = 3
|
18
|
+
PAIRED = 4
|
19
|
+
DEST_STATUS = 5
|
20
|
+
SOURCE_STATUS = 6
|
21
|
+
MISS = 7
|
22
|
+
FIN1 = 8
|
23
|
+
GOT_FIN1 = 9
|
24
|
+
FIN2 = 10
|
25
|
+
GOT_FIN2 = 11
|
26
|
+
TUND_FIN = 12
|
27
|
+
TUN_FIN = 13
|
28
|
+
IP_CHANGED = 14
|
29
|
+
MULTI_MISS = 15
|
30
|
+
HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
|
30
31
|
# https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
31
32
|
RESERVED_ROUTE = <<EOF
|
32
33
|
0.0.0.0/8
|
data/lib/girl/proxy.rb
CHANGED
@@ -36,6 +36,7 @@ require 'socket'
|
|
36
36
|
# 12 tund fin
|
37
37
|
# 13 tun fin
|
38
38
|
# 14 tun ip changed
|
39
|
+
# 15 multi miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end -> Q>*
|
39
40
|
#
|
40
41
|
# Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
|
41
42
|
#
|
@@ -74,8 +75,6 @@ module Girl
|
|
74
75
|
# "proxyd_port": 6060, // 代理服务,远端端口
|
75
76
|
# "direct_path": "girl.direct.txt", // 直连ip段
|
76
77
|
# "remote_path": "girl.remote.txt", // 交给远端解析的域名列表
|
77
|
-
# "proxy_tmp_dir": "/tmp/girl.proxy", // 近端缓存根路径
|
78
|
-
# "proxyd_tmp_dir": "/tmp/girl.proxyd", // 远端缓存根路径
|
79
78
|
# "im": "girl", // 标识,用来识别近端
|
80
79
|
# "worker_count": 4 // 子进程数,默认取cpu个数
|
81
80
|
# }
|
@@ -85,7 +84,6 @@ module Girl
|
|
85
84
|
proxyd_port = conf[ :proxyd_port ]
|
86
85
|
direct_path = conf[ :direct_path ]
|
87
86
|
remote_path = conf[ :remote_path ]
|
88
|
-
proxy_tmp_dir = conf[ :proxy_tmp_dir ]
|
89
87
|
im = conf[ :im ]
|
90
88
|
worker_count = conf[ :worker_count ]
|
91
89
|
|
@@ -121,32 +119,6 @@ module Girl
|
|
121
119
|
remotes = IO.binread( remote_path ).split( "\n" ).map { | line | line.strip }
|
122
120
|
end
|
123
121
|
|
124
|
-
unless proxy_tmp_dir
|
125
|
-
proxy_tmp_dir = '/tmp/girl.proxy'
|
126
|
-
end
|
127
|
-
|
128
|
-
unless File.exist?( proxy_tmp_dir )
|
129
|
-
Dir.mkdir( proxy_tmp_dir )
|
130
|
-
end
|
131
|
-
|
132
|
-
src_chunk_dir = File.join( proxy_tmp_dir, 'src.chunk' )
|
133
|
-
|
134
|
-
unless Dir.exist?( src_chunk_dir )
|
135
|
-
Dir.mkdir( src_chunk_dir )
|
136
|
-
end
|
137
|
-
|
138
|
-
dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
|
139
|
-
|
140
|
-
unless Dir.exist?( dst_chunk_dir )
|
141
|
-
Dir.mkdir( dst_chunk_dir )
|
142
|
-
end
|
143
|
-
|
144
|
-
tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
|
145
|
-
|
146
|
-
unless Dir.exist?( tun_chunk_dir )
|
147
|
-
Dir.mkdir( tun_chunk_dir )
|
148
|
-
end
|
149
|
-
|
150
122
|
unless im
|
151
123
|
im = 'girl'
|
152
124
|
end
|
@@ -164,12 +136,31 @@ module Girl
|
|
164
136
|
puts "proxyd port #{ proxyd_port }"
|
165
137
|
puts "#{ direct_path } #{ directs.size } directs"
|
166
138
|
puts "#{ remote_path } #{ remotes.size } remotes"
|
167
|
-
puts "src chunk dir #{ src_chunk_dir }"
|
168
|
-
puts "dst chunk dir #{ dst_chunk_dir }"
|
169
|
-
puts "tun chunk dir #{ tun_chunk_dir }"
|
170
139
|
puts "im #{ im }"
|
171
140
|
puts "worker count #{ worker_count }"
|
172
141
|
|
142
|
+
names = %w[
|
143
|
+
PACK_SIZE
|
144
|
+
READ_SIZE
|
145
|
+
WMEMS_LIMIT
|
146
|
+
RESUME_BELOW
|
147
|
+
EXPIRE_NEW
|
148
|
+
EXPIRE_AFTER
|
149
|
+
CHECK_EXPIRE_INTERVAL
|
150
|
+
CHECK_STATUS_INTERVAL
|
151
|
+
SEND_STATUS_UNTIL
|
152
|
+
MULTI_MISS_SIZE
|
153
|
+
MISS_RANGE_LIMIT
|
154
|
+
CONFUSE_UNTIL
|
155
|
+
RESOLV_CACHE_EXPIRE
|
156
|
+
]
|
157
|
+
|
158
|
+
len = names.map{ | name | name.size }.max
|
159
|
+
|
160
|
+
names.each do | name |
|
161
|
+
puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
|
162
|
+
end
|
163
|
+
|
173
164
|
if RUBY_PLATFORM.include?( 'linux' )
|
174
165
|
$0 = title
|
175
166
|
workers = []
|
@@ -177,7 +168,7 @@ module Girl
|
|
177
168
|
worker_count.times do | i |
|
178
169
|
workers << fork do
|
179
170
|
$0 = 'girl proxy worker'
|
180
|
-
worker = Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes,
|
171
|
+
worker = Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, im )
|
181
172
|
|
182
173
|
Signal.trap( :TERM ) do
|
183
174
|
puts "w#{ i } exit"
|
@@ -201,7 +192,7 @@ module Girl
|
|
201
192
|
|
202
193
|
Process.waitall
|
203
194
|
else
|
204
|
-
Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes,
|
195
|
+
Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
|
205
196
|
end
|
206
197
|
end
|
207
198
|
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -4,18 +4,16 @@ module Girl
|
|
4
4
|
##
|
5
5
|
# initialize
|
6
6
|
#
|
7
|
-
def initialize( proxy_port, proxyd_host, proxyd_port, directs, remotes,
|
7
|
+
def initialize( proxy_port, proxyd_host, proxyd_port, directs, remotes, im )
|
8
8
|
@proxyd_host = proxyd_host
|
9
9
|
@proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
|
10
10
|
@directs = directs
|
11
11
|
@remotes = remotes
|
12
|
-
@src_chunk_dir = src_chunk_dir
|
13
|
-
@dst_chunk_dir = dst_chunk_dir
|
14
|
-
@tun_chunk_dir = tun_chunk_dir
|
15
12
|
@custom = Girl::ProxyCustom.new( im )
|
16
13
|
@mutex = Mutex.new
|
17
14
|
@reads = []
|
18
15
|
@writes = []
|
16
|
+
@pause_srcs = []
|
19
17
|
@roles = {} # sock => :dotr / :proxy / :src / :dst / :tun
|
20
18
|
@src_infos = {} # src => {}
|
21
19
|
@dst_infos = {} # dst => {}
|
@@ -106,20 +104,31 @@ module Girl
|
|
106
104
|
if is_expired
|
107
105
|
puts "p#{ Process.pid } #{ Time.new } expire tun"
|
108
106
|
set_is_closing( @tun )
|
107
|
+
need_trigger = true
|
109
108
|
else
|
110
109
|
data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
|
111
110
|
# puts "debug1 #{ Time.new } heartbeat"
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
111
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
112
|
+
del_src_ids = []
|
113
|
+
|
114
|
+
@tun_info[ :srcs ].each do | src_id, src |
|
115
|
+
if src.closed?
|
116
|
+
src_info = @src_infos[ src ]
|
117
|
+
|
118
|
+
if src_info && ( now - src_info[ :last_continue_at ] > EXPIRE_AFTER )
|
119
|
+
puts "p#{ Process.pid } #{ Time.new } expire src ext #{ src_info[ :destination_domain ] }"
|
120
|
+
@tun_info[ :wmems ].delete_if { | src_id_and_pack_id, _ | src_id_and_pack_id.first == src_id }
|
121
|
+
@tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
|
122
|
+
@src_infos.delete( src )
|
123
|
+
del_src_ids << src_id
|
124
|
+
end
|
118
125
|
end
|
119
126
|
end
|
120
|
-
end
|
121
127
|
|
122
|
-
|
128
|
+
if del_src_ids.any?
|
129
|
+
@tun_info[ :srcs ].delete_if { | src_id, _ | del_src_ids.include?( src_id ) }
|
130
|
+
end
|
131
|
+
end
|
123
132
|
end
|
124
133
|
|
125
134
|
@src_infos.each do | src, src_info |
|
@@ -152,32 +161,34 @@ module Girl
|
|
152
161
|
def loop_check_status
|
153
162
|
Thread.new do
|
154
163
|
loop do
|
155
|
-
sleep
|
164
|
+
sleep CHECK_STATUS_INTERVAL
|
156
165
|
|
157
166
|
@mutex.synchronize do
|
158
167
|
if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
|
159
|
-
|
160
|
-
|
161
|
-
if @tun_info[ :src_exts ].any?
|
168
|
+
if @tun_info[ :srcs ].any?
|
162
169
|
now = Time.new
|
163
170
|
|
164
|
-
@tun_info[ :
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
171
|
+
@tun_info[ :srcs ].each do | src_id, src |
|
172
|
+
src_info = @src_infos[ src ]
|
173
|
+
|
174
|
+
if src_info && src_info[ :dst_id ] && ( now - src_info[ :last_continue_at ] < SEND_STATUS_UNTIL )
|
175
|
+
data = [ 0, SOURCE_STATUS, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
|
176
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
169
177
|
end
|
170
178
|
end
|
171
179
|
end
|
172
180
|
|
173
|
-
if @
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
181
|
+
if @pause_srcs.any? && ( @tun_info[ :wmems ].size < RESUME_BELOW )
|
182
|
+
@pause_srcs.each do | src |
|
183
|
+
src_info = @src_infos[ src ]
|
184
|
+
|
185
|
+
if src_info
|
186
|
+
puts "p#{ Process.pid } #{ Time.new } resume src #{ src_info[ :destination_domain ] }"
|
187
|
+
add_read( src )
|
188
|
+
end
|
189
|
+
end
|
179
190
|
|
180
|
-
|
191
|
+
@pause_srcs.clear
|
181
192
|
next_tick
|
182
193
|
end
|
183
194
|
end
|
@@ -187,23 +198,60 @@ module Girl
|
|
187
198
|
end
|
188
199
|
|
189
200
|
##
|
190
|
-
# loop send
|
201
|
+
# loop send hello
|
191
202
|
#
|
192
|
-
def
|
203
|
+
def loop_send_hello
|
204
|
+
data = @custom.hello
|
205
|
+
|
193
206
|
Thread.new do
|
194
|
-
EXPIRE_NEW.times do
|
195
|
-
if
|
196
|
-
# puts "debug1 break loop send
|
207
|
+
EXPIRE_NEW.times do | i |
|
208
|
+
if @tun.closed? || @tun_info[ :tund_addr ]
|
209
|
+
# puts "debug1 break loop send hello"
|
197
210
|
break
|
198
211
|
end
|
199
212
|
|
200
213
|
@mutex.synchronize do
|
201
|
-
|
202
|
-
|
203
|
-
|
214
|
+
msg = i >= 1 ? "resend hello #{ i }" : "hello i'm tun"
|
215
|
+
puts "p#{ Process.pid } #{ Time.new } #{ msg }"
|
216
|
+
# puts "debug1 #{ data.inspect }"
|
217
|
+
|
218
|
+
send_data( @tun, data, @proxyd_addr )
|
204
219
|
end
|
205
220
|
|
206
|
-
sleep
|
221
|
+
sleep CHECK_STATUS_INTERVAL
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
##
|
227
|
+
# loop send a new source
|
228
|
+
#
|
229
|
+
def loop_send_a_new_source( src )
|
230
|
+
src_info = @src_infos[ src ]
|
231
|
+
|
232
|
+
if src_info && @tun_info[ :tund_addr ]
|
233
|
+
destination_domain = src_info[ :destination_domain ]
|
234
|
+
destination_port = src_info[ :destination_port ]
|
235
|
+
domain_port = [ destination_domain, destination_port ].join( ':' )
|
236
|
+
data = [ [ 0, A_NEW_SOURCE, src_info[ :id ] ].pack( 'Q>CQ>' ), @custom.encode( domain_port ) ].join
|
237
|
+
|
238
|
+
Thread.new do
|
239
|
+
EXPIRE_NEW.times do | i |
|
240
|
+
if src.closed? || src_info[ :dst_id ]
|
241
|
+
# puts "debug1 break loop send a new source #{ src_info[ :dst_port ] }"
|
242
|
+
break
|
243
|
+
end
|
244
|
+
|
245
|
+
@mutex.synchronize do
|
246
|
+
if i >= 1
|
247
|
+
puts "p#{ Process.pid } #{ Time.new } resend a new source #{ domain_port } #{ i }"
|
248
|
+
end
|
249
|
+
|
250
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
251
|
+
end
|
252
|
+
|
253
|
+
sleep CHECK_STATUS_INTERVAL
|
254
|
+
end
|
207
255
|
end
|
208
256
|
end
|
209
257
|
end
|
@@ -304,17 +352,12 @@ module Girl
|
|
304
352
|
port = tun.local_address.ip_port
|
305
353
|
tun_info = {
|
306
354
|
port: port, # 端口
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
caches: [], # 块读出缓存 [ src_id, pack_id, data ]
|
311
|
-
chunks: [], # 块队列 filename
|
312
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
355
|
+
pending_sources: [], # 还没配上tund,暂存的src
|
356
|
+
wbuffs: [], # 写前 [ src_id, pack_id, data ]
|
357
|
+
wmems: {}, # 写后 [ src_id, pack_id ] => data
|
313
358
|
tund_addr: nil, # tund地址
|
314
|
-
|
315
|
-
src_ids: {}, #
|
316
|
-
paused: false, # 是否暂停写
|
317
|
-
resendings: [], # 重传队列 [ src_id, pack_id ]
|
359
|
+
srcs: {}, # src_id => src
|
360
|
+
src_ids: {}, # dst_id => src_id
|
318
361
|
created_at: Time.new, # 创建时间
|
319
362
|
last_recv_at: nil, # 上一次收到流量的时间,过期关闭
|
320
363
|
is_closing: false # 是否准备关闭
|
@@ -324,10 +367,7 @@ module Girl
|
|
324
367
|
@tun_info = tun_info
|
325
368
|
|
326
369
|
add_read( tun, :tun )
|
327
|
-
|
328
|
-
puts "p#{ Process.pid } #{ Time.new } hello i'm tun"
|
329
|
-
# puts "debug1 #{ data.inspect }"
|
330
|
-
add_tun_ctlmsg( data, @proxyd_addr )
|
370
|
+
loop_send_hello
|
331
371
|
end
|
332
372
|
|
333
373
|
##
|
@@ -360,9 +400,6 @@ module Girl
|
|
360
400
|
src: src, # 对应src
|
361
401
|
domain: domain, # 域名
|
362
402
|
wbuff: '', # 写前
|
363
|
-
cache: '', # 块读出缓存
|
364
|
-
chunks: [], # 块队列,写前达到块大小时结一个块 filename
|
365
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
366
403
|
last_continue_at: Time.new, # 上一次发生流量的时间
|
367
404
|
is_closing: false # 是否准备关闭
|
368
405
|
}
|
@@ -376,11 +413,8 @@ module Girl
|
|
376
413
|
# puts "debug1 add src wbuff http ok"
|
377
414
|
add_src_wbuff( src, HTTP_OK )
|
378
415
|
else
|
379
|
-
# puts "debug1 add src
|
380
|
-
|
381
|
-
src_info[ :rbuffs ].each do | _, data |
|
382
|
-
add_dst_wbuff( dst, data )
|
383
|
-
end
|
416
|
+
# puts "debug1 add src rbuff to dst wbuff"
|
417
|
+
add_dst_wbuff( dst, src_info[ :rbuff ] )
|
384
418
|
end
|
385
419
|
elsif src_info[ :proxy_proto ] == :socks5
|
386
420
|
add_src_wbuff_socks5_conn_reply( src )
|
@@ -396,31 +430,15 @@ module Girl
|
|
396
430
|
end
|
397
431
|
|
398
432
|
src_info = @src_infos[ src ]
|
399
|
-
src_id = src_info[ :id ]
|
400
|
-
destination_port = src_info[ :destination_port ]
|
401
|
-
destination_domain = src_info[ :destination_domain ]
|
402
|
-
|
403
|
-
src_ext = {
|
404
|
-
src: src, # src
|
405
|
-
dst_port: nil, # 远端dst端口
|
406
|
-
destination_domain: destination_domain, # 目的地域名
|
407
|
-
wmems: {}, # 写后 pack_id => data
|
408
|
-
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
409
|
-
relay_pack_id: 0, # 转发到几
|
410
|
-
continue_dst_pack_id: 0, # 收到几
|
411
|
-
pieces: {}, # 跳号包 dst_pack_id => data
|
412
|
-
is_dst_closed: false, # dst是否已关闭
|
413
|
-
biggest_dst_pack_id: 0, # dst最大包号码
|
414
|
-
completed_pack_id: 0, # 完成到几(对面收到几)
|
415
|
-
last_continue_at: Time.new # 上一次发生流量的时间
|
416
|
-
}
|
417
|
-
|
418
|
-
@tun_info[ :src_exts ][ src_id ] = src_ext
|
419
433
|
src_info[ :proxy_type ] = :tunnel
|
434
|
+
src_id = src_info[ :id ]
|
435
|
+
@tun_info[ :srcs ][ src_id ] = src
|
420
436
|
|
421
|
-
|
422
|
-
|
423
|
-
|
437
|
+
if @tun_info[ :tund_addr ]
|
438
|
+
loop_send_a_new_source( src )
|
439
|
+
else
|
440
|
+
@tun_info[ :pending_sources ] << src
|
441
|
+
end
|
424
442
|
end
|
425
443
|
|
426
444
|
##
|
@@ -459,75 +477,12 @@ module Girl
|
|
459
477
|
[ data, domain_and_port ]
|
460
478
|
end
|
461
479
|
|
462
|
-
##
|
463
|
-
# add tun ctlmsg
|
464
|
-
#
|
465
|
-
def add_tun_ctlmsg( data, to_addr = nil )
|
466
|
-
unless to_addr
|
467
|
-
to_addr = @tun_info[ :tund_addr ]
|
468
|
-
end
|
469
|
-
|
470
|
-
if to_addr
|
471
|
-
@tun_info[ :ctlmsgs ] << [ to_addr, data ]
|
472
|
-
add_write( @tun )
|
473
|
-
else
|
474
|
-
@tun_info[ :ctlmsg_rbuffs ] << data
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
##
|
479
|
-
# add tun wbuff
|
480
|
-
#
|
481
|
-
def add_tun_wbuff( src_id, pack_id, data )
|
482
|
-
@tun_info[ :wbuffs ] << [ src_id, pack_id, data ]
|
483
|
-
|
484
|
-
if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
|
485
|
-
spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
|
486
|
-
filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
|
487
|
-
chunk_path = File.join( @tun_chunk_dir, filename )
|
488
|
-
datas = @tun_info[ :wbuffs ].map{ | _src_id, _pack_id, _data | [ [ _src_id, _pack_id, _data.bytesize ].pack( 'Q>Q>n' ), _data ].join }
|
489
|
-
|
490
|
-
begin
|
491
|
-
IO.binwrite( chunk_path, datas.join )
|
492
|
-
rescue Errno::ENOSPC => e
|
493
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tun"
|
494
|
-
set_is_closing( @tun )
|
495
|
-
return
|
496
|
-
end
|
497
|
-
|
498
|
-
@tun_info[ :chunks ] << filename
|
499
|
-
@tun_info[ :spring ] = spring
|
500
|
-
@tun_info[ :wbuffs ].clear
|
501
|
-
end
|
502
|
-
|
503
|
-
add_write( @tun )
|
504
|
-
end
|
505
|
-
|
506
480
|
##
|
507
481
|
# add src wbuff
|
508
482
|
#
|
509
483
|
def add_src_wbuff( src, data )
|
510
484
|
src_info = @src_infos[ src ]
|
511
485
|
src_info[ :wbuff ] << data
|
512
|
-
|
513
|
-
if src_info[ :wbuff ].bytesize >= CHUNK_SIZE
|
514
|
-
spring = src_info[ :chunks ].size > 0 ? ( src_info[ :spring ] + 1 ) : 0
|
515
|
-
filename = "#{ Process.pid }-#{ src_info[ :id ] }.#{ spring }"
|
516
|
-
chunk_path = File.join( @src_chunk_dir, filename )
|
517
|
-
|
518
|
-
begin
|
519
|
-
IO.binwrite( chunk_path, src_info[ :wbuff ] )
|
520
|
-
rescue Errno::ENOSPC => e
|
521
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close src"
|
522
|
-
set_is_closing( src )
|
523
|
-
return
|
524
|
-
end
|
525
|
-
|
526
|
-
src_info[ :chunks ] << filename
|
527
|
-
src_info[ :spring ] = spring
|
528
|
-
src_info[ :wbuff ].clear
|
529
|
-
end
|
530
|
-
|
531
486
|
add_write( src )
|
532
487
|
end
|
533
488
|
|
@@ -537,37 +492,20 @@ module Girl
|
|
537
492
|
def add_dst_wbuff( dst, data )
|
538
493
|
dst_info = @dst_infos[ dst ]
|
539
494
|
dst_info[ :wbuff ] << data
|
540
|
-
|
541
|
-
if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
|
542
|
-
spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
|
543
|
-
filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
|
544
|
-
chunk_path = File.join( @dst_chunk_dir, filename )
|
545
|
-
|
546
|
-
begin
|
547
|
-
IO.binwrite( chunk_path, dst_info[ :wbuff ] )
|
548
|
-
rescue Errno::ENOSPC => e
|
549
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close dst"
|
550
|
-
set_is_closing( dst )
|
551
|
-
return
|
552
|
-
end
|
553
|
-
|
554
|
-
dst_info[ :chunks ] << filename
|
555
|
-
dst_info[ :spring ] = spring
|
556
|
-
dst_info[ :wbuff ].clear
|
557
|
-
end
|
558
|
-
|
559
495
|
add_write( dst )
|
560
496
|
end
|
561
497
|
|
562
498
|
##
|
563
499
|
# add read
|
564
500
|
#
|
565
|
-
def add_read( sock, role )
|
566
|
-
|
501
|
+
def add_read( sock, role = nil )
|
502
|
+
if sock && !sock.closed? && !@reads.include?( sock )
|
567
503
|
@reads << sock
|
568
|
-
end
|
569
504
|
|
570
|
-
|
505
|
+
if role
|
506
|
+
@roles[ sock ] = role
|
507
|
+
end
|
508
|
+
end
|
571
509
|
end
|
572
510
|
|
573
511
|
##
|
@@ -579,6 +517,17 @@ module Girl
|
|
579
517
|
end
|
580
518
|
end
|
581
519
|
|
520
|
+
##
|
521
|
+
# add pause src
|
522
|
+
#
|
523
|
+
def add_pause_src( src )
|
524
|
+
@reads.delete( src )
|
525
|
+
|
526
|
+
unless @pause_srcs.include?( src )
|
527
|
+
@pause_srcs << src
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
582
531
|
##
|
583
532
|
# set is closing
|
584
533
|
#
|
@@ -603,10 +552,52 @@ module Girl
|
|
603
552
|
end
|
604
553
|
end
|
605
554
|
|
555
|
+
##
|
556
|
+
# tunnel data
|
557
|
+
#
|
558
|
+
def tunnel_data( src, data )
|
559
|
+
src_info = @src_infos[ src ]
|
560
|
+
src_id = src_info[ :id ]
|
561
|
+
now = Time.new
|
562
|
+
pack_id = src_info[ :biggest_pack_id ]
|
563
|
+
idx = 0
|
564
|
+
len = data.bytesize
|
565
|
+
|
566
|
+
while idx < len
|
567
|
+
chunk = data[ idx, PACK_SIZE ]
|
568
|
+
pack_id += 1
|
569
|
+
|
570
|
+
if pack_id <= CONFUSE_UNTIL
|
571
|
+
chunk = @custom.encode( chunk )
|
572
|
+
# puts "debug1 encoded chunk #{ pack_id }"
|
573
|
+
end
|
574
|
+
|
575
|
+
data2 = [ [ pack_id, src_id ].pack( 'Q>Q>' ), chunk ].join
|
576
|
+
sent = send_data( @tun, data2, @tun_info[ :tund_addr ] )
|
577
|
+
# puts "debug2 written pack #{ pack_id } #{ sent }"
|
578
|
+
@tun_info[ :wmems ][ [ src_id, pack_id ] ] = data2
|
579
|
+
src_info[ :send_ats ][ pack_id ] = now
|
580
|
+
idx += PACK_SIZE
|
581
|
+
end
|
582
|
+
|
583
|
+
src_info[ :biggest_pack_id ] = pack_id
|
584
|
+
src_info[ :last_continue_at ] = now
|
585
|
+
|
586
|
+
# 写后超过上限,暂停读src
|
587
|
+
if @tun_info[ :wmems ].size >= WMEMS_LIMIT
|
588
|
+
puts "p#{ Process.pid } #{ Time.new } pause src #{ src_id } #{ src_info[ :destination_domain ] } #{ src_info[ :biggest_pack_id ] }"
|
589
|
+
add_pause_src( src )
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
606
593
|
##
|
607
594
|
# send data
|
608
595
|
#
|
609
596
|
def send_data( tun, data, to_addr )
|
597
|
+
unless to_addr
|
598
|
+
return false
|
599
|
+
end
|
600
|
+
|
610
601
|
begin
|
611
602
|
tun.sendmsg( data, 0, to_addr )
|
612
603
|
rescue IO::WaitWritable, Errno::EINTR
|
@@ -626,36 +617,36 @@ module Girl
|
|
626
617
|
def close_src( src )
|
627
618
|
# puts "debug1 close src"
|
628
619
|
close_sock( src )
|
629
|
-
|
620
|
+
@pause_srcs.delete( src )
|
621
|
+
src_info = @src_infos[ src ]
|
630
622
|
|
631
|
-
src_info[ :
|
632
|
-
|
633
|
-
|
634
|
-
|
623
|
+
if src_info[ :proxy_type ] == :direct
|
624
|
+
@src_infos.delete( src )
|
625
|
+
|
626
|
+
if src_info[ :dst ]
|
627
|
+
set_is_closing( src_info[ :dst ] )
|
635
628
|
end
|
636
|
-
end
|
637
629
|
|
638
|
-
|
630
|
+
return
|
631
|
+
end
|
639
632
|
|
640
|
-
if src_info[ :
|
641
|
-
|
633
|
+
if @tun.closed? || src_info[ :dst_id ].nil?
|
634
|
+
@src_infos.delete( src )
|
635
|
+
return
|
636
|
+
end
|
642
637
|
|
643
|
-
|
644
|
-
return if src_ext.nil? || src_ext[ :dst_port ].nil?
|
638
|
+
src_id = src_info[ :id ]
|
645
639
|
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
|
654
|
-
add_tun_ctlmsg( data )
|
655
|
-
end
|
656
|
-
elsif src_info[ :proxy_type ] == :direct
|
657
|
-
set_is_closing( src_info[ :dst ] )
|
640
|
+
if src_info[ :is_dst_closed ]
|
641
|
+
# puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
|
642
|
+
del_src_ext( src_id )
|
643
|
+
data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
|
644
|
+
else
|
645
|
+
# puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
|
646
|
+
data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
|
658
647
|
end
|
648
|
+
|
649
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
659
650
|
end
|
660
651
|
|
661
652
|
##
|
@@ -665,14 +656,6 @@ module Girl
|
|
665
656
|
# puts "debug1 close dst"
|
666
657
|
close_sock( dst )
|
667
658
|
dst_info = @dst_infos.delete( dst )
|
668
|
-
|
669
|
-
dst_info[ :chunks ].each do | filename |
|
670
|
-
begin
|
671
|
-
File.delete( File.join( @dst_chunk_dir, filename ) )
|
672
|
-
rescue Errno::ENOENT
|
673
|
-
end
|
674
|
-
end
|
675
|
-
|
676
659
|
set_is_closing( dst_info[ :src ] )
|
677
660
|
end
|
678
661
|
|
@@ -682,15 +665,7 @@ module Girl
|
|
682
665
|
def close_tun( tun )
|
683
666
|
# puts "debug1 close tun"
|
684
667
|
close_sock( tun )
|
685
|
-
|
686
|
-
@tun_info[ :chunks ].each do | filename |
|
687
|
-
begin
|
688
|
-
File.delete( File.join( @tun_chunk_dir, filename ) )
|
689
|
-
rescue Errno::ENOENT
|
690
|
-
end
|
691
|
-
end
|
692
|
-
|
693
|
-
@tun_info[ :src_exts ].each{ | _, src_ext | set_is_closing( src_ext[ :src ] ) }
|
668
|
+
@tun_info[ :srcs ].each{ | _, src | set_is_closing( src ) }
|
694
669
|
end
|
695
670
|
|
696
671
|
##
|
@@ -707,27 +682,32 @@ module Girl
|
|
707
682
|
# del src ext
|
708
683
|
#
|
709
684
|
def del_src_ext( src_id )
|
710
|
-
|
685
|
+
@tun_info[ :wmems ].delete_if { | src_id_and_pack_id, _ | src_id_and_pack_id.first == src_id }
|
686
|
+
src = @tun_info[ :srcs ].delete( src_id )
|
687
|
+
|
688
|
+
if src
|
689
|
+
src_info = @src_infos.delete( src )
|
711
690
|
|
712
|
-
|
713
|
-
|
691
|
+
if src_info
|
692
|
+
@tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
|
693
|
+
end
|
714
694
|
end
|
715
695
|
end
|
716
696
|
|
717
697
|
##
|
718
698
|
# release wmems
|
719
699
|
#
|
720
|
-
def release_wmems(
|
721
|
-
if completed_pack_id >
|
700
|
+
def release_wmems( src_info, completed_pack_id )
|
701
|
+
if completed_pack_id > src_info[ :completed_pack_id ]
|
722
702
|
# puts "debug2 update completed pack #{ completed_pack_id }"
|
723
|
-
pack_ids =
|
703
|
+
pack_ids = src_info[ :send_ats ].keys.select { | pack_id | pack_id <= completed_pack_id }
|
724
704
|
|
725
705
|
pack_ids.each do | pack_id |
|
726
|
-
|
727
|
-
|
706
|
+
@tun_info[ :wmems ].delete( [ src_info[ :id ], pack_id ] )
|
707
|
+
src_info[ :send_ats ].delete( pack_id )
|
728
708
|
end
|
729
709
|
|
730
|
-
|
710
|
+
src_info[ :completed_pack_id ] = completed_pack_id
|
731
711
|
end
|
732
712
|
end
|
733
713
|
|
@@ -743,32 +723,16 @@ module Girl
|
|
743
723
|
#
|
744
724
|
def write_src( src )
|
745
725
|
src_info = @src_infos[ src ]
|
746
|
-
from, data = :cache, src_info[ :cache ]
|
747
726
|
|
748
|
-
if
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
begin
|
753
|
-
data = src_info[ :cache ] = IO.binread( path )
|
754
|
-
File.delete( path )
|
755
|
-
rescue Errno::ENOENT => e
|
756
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
757
|
-
close_src( src )
|
758
|
-
return
|
759
|
-
end
|
760
|
-
else
|
761
|
-
from, data = :wbuff, src_info[ :wbuff ]
|
762
|
-
end
|
727
|
+
if src_info[ :is_closing ]
|
728
|
+
close_src( src )
|
729
|
+
return
|
763
730
|
end
|
764
731
|
|
765
|
-
|
766
|
-
if src_info[ :is_closing ]
|
767
|
-
close_src( src )
|
768
|
-
else
|
769
|
-
@writes.delete( src )
|
770
|
-
end
|
732
|
+
data = src_info[ :wbuff ]
|
771
733
|
|
734
|
+
if data.empty?
|
735
|
+
@writes.delete( src )
|
772
736
|
return
|
773
737
|
end
|
774
738
|
|
@@ -783,7 +747,7 @@ module Girl
|
|
783
747
|
|
784
748
|
# puts "debug2 write src #{ written }"
|
785
749
|
data = data[ written..-1 ]
|
786
|
-
src_info[
|
750
|
+
src_info[ :wbuff ] = data
|
787
751
|
src_info[ :last_continue_at ] = Time.new
|
788
752
|
end
|
789
753
|
|
@@ -792,32 +756,16 @@ module Girl
|
|
792
756
|
#
|
793
757
|
def write_dst( dst )
|
794
758
|
dst_info = @dst_infos[ dst ]
|
795
|
-
from, data = :cache, dst_info[ :cache ]
|
796
759
|
|
797
|
-
if
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
begin
|
802
|
-
data = dst_info[ :cache ] = IO.binread( path )
|
803
|
-
File.delete( path )
|
804
|
-
rescue Errno::ENOENT => e
|
805
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
806
|
-
close_dst( dst )
|
807
|
-
return
|
808
|
-
end
|
809
|
-
else
|
810
|
-
from, data = :wbuff, dst_info[ :wbuff ]
|
811
|
-
end
|
760
|
+
if dst_info[ :is_closing ]
|
761
|
+
close_dst( dst )
|
762
|
+
return
|
812
763
|
end
|
813
764
|
|
814
|
-
|
815
|
-
if dst_info[ :is_closing ]
|
816
|
-
close_dst( dst )
|
817
|
-
else
|
818
|
-
@writes.delete( dst )
|
819
|
-
end
|
765
|
+
data = dst_info[ :wbuff ]
|
820
766
|
|
767
|
+
if data.empty?
|
768
|
+
@writes.delete( dst )
|
821
769
|
return
|
822
770
|
end
|
823
771
|
|
@@ -833,7 +781,7 @@ module Girl
|
|
833
781
|
|
834
782
|
# puts "debug2 write dst #{ written }"
|
835
783
|
data = data[ written..-1 ]
|
836
|
-
dst_info[
|
784
|
+
dst_info[ :wbuff ] = data
|
837
785
|
dst_info[ :last_continue_at ] = Time.new
|
838
786
|
end
|
839
787
|
|
@@ -846,106 +794,7 @@ module Girl
|
|
846
794
|
return
|
847
795
|
end
|
848
796
|
|
849
|
-
|
850
|
-
|
851
|
-
# 传ctlmsg
|
852
|
-
while @tun_info[ :ctlmsgs ].any?
|
853
|
-
to_addr, data = @tun_info[ :ctlmsgs ].first
|
854
|
-
|
855
|
-
unless send_data( tun, data, to_addr )
|
856
|
-
return
|
857
|
-
end
|
858
|
-
|
859
|
-
@tun_info[ :ctlmsgs ].shift
|
860
|
-
end
|
861
|
-
|
862
|
-
# 重传
|
863
|
-
while @tun_info[ :resendings ].any?
|
864
|
-
src_id, pack_id = @tun_info[ :resendings ].first
|
865
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
866
|
-
|
867
|
-
if src_ext
|
868
|
-
data = src_ext[ :wmems ][ pack_id ]
|
869
|
-
|
870
|
-
if data
|
871
|
-
unless send_data( tun, data, @tun_info[ :tund_addr ] )
|
872
|
-
return
|
873
|
-
end
|
874
|
-
|
875
|
-
src_ext[ :last_continue_at ] = now
|
876
|
-
end
|
877
|
-
end
|
878
|
-
|
879
|
-
@tun_info[ :resendings ].shift
|
880
|
-
end
|
881
|
-
|
882
|
-
# 若写后达到上限,暂停取写前
|
883
|
-
if @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
|
884
|
-
unless @tun_info[ :paused ]
|
885
|
-
puts "p#{ Process.pid } #{ Time.new } pause tun"
|
886
|
-
@tun_info[ :paused ] = true
|
887
|
-
end
|
888
|
-
|
889
|
-
@writes.delete( tun )
|
890
|
-
return
|
891
|
-
end
|
892
|
-
|
893
|
-
# 取写前
|
894
|
-
if @tun_info[ :caches ].any?
|
895
|
-
datas = @tun_info[ :caches ]
|
896
|
-
elsif @tun_info[ :chunks ].any?
|
897
|
-
path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
|
898
|
-
|
899
|
-
begin
|
900
|
-
data = IO.binread( path )
|
901
|
-
File.delete( path )
|
902
|
-
rescue Errno::ENOENT => e
|
903
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
904
|
-
close_tun( tun )
|
905
|
-
return
|
906
|
-
end
|
907
|
-
|
908
|
-
caches = []
|
909
|
-
|
910
|
-
until data.empty?
|
911
|
-
_src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
|
912
|
-
caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
|
913
|
-
data = data[ ( 18 + pack_size )..-1 ]
|
914
|
-
end
|
915
|
-
|
916
|
-
datas = @tun_info[ :caches ] = caches
|
917
|
-
elsif @tun_info[ :wbuffs ].any?
|
918
|
-
datas = @tun_info[ :wbuffs ]
|
919
|
-
else
|
920
|
-
@writes.delete( tun )
|
921
|
-
return
|
922
|
-
end
|
923
|
-
|
924
|
-
while datas.any?
|
925
|
-
src_id, pack_id, data = datas.first
|
926
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
927
|
-
|
928
|
-
if src_ext
|
929
|
-
if pack_id <= CONFUSE_UNTIL
|
930
|
-
data = @custom.encode( data )
|
931
|
-
# puts "debug1 encoded pack #{ pack_id }"
|
932
|
-
end
|
933
|
-
|
934
|
-
data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
|
935
|
-
|
936
|
-
unless send_data( tun, data, @tun_info[ :tund_addr ] )
|
937
|
-
return
|
938
|
-
end
|
939
|
-
|
940
|
-
# puts "debug2 written pack #{ pack_id }"
|
941
|
-
src_ext[ :relay_pack_id ] = pack_id
|
942
|
-
src_ext[ :wmems ][ pack_id ] = data
|
943
|
-
src_ext[ :send_ats ][ pack_id ] = now
|
944
|
-
src_ext[ :last_continue_at ] = now
|
945
|
-
end
|
946
|
-
|
947
|
-
datas.shift
|
948
|
-
end
|
797
|
+
@writes.delete( tun )
|
949
798
|
end
|
950
799
|
|
951
800
|
##
|
@@ -965,11 +814,11 @@ module Girl
|
|
965
814
|
return
|
966
815
|
end
|
967
816
|
|
968
|
-
|
969
|
-
# puts "debug1 accept a src #{ addrinfo.inspect } #{
|
817
|
+
src_id = rand( ( 2 ** 64 ) - 2 ) + 1
|
818
|
+
# puts "debug1 accept a src #{ addrinfo.inspect } #{ src_id }"
|
970
819
|
|
971
820
|
@src_infos[ src ] = {
|
972
|
-
id:
|
821
|
+
id: src_id, # id
|
973
822
|
proxy_proto: :uncheck, # :uncheck / :http / :socks5
|
974
823
|
proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
|
975
824
|
dst: nil, # :direct的场合,对应的dst
|
@@ -977,11 +826,15 @@ module Girl
|
|
977
826
|
destination_port: nil, # 目的地端口
|
978
827
|
biggest_pack_id: 0, # 最大包号码
|
979
828
|
is_connect: true, # 代理协议是http的场合,是否是CONNECT
|
980
|
-
|
829
|
+
rbuff: '', # 非CONNECT,dst或者远端dst未准备好,暂存流量
|
981
830
|
wbuff: '', # 写前
|
982
|
-
|
983
|
-
|
984
|
-
|
831
|
+
dst_id: nil, # 远端dst id
|
832
|
+
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
833
|
+
continue_dst_pack_id: 0, # 收到几
|
834
|
+
pieces: {}, # 跳号包 dst_pack_id => data
|
835
|
+
is_dst_closed: false, # dst是否已关闭
|
836
|
+
biggest_dst_pack_id: 0, # dst最大包号码
|
837
|
+
completed_pack_id: 0, # 完成到几(对面收到几)
|
985
838
|
last_continue_at: Time.new, # 上一次发生流量的时间
|
986
839
|
is_closing: false # 是否准备关闭
|
987
840
|
}
|
@@ -994,7 +847,7 @@ module Girl
|
|
994
847
|
#
|
995
848
|
def read_src( src )
|
996
849
|
begin
|
997
|
-
data = src.read_nonblock(
|
850
|
+
data = src.read_nonblock( READ_SIZE )
|
998
851
|
rescue IO::WaitReadable, Errno::EINTR
|
999
852
|
return
|
1000
853
|
rescue Exception => e
|
@@ -1074,9 +927,7 @@ module Girl
|
|
1074
927
|
end
|
1075
928
|
|
1076
929
|
src_info[ :is_connect ] = false
|
1077
|
-
|
1078
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1079
|
-
src_info[ :rbuffs ] << [ pack_id, data ]
|
930
|
+
src_info[ :rbuff ] << data
|
1080
931
|
end
|
1081
932
|
|
1082
933
|
domain, port = domain_and_port.split( ':' )
|
@@ -1089,9 +940,7 @@ module Girl
|
|
1089
940
|
resolve_domain( src, domain )
|
1090
941
|
when :checking
|
1091
942
|
# puts "debug1 add src rbuff while checking #{ data.inspect }"
|
1092
|
-
|
1093
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1094
|
-
src_info[ :rbuffs ] << [ pack_id, data ]
|
943
|
+
src_info[ :rbuff ] << data
|
1095
944
|
when :negotiation
|
1096
945
|
# +----+-----+-------+------+----------+----------+
|
1097
946
|
# |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
|
@@ -1129,19 +978,7 @@ module Girl
|
|
1129
978
|
puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
|
1130
979
|
end
|
1131
980
|
when :tunnel
|
1132
|
-
|
1133
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
1134
|
-
|
1135
|
-
unless src_ext
|
1136
|
-
# puts "debug1 not found src ext"
|
1137
|
-
set_is_closing( src )
|
1138
|
-
return
|
1139
|
-
end
|
1140
|
-
|
1141
|
-
pack_id = src_info[ :biggest_pack_id ] + 1
|
1142
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1143
|
-
|
1144
|
-
if src_ext[ :dst_port ]
|
981
|
+
if src_info[ :dst_id ]
|
1145
982
|
if @tun.closed?
|
1146
983
|
# puts "debug1 tun closed, close src"
|
1147
984
|
set_is_closing( src )
|
@@ -1152,10 +989,10 @@ module Girl
|
|
1152
989
|
data, _ = sub_http_request( data )
|
1153
990
|
end
|
1154
991
|
|
1155
|
-
|
992
|
+
tunnel_data( src, data )
|
1156
993
|
else
|
1157
994
|
# puts "debug1 remote dst not ready, save data to src rbuff"
|
1158
|
-
src_info[ :
|
995
|
+
src_info[ :rbuff ] << data
|
1159
996
|
end
|
1160
997
|
when :direct
|
1161
998
|
dst = src_info[ :dst ]
|
@@ -1174,7 +1011,7 @@ module Girl
|
|
1174
1011
|
add_dst_wbuff( dst, data )
|
1175
1012
|
else
|
1176
1013
|
# puts "debug1 dst not ready, save data to src rbuff"
|
1177
|
-
src_info[ :
|
1014
|
+
src_info[ :rbuff ] << data
|
1178
1015
|
end
|
1179
1016
|
end
|
1180
1017
|
end
|
@@ -1184,7 +1021,7 @@ module Girl
|
|
1184
1021
|
#
|
1185
1022
|
def read_dst( dst )
|
1186
1023
|
begin
|
1187
|
-
data = dst.read_nonblock(
|
1024
|
+
data = dst.read_nonblock( READ_SIZE )
|
1188
1025
|
rescue IO::WaitReadable, Errno::EINTR
|
1189
1026
|
return
|
1190
1027
|
rescue Exception => e
|
@@ -1226,143 +1063,194 @@ module Girl
|
|
1226
1063
|
|
1227
1064
|
tund_port = data[ 9, 2 ].unpack( 'n' ).first
|
1228
1065
|
|
1229
|
-
|
1066
|
+
puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
|
1230
1067
|
tund_addr = Socket.sockaddr_in( tund_port, @proxyd_host )
|
1231
1068
|
@tun_info[ :tund_addr ] = tund_addr
|
1232
1069
|
|
1233
|
-
if @tun_info[ :
|
1234
|
-
|
1235
|
-
|
1236
|
-
@tun_info[ :
|
1237
|
-
|
1070
|
+
if @tun_info[ :pending_sources ].any?
|
1071
|
+
puts "p#{ Process.pid } #{ Time.new } send pending sources"
|
1072
|
+
|
1073
|
+
@tun_info[ :pending_sources ].each do | src |
|
1074
|
+
loop_send_a_new_source( src )
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
@tun_info[ :pending_sources ].clear
|
1238
1078
|
end
|
1239
1079
|
when PAIRED
|
1240
1080
|
return if from_addr != @tun_info[ :tund_addr ]
|
1241
1081
|
|
1242
|
-
src_id,
|
1082
|
+
src_id, dst_id = data[ 9, 10 ].unpack( 'Q>n' )
|
1243
1083
|
|
1244
|
-
|
1245
|
-
return if src_ext.nil? || src_ext[ :dst_port ]
|
1246
|
-
|
1247
|
-
src = src_ext[ :src ]
|
1084
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1248
1085
|
return if src.closed?
|
1249
1086
|
|
1250
|
-
|
1087
|
+
src_info = @src_infos[ src ]
|
1088
|
+
return if src_info[ :dst_id ]
|
1251
1089
|
|
1252
|
-
|
1090
|
+
# puts "debug1 got paired #{ src_id } #{ dst_id }"
|
1091
|
+
|
1092
|
+
if dst_id == 0
|
1253
1093
|
set_is_closing( src )
|
1254
1094
|
return
|
1255
1095
|
end
|
1256
1096
|
|
1257
|
-
|
1258
|
-
@tun_info[ :src_ids ][
|
1259
|
-
|
1260
|
-
src_info = @src_infos[ src ]
|
1097
|
+
src_info[ :dst_id ] = dst_id
|
1098
|
+
@tun_info[ :src_ids ][ dst_id ] = src_id
|
1261
1099
|
|
1262
1100
|
if src_info[ :proxy_proto ] == :http
|
1263
1101
|
if src_info[ :is_connect ]
|
1264
1102
|
# puts "debug1 add src wbuff http ok"
|
1265
1103
|
add_src_wbuff( src, HTTP_OK )
|
1266
1104
|
else
|
1267
|
-
# puts "debug1
|
1268
|
-
|
1269
|
-
src_info[ :rbuffs ].each do | pack_id, _data |
|
1270
|
-
add_tun_wbuff( src_id, pack_id, _data )
|
1271
|
-
end
|
1105
|
+
# puts "debug1 send src rbuff to tund"
|
1106
|
+
tunnel_data( src, src_info[ :rbuff ] )
|
1272
1107
|
end
|
1273
1108
|
elsif src_info[ :proxy_proto ] == :socks5
|
1274
|
-
add_src_wbuff_socks5_conn_reply(
|
1109
|
+
add_src_wbuff_socks5_conn_reply( src )
|
1275
1110
|
end
|
1276
1111
|
when DEST_STATUS
|
1277
1112
|
return if from_addr != @tun_info[ :tund_addr ]
|
1278
1113
|
|
1279
|
-
|
1114
|
+
dst_id, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
1280
1115
|
|
1281
|
-
src_id = @tun_info[ :src_ids ][
|
1116
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1282
1117
|
return unless src_id
|
1283
1118
|
|
1284
|
-
|
1285
|
-
return unless
|
1119
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1120
|
+
return unless src
|
1121
|
+
|
1122
|
+
src_info = @src_infos[ src ]
|
1123
|
+
return unless src_info
|
1286
1124
|
|
1287
|
-
# puts "debug2 got dest status"
|
1125
|
+
# puts "debug2 got dest status #{ Time.new }"
|
1288
1126
|
|
1289
|
-
|
1127
|
+
# 消写后
|
1128
|
+
release_wmems( src_info, continue_src_pack_id )
|
1290
1129
|
|
1291
1130
|
# 发miss
|
1292
|
-
if !
|
1131
|
+
if !src.closed? && ( src_info[ :continue_dst_pack_id ] < relay_dst_pack_id )
|
1293
1132
|
ranges = []
|
1294
|
-
|
1133
|
+
ignored = false
|
1134
|
+
curr_pack_id = src_info[ :continue_dst_pack_id ] + 1
|
1295
1135
|
|
1296
|
-
|
1136
|
+
src_info[ :pieces ].keys.sort.each do | pack_id |
|
1297
1137
|
if pack_id > curr_pack_id
|
1298
1138
|
ranges << [ curr_pack_id, pack_id - 1 ]
|
1139
|
+
|
1140
|
+
if ranges.size >= MISS_RANGE_LIMIT
|
1141
|
+
puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
|
1142
|
+
ignored = true
|
1143
|
+
break
|
1144
|
+
end
|
1299
1145
|
end
|
1300
1146
|
|
1301
1147
|
curr_pack_id = pack_id + 1
|
1302
1148
|
end
|
1303
1149
|
|
1304
|
-
if curr_pack_id <= relay_dst_pack_id
|
1150
|
+
if !ignored && ( curr_pack_id <= relay_dst_pack_id )
|
1305
1151
|
ranges << [ curr_pack_id, relay_dst_pack_id ]
|
1306
1152
|
end
|
1307
1153
|
|
1308
|
-
|
1309
|
-
|
1154
|
+
# puts "debug1 continue/relay #{ src_info[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
|
1155
|
+
idx = 0
|
1156
|
+
ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
|
1310
1157
|
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1158
|
+
while idx < ranges.size
|
1159
|
+
chunk = ranges[ idx, MULTI_MISS_SIZE ].join
|
1160
|
+
data2 = [ [ 0, MULTI_MISS, dst_id ].pack( 'Q>Cn' ), chunk ].join
|
1161
|
+
send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1162
|
+
idx += MULTI_MISS_SIZE
|
1163
|
+
end
|
1164
|
+
end
|
1165
|
+
when MULTI_MISS
|
1166
|
+
src_id, *ranges = data[ 9..-1 ].unpack( 'Q>Q>*' )
|
1167
|
+
|
1168
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1169
|
+
return unless src
|
1170
|
+
|
1171
|
+
src_info = @src_infos[ src ]
|
1172
|
+
return unless src_info
|
1316
1173
|
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1174
|
+
return if ranges.empty? || ( ranges.size % 2 != 0 )
|
1175
|
+
|
1176
|
+
# puts "debug1 got multi miss #{ src_id } #{ ranges.size }"
|
1177
|
+
|
1178
|
+
idx = 0
|
1179
|
+
|
1180
|
+
while idx < ranges.size
|
1181
|
+
pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
|
1182
|
+
|
1183
|
+
( pack_id_begin..pack_id_end ).each do | pack_id |
|
1184
|
+
send_at = src_info[ :send_ats ][ pack_id ]
|
1185
|
+
|
1186
|
+
if send_at
|
1187
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
1188
|
+
data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
|
1189
|
+
|
1190
|
+
if data2
|
1191
|
+
if send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1192
|
+
src_info[ :last_continue_at ] = now
|
1193
|
+
end
|
1194
|
+
end
|
1195
|
+
end
|
1320
1196
|
end
|
1197
|
+
|
1198
|
+
idx += 2
|
1321
1199
|
end
|
1322
1200
|
when MISS
|
1323
1201
|
return if from_addr != @tun_info[ :tund_addr ]
|
1324
1202
|
|
1325
1203
|
src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
1326
1204
|
|
1327
|
-
|
1328
|
-
return unless
|
1205
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1206
|
+
return unless src
|
1207
|
+
|
1208
|
+
src_info = @src_infos[ src ]
|
1209
|
+
return unless src_info
|
1329
1210
|
|
1330
1211
|
( pack_id_begin..pack_id_end ).each do | pack_id |
|
1331
|
-
send_at =
|
1212
|
+
send_at = src_info[ :send_ats ][ pack_id ]
|
1332
1213
|
|
1333
1214
|
if send_at
|
1334
|
-
break if now - send_at <
|
1335
|
-
@tun_info[ :
|
1215
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
1216
|
+
data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
|
1217
|
+
|
1218
|
+
if data2
|
1219
|
+
if send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1220
|
+
src_info[ :last_continue_at ] = now
|
1221
|
+
end
|
1222
|
+
end
|
1336
1223
|
end
|
1337
1224
|
end
|
1338
|
-
|
1339
|
-
add_write( tun )
|
1340
1225
|
when FIN1
|
1341
1226
|
return if from_addr != @tun_info[ :tund_addr ]
|
1342
1227
|
|
1343
|
-
|
1228
|
+
dst_id, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
1344
1229
|
|
1345
|
-
src_id = @tun_info[ :src_ids ][
|
1230
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1346
1231
|
return unless src_id
|
1347
1232
|
|
1348
|
-
|
1349
|
-
return unless
|
1233
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1234
|
+
return unless src
|
1350
1235
|
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1236
|
+
src_info = @src_infos[ src ]
|
1237
|
+
return unless src_info
|
1238
|
+
|
1239
|
+
# puts "debug1 got fin1 #{ dst_id } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
|
1240
|
+
src_info[ :is_dst_closed ] = true
|
1241
|
+
src_info[ :biggest_dst_pack_id ] = biggest_dst_pack_id
|
1242
|
+
release_wmems( src_info, continue_src_pack_id )
|
1355
1243
|
|
1356
|
-
if ( biggest_dst_pack_id ==
|
1244
|
+
if ( biggest_dst_pack_id == src_info[ :continue_dst_pack_id ] )
|
1357
1245
|
# puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
|
1358
|
-
set_is_closing(
|
1246
|
+
set_is_closing( src )
|
1359
1247
|
end
|
1360
1248
|
when FIN2
|
1361
1249
|
return if from_addr != @tun_info[ :tund_addr ]
|
1362
1250
|
|
1363
|
-
|
1251
|
+
dst_id = data[ 9, 2 ].unpack( 'n' ).first
|
1364
1252
|
|
1365
|
-
src_id = @tun_info[ :src_ids ][
|
1253
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1366
1254
|
return unless src_id
|
1367
1255
|
|
1368
1256
|
# puts "debug1 1-2. tun recv fin2 -> del src ext"
|
@@ -1384,14 +1272,18 @@ module Girl
|
|
1384
1272
|
|
1385
1273
|
return if from_addr != @tun_info[ :tund_addr ]
|
1386
1274
|
|
1387
|
-
|
1275
|
+
dst_id = data[ 8, 2 ].unpack( 'n' ).first
|
1388
1276
|
|
1389
|
-
src_id = @tun_info[ :src_ids ][
|
1277
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1390
1278
|
return unless src_id
|
1391
1279
|
|
1392
|
-
|
1393
|
-
return
|
1394
|
-
|
1280
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1281
|
+
return unless src
|
1282
|
+
|
1283
|
+
src_info = @src_infos[ src ]
|
1284
|
+
return unless src_info
|
1285
|
+
|
1286
|
+
return if ( pack_id <= src_info[ :continue_dst_pack_id ] ) || src_info[ :pieces ].include?( pack_id )
|
1395
1287
|
|
1396
1288
|
data = data[ 10..-1 ]
|
1397
1289
|
# puts "debug2 got pack #{ pack_id }"
|
@@ -1403,24 +1295,25 @@ module Girl
|
|
1403
1295
|
end
|
1404
1296
|
|
1405
1297
|
# 放进写前,跳号放碎片缓存
|
1406
|
-
if pack_id -
|
1407
|
-
while
|
1408
|
-
data <<
|
1298
|
+
if pack_id - src_info[ :continue_dst_pack_id ] == 1
|
1299
|
+
while src_info[ :pieces ].include?( pack_id + 1 )
|
1300
|
+
data << src_info[ :pieces ].delete( pack_id + 1 )
|
1409
1301
|
pack_id += 1
|
1410
1302
|
end
|
1411
1303
|
|
1412
|
-
|
1413
|
-
|
1414
|
-
add_src_wbuff(
|
1304
|
+
src_info[ :continue_dst_pack_id ] = pack_id
|
1305
|
+
src_info[ :last_continue_at ] = now
|
1306
|
+
add_src_wbuff( src, data )
|
1415
1307
|
# puts "debug2 update continue dst pack #{ pack_id }"
|
1416
1308
|
|
1417
|
-
#
|
1418
|
-
if
|
1309
|
+
# 若对面已关闭,且流量正好收全,关闭src
|
1310
|
+
if src_info[ :is_dst_closed ] && ( pack_id == src_info[ :biggest_dst_pack_id ] )
|
1419
1311
|
# puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
|
1420
|
-
set_is_closing(
|
1312
|
+
set_is_closing( src )
|
1421
1313
|
end
|
1422
1314
|
else
|
1423
|
-
|
1315
|
+
src_info[ :pieces ][ pack_id ] = data
|
1316
|
+
src_info[ :last_continue_at ] = now
|
1424
1317
|
end
|
1425
1318
|
end
|
1426
1319
|
|