girl 0.82.0 → 0.87.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/girl.gemspec +1 -1
- data/lib/girl/head.rb +29 -28
- data/lib/girl/proxy.rb +26 -35
- data/lib/girl/proxy_worker.rb +368 -474
- 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: 590ceead2e46e0803325aff199ec4fa4610a554f873ad58e91f83e8cba7bd4a9
|
4
|
+
data.tar.gz: 3034b02ee1ddf592a67446d82a3f974f2439aef9f380f20b39c96aa943a4a7ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27d1dd5ef6d6f4d29c1916af5c10c8eb694e7cbf11f2f8518a6d4a3ebd0d368aa92518a9c5c0f91079f9291c67b1050be16db3f0154d7fb710f55d818ca75576
|
7
|
+
data.tar.gz: ae5ab8293caf167146784342a93e059ef03a201dbd1a1a3df6bbe206321f95b13526e78713ca77903e3be44873ce02474c4d3260187fcd85c993206401fef586
|
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
|
|
@@ -108,7 +106,7 @@ module Girl
|
|
108
106
|
raise "not found direct file #{ direct_path }"
|
109
107
|
end
|
110
108
|
|
111
|
-
directs = (
|
109
|
+
directs = ( RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map { | line | IPAddr.new( line.strip ) }
|
112
110
|
end
|
113
111
|
|
114
112
|
remotes = []
|
@@ -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
|
@@ -186,24 +197,58 @@ module Girl
|
|
186
197
|
end
|
187
198
|
end
|
188
199
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
def loop_send_a_new_source( src_ext, data )
|
200
|
+
def loop_send_hello
|
201
|
+
data = @custom.hello
|
202
|
+
|
193
203
|
Thread.new do
|
194
|
-
EXPIRE_NEW.times do
|
195
|
-
if
|
196
|
-
# puts "debug1 break loop send
|
204
|
+
EXPIRE_NEW.times do | i |
|
205
|
+
if @tun.closed? || @tun_info[ :tund_addr ]
|
206
|
+
# puts "debug1 break loop send hello"
|
197
207
|
break
|
198
208
|
end
|
199
209
|
|
200
210
|
@mutex.synchronize do
|
201
|
-
|
202
|
-
|
203
|
-
|
211
|
+
msg = i >= 1 ? "resend hello #{ i }" : "hello i'm tun"
|
212
|
+
puts "p#{ Process.pid } #{ Time.new } #{ msg }"
|
213
|
+
# puts "debug1 #{ data.inspect }"
|
214
|
+
|
215
|
+
send_data( @tun, data, @proxyd_addr )
|
204
216
|
end
|
205
217
|
|
206
|
-
sleep
|
218
|
+
sleep CHECK_STATUS_INTERVAL
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
##
|
224
|
+
# loop send a new source
|
225
|
+
#
|
226
|
+
def loop_send_a_new_source( src )
|
227
|
+
src_info = @src_infos[ src ]
|
228
|
+
|
229
|
+
if src_info && @tun_info[ :tund_addr ]
|
230
|
+
destination_domain = src_info[ :destination_domain ]
|
231
|
+
destination_port = src_info[ :destination_port ]
|
232
|
+
domain_port = [ destination_domain, destination_port ].join( ':' )
|
233
|
+
data = [ [ 0, A_NEW_SOURCE, src_info[ :id ] ].pack( 'Q>CQ>' ), @custom.encode( domain_port ) ].join
|
234
|
+
|
235
|
+
Thread.new do
|
236
|
+
EXPIRE_NEW.times do | i |
|
237
|
+
if src.closed? || src_info[ :dst_id ]
|
238
|
+
# puts "debug1 break loop send a new source #{ src_info[ :dst_port ] }"
|
239
|
+
break
|
240
|
+
end
|
241
|
+
|
242
|
+
@mutex.synchronize do
|
243
|
+
if i >= 1
|
244
|
+
puts "p#{ Process.pid } #{ Time.new } resend a new source #{ domain_port } #{ i }"
|
245
|
+
end
|
246
|
+
|
247
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
248
|
+
end
|
249
|
+
|
250
|
+
sleep CHECK_STATUS_INTERVAL
|
251
|
+
end
|
207
252
|
end
|
208
253
|
end
|
209
254
|
end
|
@@ -264,8 +309,10 @@ module Girl
|
|
264
309
|
# deal with destination ip
|
265
310
|
#
|
266
311
|
def deal_with_destination_ip( src, ip_info )
|
267
|
-
|
268
|
-
|
312
|
+
src_info = @src_infos[ src ]
|
313
|
+
|
314
|
+
if ( @directs.any? { | direct | direct.include?( ip_info.ip_address ) } ) || ( ( src_info[ :destination_domain ] == @proxyd_host ) && ![ 80, 443 ].include?( src_info[ :destination_port ] ) )
|
315
|
+
# ip命中直连列表,或者访问远端非80/443端口,直连
|
269
316
|
# puts "debug1 #{ ip_info.inspect } hit directs"
|
270
317
|
new_a_dst( src, ip_info )
|
271
318
|
else
|
@@ -302,15 +349,12 @@ module Girl
|
|
302
349
|
port = tun.local_address.ip_port
|
303
350
|
tun_info = {
|
304
351
|
port: port, # 端口
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
caches: [], # 块读出缓存 [ src_id, pack_id, data ]
|
309
|
-
chunks: [], # 块队列 filename
|
310
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
352
|
+
pending_sources: [], # 还没配上tund,暂存的src
|
353
|
+
wbuffs: [], # 写前 [ src_id, pack_id, data ]
|
354
|
+
wmems: {}, # 写后 [ src_id, pack_id ] => data
|
311
355
|
tund_addr: nil, # tund地址
|
312
|
-
|
313
|
-
src_ids: {}, #
|
356
|
+
srcs: {}, # src_id => src
|
357
|
+
src_ids: {}, # dst_id => src_id
|
314
358
|
paused: false, # 是否暂停写
|
315
359
|
resendings: [], # 重传队列 [ src_id, pack_id ]
|
316
360
|
created_at: Time.new, # 创建时间
|
@@ -322,10 +366,7 @@ module Girl
|
|
322
366
|
@tun_info = tun_info
|
323
367
|
|
324
368
|
add_read( tun, :tun )
|
325
|
-
|
326
|
-
puts "p#{ Process.pid } #{ Time.new } hello i'm tun"
|
327
|
-
# puts "debug1 #{ data.inspect }"
|
328
|
-
add_tun_ctlmsg( data, @proxyd_addr )
|
369
|
+
loop_send_hello
|
329
370
|
end
|
330
371
|
|
331
372
|
##
|
@@ -358,9 +399,6 @@ module Girl
|
|
358
399
|
src: src, # 对应src
|
359
400
|
domain: domain, # 域名
|
360
401
|
wbuff: '', # 写前
|
361
|
-
cache: '', # 块读出缓存
|
362
|
-
chunks: [], # 块队列,写前达到块大小时结一个块 filename
|
363
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
364
402
|
last_continue_at: Time.new, # 上一次发生流量的时间
|
365
403
|
is_closing: false # 是否准备关闭
|
366
404
|
}
|
@@ -374,11 +412,8 @@ module Girl
|
|
374
412
|
# puts "debug1 add src wbuff http ok"
|
375
413
|
add_src_wbuff( src, HTTP_OK )
|
376
414
|
else
|
377
|
-
# puts "debug1 add src
|
378
|
-
|
379
|
-
src_info[ :rbuffs ].each do | _, data |
|
380
|
-
add_dst_wbuff( dst, data )
|
381
|
-
end
|
415
|
+
# puts "debug1 add src rbuff to dst wbuff"
|
416
|
+
add_dst_wbuff( dst, src_info[ :rbuff ] )
|
382
417
|
end
|
383
418
|
elsif src_info[ :proxy_proto ] == :socks5
|
384
419
|
add_src_wbuff_socks5_conn_reply( src )
|
@@ -394,31 +429,15 @@ module Girl
|
|
394
429
|
end
|
395
430
|
|
396
431
|
src_info = @src_infos[ src ]
|
397
|
-
src_id = src_info[ :id ]
|
398
|
-
destination_port = src_info[ :destination_port ]
|
399
|
-
destination_domain = src_info[ :destination_domain ]
|
400
|
-
|
401
|
-
src_ext = {
|
402
|
-
src: src, # src
|
403
|
-
dst_port: nil, # 远端dst端口
|
404
|
-
destination_domain: destination_domain, # 目的地域名
|
405
|
-
wmems: {}, # 写后 pack_id => data
|
406
|
-
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
407
|
-
relay_pack_id: 0, # 转发到几
|
408
|
-
continue_dst_pack_id: 0, # 收到几
|
409
|
-
pieces: {}, # 跳号包 dst_pack_id => data
|
410
|
-
is_dst_closed: false, # dst是否已关闭
|
411
|
-
biggest_dst_pack_id: 0, # dst最大包号码
|
412
|
-
completed_pack_id: 0, # 完成到几(对面收到几)
|
413
|
-
last_continue_at: Time.new # 上一次发生流量的时间
|
414
|
-
}
|
415
|
-
|
416
|
-
@tun_info[ :src_exts ][ src_id ] = src_ext
|
417
432
|
src_info[ :proxy_type ] = :tunnel
|
433
|
+
src_id = src_info[ :id ]
|
434
|
+
@tun_info[ :srcs ][ src_id ] = src
|
418
435
|
|
419
|
-
|
420
|
-
|
421
|
-
|
436
|
+
if @tun_info[ :tund_addr ]
|
437
|
+
loop_send_a_new_source( src )
|
438
|
+
else
|
439
|
+
@tun_info[ :pending_sources ] << src
|
440
|
+
end
|
422
441
|
end
|
423
442
|
|
424
443
|
##
|
@@ -457,75 +476,12 @@ module Girl
|
|
457
476
|
[ data, domain_and_port ]
|
458
477
|
end
|
459
478
|
|
460
|
-
##
|
461
|
-
# add tun ctlmsg
|
462
|
-
#
|
463
|
-
def add_tun_ctlmsg( data, to_addr = nil )
|
464
|
-
unless to_addr
|
465
|
-
to_addr = @tun_info[ :tund_addr ]
|
466
|
-
end
|
467
|
-
|
468
|
-
if to_addr
|
469
|
-
@tun_info[ :ctlmsgs ] << [ to_addr, data ]
|
470
|
-
add_write( @tun )
|
471
|
-
else
|
472
|
-
@tun_info[ :ctlmsg_rbuffs ] << data
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
##
|
477
|
-
# add tun wbuff
|
478
|
-
#
|
479
|
-
def add_tun_wbuff( src_id, pack_id, data )
|
480
|
-
@tun_info[ :wbuffs ] << [ src_id, pack_id, data ]
|
481
|
-
|
482
|
-
if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
|
483
|
-
spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
|
484
|
-
filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
|
485
|
-
chunk_path = File.join( @tun_chunk_dir, filename )
|
486
|
-
datas = @tun_info[ :wbuffs ].map{ | _src_id, _pack_id, _data | [ [ _src_id, _pack_id, _data.bytesize ].pack( 'Q>Q>n' ), _data ].join }
|
487
|
-
|
488
|
-
begin
|
489
|
-
IO.binwrite( chunk_path, datas.join )
|
490
|
-
rescue Errno::ENOSPC => e
|
491
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tun"
|
492
|
-
set_is_closing( @tun )
|
493
|
-
return
|
494
|
-
end
|
495
|
-
|
496
|
-
@tun_info[ :chunks ] << filename
|
497
|
-
@tun_info[ :spring ] = spring
|
498
|
-
@tun_info[ :wbuffs ].clear
|
499
|
-
end
|
500
|
-
|
501
|
-
add_write( @tun )
|
502
|
-
end
|
503
|
-
|
504
479
|
##
|
505
480
|
# add src wbuff
|
506
481
|
#
|
507
482
|
def add_src_wbuff( src, data )
|
508
483
|
src_info = @src_infos[ src ]
|
509
484
|
src_info[ :wbuff ] << data
|
510
|
-
|
511
|
-
if src_info[ :wbuff ].bytesize >= CHUNK_SIZE
|
512
|
-
spring = src_info[ :chunks ].size > 0 ? ( src_info[ :spring ] + 1 ) : 0
|
513
|
-
filename = "#{ Process.pid }-#{ src_info[ :id ] }.#{ spring }"
|
514
|
-
chunk_path = File.join( @src_chunk_dir, filename )
|
515
|
-
|
516
|
-
begin
|
517
|
-
IO.binwrite( chunk_path, src_info[ :wbuff ] )
|
518
|
-
rescue Errno::ENOSPC => e
|
519
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close src"
|
520
|
-
set_is_closing( src )
|
521
|
-
return
|
522
|
-
end
|
523
|
-
|
524
|
-
src_info[ :chunks ] << filename
|
525
|
-
src_info[ :spring ] = spring
|
526
|
-
src_info[ :wbuff ].clear
|
527
|
-
end
|
528
|
-
|
529
485
|
add_write( src )
|
530
486
|
end
|
531
487
|
|
@@ -535,37 +491,20 @@ module Girl
|
|
535
491
|
def add_dst_wbuff( dst, data )
|
536
492
|
dst_info = @dst_infos[ dst ]
|
537
493
|
dst_info[ :wbuff ] << data
|
538
|
-
|
539
|
-
if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
|
540
|
-
spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
|
541
|
-
filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
|
542
|
-
chunk_path = File.join( @dst_chunk_dir, filename )
|
543
|
-
|
544
|
-
begin
|
545
|
-
IO.binwrite( chunk_path, dst_info[ :wbuff ] )
|
546
|
-
rescue Errno::ENOSPC => e
|
547
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close dst"
|
548
|
-
set_is_closing( dst )
|
549
|
-
return
|
550
|
-
end
|
551
|
-
|
552
|
-
dst_info[ :chunks ] << filename
|
553
|
-
dst_info[ :spring ] = spring
|
554
|
-
dst_info[ :wbuff ].clear
|
555
|
-
end
|
556
|
-
|
557
494
|
add_write( dst )
|
558
495
|
end
|
559
496
|
|
560
497
|
##
|
561
498
|
# add read
|
562
499
|
#
|
563
|
-
def add_read( sock, role )
|
564
|
-
|
500
|
+
def add_read( sock, role = nil )
|
501
|
+
if sock && !sock.closed? && !@reads.include?( sock )
|
565
502
|
@reads << sock
|
566
|
-
end
|
567
503
|
|
568
|
-
|
504
|
+
if role
|
505
|
+
@roles[ sock ] = role
|
506
|
+
end
|
507
|
+
end
|
569
508
|
end
|
570
509
|
|
571
510
|
##
|
@@ -577,6 +516,17 @@ module Girl
|
|
577
516
|
end
|
578
517
|
end
|
579
518
|
|
519
|
+
##
|
520
|
+
# add pause src
|
521
|
+
#
|
522
|
+
def add_pause_src( src )
|
523
|
+
@reads.delete( src )
|
524
|
+
|
525
|
+
unless @pause_srcs.include?( src )
|
526
|
+
@pause_srcs << src
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
580
530
|
##
|
581
531
|
# set is closing
|
582
532
|
#
|
@@ -601,10 +551,52 @@ module Girl
|
|
601
551
|
end
|
602
552
|
end
|
603
553
|
|
554
|
+
##
|
555
|
+
# tunnel data
|
556
|
+
#
|
557
|
+
def tunnel_data( src, data )
|
558
|
+
src_info = @src_infos[ src ]
|
559
|
+
src_id = src_info[ :id ]
|
560
|
+
now = Time.new
|
561
|
+
pack_id = src_info[ :biggest_pack_id ]
|
562
|
+
idx = 0
|
563
|
+
len = data.bytesize
|
564
|
+
|
565
|
+
while idx < len
|
566
|
+
chunk = data[ idx, PACK_SIZE ]
|
567
|
+
pack_id += 1
|
568
|
+
|
569
|
+
if pack_id <= CONFUSE_UNTIL
|
570
|
+
chunk = @custom.encode( chunk )
|
571
|
+
# puts "debug1 encoded chunk #{ pack_id }"
|
572
|
+
end
|
573
|
+
|
574
|
+
data2 = [ [ pack_id, src_id ].pack( 'Q>Q>' ), chunk ].join
|
575
|
+
sent = send_data( @tun, data2, @tun_info[ :tund_addr ] )
|
576
|
+
# puts "debug2 written pack #{ pack_id } #{ sent }"
|
577
|
+
@tun_info[ :wmems ][ [ src_id, pack_id ] ] = data2
|
578
|
+
src_info[ :send_ats ][ pack_id ] = now
|
579
|
+
idx += PACK_SIZE
|
580
|
+
end
|
581
|
+
|
582
|
+
src_info[ :biggest_pack_id ] = pack_id
|
583
|
+
src_info[ :last_continue_at ] = now
|
584
|
+
|
585
|
+
# 写后超过上限,暂停读src
|
586
|
+
if @tun_info[ :wmems ].size >= WMEMS_LIMIT
|
587
|
+
puts "p#{ Process.pid } #{ Time.new } pause src #{ src_id } #{ src_info[ :destination_domain ] } #{ src_info[ :biggest_pack_id ] }"
|
588
|
+
add_pause_src( src )
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
604
592
|
##
|
605
593
|
# send data
|
606
594
|
#
|
607
595
|
def send_data( tun, data, to_addr )
|
596
|
+
unless to_addr
|
597
|
+
return false
|
598
|
+
end
|
599
|
+
|
608
600
|
begin
|
609
601
|
tun.sendmsg( data, 0, to_addr )
|
610
602
|
rescue IO::WaitWritable, Errno::EINTR
|
@@ -624,36 +616,36 @@ module Girl
|
|
624
616
|
def close_src( src )
|
625
617
|
# puts "debug1 close src"
|
626
618
|
close_sock( src )
|
627
|
-
|
619
|
+
@pause_srcs.delete( src )
|
620
|
+
src_info = @src_infos[ src ]
|
628
621
|
|
629
|
-
src_info[ :
|
630
|
-
|
631
|
-
|
632
|
-
|
622
|
+
if src_info[ :proxy_type ] == :direct
|
623
|
+
@src_infos.delete( src )
|
624
|
+
|
625
|
+
if src_info[ :dst ]
|
626
|
+
set_is_closing( src_info[ :dst ] )
|
633
627
|
end
|
634
|
-
end
|
635
628
|
|
636
|
-
|
629
|
+
return
|
630
|
+
end
|
637
631
|
|
638
|
-
if src_info[ :
|
639
|
-
|
632
|
+
if @tun.closed? || src_info[ :dst_id ].nil?
|
633
|
+
@src_infos.delete( src )
|
634
|
+
return
|
635
|
+
end
|
640
636
|
|
641
|
-
|
642
|
-
return if src_ext.nil? || src_ext[ :dst_port ].nil?
|
637
|
+
src_id = src_info[ :id ]
|
643
638
|
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
|
652
|
-
add_tun_ctlmsg( data )
|
653
|
-
end
|
654
|
-
elsif src_info[ :proxy_type ] == :direct
|
655
|
-
set_is_closing( src_info[ :dst ] )
|
639
|
+
if src_info[ :is_dst_closed ]
|
640
|
+
# puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
|
641
|
+
del_src_ext( src_id )
|
642
|
+
data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
|
643
|
+
else
|
644
|
+
# puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
|
645
|
+
data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
|
656
646
|
end
|
647
|
+
|
648
|
+
send_data( @tun, data, @tun_info[ :tund_addr ] )
|
657
649
|
end
|
658
650
|
|
659
651
|
##
|
@@ -663,14 +655,6 @@ module Girl
|
|
663
655
|
# puts "debug1 close dst"
|
664
656
|
close_sock( dst )
|
665
657
|
dst_info = @dst_infos.delete( dst )
|
666
|
-
|
667
|
-
dst_info[ :chunks ].each do | filename |
|
668
|
-
begin
|
669
|
-
File.delete( File.join( @dst_chunk_dir, filename ) )
|
670
|
-
rescue Errno::ENOENT
|
671
|
-
end
|
672
|
-
end
|
673
|
-
|
674
658
|
set_is_closing( dst_info[ :src ] )
|
675
659
|
end
|
676
660
|
|
@@ -680,15 +664,7 @@ module Girl
|
|
680
664
|
def close_tun( tun )
|
681
665
|
# puts "debug1 close tun"
|
682
666
|
close_sock( tun )
|
683
|
-
|
684
|
-
@tun_info[ :chunks ].each do | filename |
|
685
|
-
begin
|
686
|
-
File.delete( File.join( @tun_chunk_dir, filename ) )
|
687
|
-
rescue Errno::ENOENT
|
688
|
-
end
|
689
|
-
end
|
690
|
-
|
691
|
-
@tun_info[ :src_exts ].each{ | _, src_ext | set_is_closing( src_ext[ :src ] ) }
|
667
|
+
@tun_info[ :srcs ].each{ | _, src | set_is_closing( src ) }
|
692
668
|
end
|
693
669
|
|
694
670
|
##
|
@@ -705,27 +681,32 @@ module Girl
|
|
705
681
|
# del src ext
|
706
682
|
#
|
707
683
|
def del_src_ext( src_id )
|
708
|
-
|
684
|
+
@tun_info[ :wmems ].delete_if { | src_id_and_pack_id, _ | src_id_and_pack_id.first == src_id }
|
685
|
+
src = @tun_info[ :srcs ].delete( src_id )
|
709
686
|
|
710
|
-
if
|
711
|
-
|
687
|
+
if src
|
688
|
+
src_info = @src_infos.delete( src )
|
689
|
+
|
690
|
+
if src_info
|
691
|
+
@tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
|
692
|
+
end
|
712
693
|
end
|
713
694
|
end
|
714
695
|
|
715
696
|
##
|
716
697
|
# release wmems
|
717
698
|
#
|
718
|
-
def release_wmems(
|
719
|
-
if completed_pack_id >
|
699
|
+
def release_wmems( src_info, completed_pack_id )
|
700
|
+
if completed_pack_id > src_info[ :completed_pack_id ]
|
720
701
|
# puts "debug2 update completed pack #{ completed_pack_id }"
|
721
|
-
pack_ids =
|
702
|
+
pack_ids = src_info[ :send_ats ].keys.select { | pack_id | pack_id <= completed_pack_id }
|
722
703
|
|
723
704
|
pack_ids.each do | pack_id |
|
724
|
-
|
725
|
-
|
705
|
+
@tun_info[ :wmems ].delete( [ src_info[ :id ], pack_id ] )
|
706
|
+
src_info[ :send_ats ].delete( pack_id )
|
726
707
|
end
|
727
708
|
|
728
|
-
|
709
|
+
src_info[ :completed_pack_id ] = completed_pack_id
|
729
710
|
end
|
730
711
|
end
|
731
712
|
|
@@ -741,32 +722,16 @@ module Girl
|
|
741
722
|
#
|
742
723
|
def write_src( src )
|
743
724
|
src_info = @src_infos[ src ]
|
744
|
-
from, data = :cache, src_info[ :cache ]
|
745
725
|
|
746
|
-
if
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
begin
|
751
|
-
data = src_info[ :cache ] = IO.binread( path )
|
752
|
-
File.delete( path )
|
753
|
-
rescue Errno::ENOENT => e
|
754
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
755
|
-
close_src( src )
|
756
|
-
return
|
757
|
-
end
|
758
|
-
else
|
759
|
-
from, data = :wbuff, src_info[ :wbuff ]
|
760
|
-
end
|
726
|
+
if src_info[ :is_closing ]
|
727
|
+
close_src( src )
|
728
|
+
return
|
761
729
|
end
|
762
730
|
|
763
|
-
|
764
|
-
if src_info[ :is_closing ]
|
765
|
-
close_src( src )
|
766
|
-
else
|
767
|
-
@writes.delete( src )
|
768
|
-
end
|
731
|
+
data = src_info[ :wbuff ]
|
769
732
|
|
733
|
+
if data.empty?
|
734
|
+
@writes.delete( src )
|
770
735
|
return
|
771
736
|
end
|
772
737
|
|
@@ -781,7 +746,7 @@ module Girl
|
|
781
746
|
|
782
747
|
# puts "debug2 write src #{ written }"
|
783
748
|
data = data[ written..-1 ]
|
784
|
-
src_info[
|
749
|
+
src_info[ :wbuff ] = data
|
785
750
|
src_info[ :last_continue_at ] = Time.new
|
786
751
|
end
|
787
752
|
|
@@ -790,32 +755,16 @@ module Girl
|
|
790
755
|
#
|
791
756
|
def write_dst( dst )
|
792
757
|
dst_info = @dst_infos[ dst ]
|
793
|
-
from, data = :cache, dst_info[ :cache ]
|
794
758
|
|
795
|
-
if
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
begin
|
800
|
-
data = dst_info[ :cache ] = IO.binread( path )
|
801
|
-
File.delete( path )
|
802
|
-
rescue Errno::ENOENT => e
|
803
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
804
|
-
close_dst( dst )
|
805
|
-
return
|
806
|
-
end
|
807
|
-
else
|
808
|
-
from, data = :wbuff, dst_info[ :wbuff ]
|
809
|
-
end
|
759
|
+
if dst_info[ :is_closing ]
|
760
|
+
close_dst( dst )
|
761
|
+
return
|
810
762
|
end
|
811
763
|
|
812
|
-
|
813
|
-
if dst_info[ :is_closing ]
|
814
|
-
close_dst( dst )
|
815
|
-
else
|
816
|
-
@writes.delete( dst )
|
817
|
-
end
|
764
|
+
data = dst_info[ :wbuff ]
|
818
765
|
|
766
|
+
if data.empty?
|
767
|
+
@writes.delete( dst )
|
819
768
|
return
|
820
769
|
end
|
821
770
|
|
@@ -831,7 +780,7 @@ module Girl
|
|
831
780
|
|
832
781
|
# puts "debug2 write dst #{ written }"
|
833
782
|
data = data[ written..-1 ]
|
834
|
-
dst_info[
|
783
|
+
dst_info[ :wbuff ] = data
|
835
784
|
dst_info[ :last_continue_at ] = Time.new
|
836
785
|
end
|
837
786
|
|
@@ -844,106 +793,7 @@ module Girl
|
|
844
793
|
return
|
845
794
|
end
|
846
795
|
|
847
|
-
|
848
|
-
|
849
|
-
# 传ctlmsg
|
850
|
-
while @tun_info[ :ctlmsgs ].any?
|
851
|
-
to_addr, data = @tun_info[ :ctlmsgs ].first
|
852
|
-
|
853
|
-
unless send_data( tun, data, to_addr )
|
854
|
-
return
|
855
|
-
end
|
856
|
-
|
857
|
-
@tun_info[ :ctlmsgs ].shift
|
858
|
-
end
|
859
|
-
|
860
|
-
# 重传
|
861
|
-
while @tun_info[ :resendings ].any?
|
862
|
-
src_id, pack_id = @tun_info[ :resendings ].first
|
863
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
864
|
-
|
865
|
-
if src_ext
|
866
|
-
data = src_ext[ :wmems ][ pack_id ]
|
867
|
-
|
868
|
-
if data
|
869
|
-
unless send_data( tun, data, @tun_info[ :tund_addr ] )
|
870
|
-
return
|
871
|
-
end
|
872
|
-
|
873
|
-
src_ext[ :last_continue_at ] = now
|
874
|
-
end
|
875
|
-
end
|
876
|
-
|
877
|
-
@tun_info[ :resendings ].shift
|
878
|
-
end
|
879
|
-
|
880
|
-
# 若写后达到上限,暂停取写前
|
881
|
-
if @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
|
882
|
-
unless @tun_info[ :paused ]
|
883
|
-
puts "p#{ Process.pid } #{ Time.new } pause tun"
|
884
|
-
@tun_info[ :paused ] = true
|
885
|
-
end
|
886
|
-
|
887
|
-
@writes.delete( tun )
|
888
|
-
return
|
889
|
-
end
|
890
|
-
|
891
|
-
# 取写前
|
892
|
-
if @tun_info[ :caches ].any?
|
893
|
-
datas = @tun_info[ :caches ]
|
894
|
-
elsif @tun_info[ :chunks ].any?
|
895
|
-
path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
|
896
|
-
|
897
|
-
begin
|
898
|
-
data = IO.binread( path )
|
899
|
-
File.delete( path )
|
900
|
-
rescue Errno::ENOENT => e
|
901
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
902
|
-
close_tun( tun )
|
903
|
-
return
|
904
|
-
end
|
905
|
-
|
906
|
-
caches = []
|
907
|
-
|
908
|
-
until data.empty?
|
909
|
-
_src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
|
910
|
-
caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
|
911
|
-
data = data[ ( 18 + pack_size )..-1 ]
|
912
|
-
end
|
913
|
-
|
914
|
-
datas = @tun_info[ :caches ] = caches
|
915
|
-
elsif @tun_info[ :wbuffs ].any?
|
916
|
-
datas = @tun_info[ :wbuffs ]
|
917
|
-
else
|
918
|
-
@writes.delete( tun )
|
919
|
-
return
|
920
|
-
end
|
921
|
-
|
922
|
-
while datas.any?
|
923
|
-
src_id, pack_id, data = datas.first
|
924
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
925
|
-
|
926
|
-
if src_ext
|
927
|
-
if pack_id <= CONFUSE_UNTIL
|
928
|
-
data = @custom.encode( data )
|
929
|
-
# puts "debug1 encoded pack #{ pack_id }"
|
930
|
-
end
|
931
|
-
|
932
|
-
data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
|
933
|
-
|
934
|
-
unless send_data( tun, data, @tun_info[ :tund_addr ] )
|
935
|
-
return
|
936
|
-
end
|
937
|
-
|
938
|
-
# puts "debug2 written pack #{ pack_id }"
|
939
|
-
src_ext[ :relay_pack_id ] = pack_id
|
940
|
-
src_ext[ :wmems ][ pack_id ] = data
|
941
|
-
src_ext[ :send_ats ][ pack_id ] = now
|
942
|
-
src_ext[ :last_continue_at ] = now
|
943
|
-
end
|
944
|
-
|
945
|
-
datas.shift
|
946
|
-
end
|
796
|
+
@writes.delete( tun )
|
947
797
|
end
|
948
798
|
|
949
799
|
##
|
@@ -963,11 +813,11 @@ module Girl
|
|
963
813
|
return
|
964
814
|
end
|
965
815
|
|
966
|
-
|
967
|
-
# puts "debug1 accept a src #{ addrinfo.inspect } #{
|
816
|
+
src_id = rand( ( 2 ** 64 ) - 2 ) + 1
|
817
|
+
# puts "debug1 accept a src #{ addrinfo.inspect } #{ src_id }"
|
968
818
|
|
969
819
|
@src_infos[ src ] = {
|
970
|
-
id:
|
820
|
+
id: src_id, # id
|
971
821
|
proxy_proto: :uncheck, # :uncheck / :http / :socks5
|
972
822
|
proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
|
973
823
|
dst: nil, # :direct的场合,对应的dst
|
@@ -975,11 +825,15 @@ module Girl
|
|
975
825
|
destination_port: nil, # 目的地端口
|
976
826
|
biggest_pack_id: 0, # 最大包号码
|
977
827
|
is_connect: true, # 代理协议是http的场合,是否是CONNECT
|
978
|
-
|
828
|
+
rbuff: '', # 非CONNECT,dst或者远端dst未准备好,暂存流量
|
979
829
|
wbuff: '', # 写前
|
980
|
-
|
981
|
-
|
982
|
-
|
830
|
+
dst_id: nil, # 远端dst id
|
831
|
+
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
832
|
+
continue_dst_pack_id: 0, # 收到几
|
833
|
+
pieces: {}, # 跳号包 dst_pack_id => data
|
834
|
+
is_dst_closed: false, # dst是否已关闭
|
835
|
+
biggest_dst_pack_id: 0, # dst最大包号码
|
836
|
+
completed_pack_id: 0, # 完成到几(对面收到几)
|
983
837
|
last_continue_at: Time.new, # 上一次发生流量的时间
|
984
838
|
is_closing: false # 是否准备关闭
|
985
839
|
}
|
@@ -992,7 +846,7 @@ module Girl
|
|
992
846
|
#
|
993
847
|
def read_src( src )
|
994
848
|
begin
|
995
|
-
data = src.read_nonblock(
|
849
|
+
data = src.read_nonblock( READ_SIZE )
|
996
850
|
rescue IO::WaitReadable, Errno::EINTR
|
997
851
|
return
|
998
852
|
rescue Exception => e
|
@@ -1072,9 +926,7 @@ module Girl
|
|
1072
926
|
end
|
1073
927
|
|
1074
928
|
src_info[ :is_connect ] = false
|
1075
|
-
|
1076
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1077
|
-
src_info[ :rbuffs ] << [ pack_id, data ]
|
929
|
+
src_info[ :rbuff ] << data
|
1078
930
|
end
|
1079
931
|
|
1080
932
|
domain, port = domain_and_port.split( ':' )
|
@@ -1087,9 +939,7 @@ module Girl
|
|
1087
939
|
resolve_domain( src, domain )
|
1088
940
|
when :checking
|
1089
941
|
# puts "debug1 add src rbuff while checking #{ data.inspect }"
|
1090
|
-
|
1091
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1092
|
-
src_info[ :rbuffs ] << [ pack_id, data ]
|
942
|
+
src_info[ :rbuff ] << data
|
1093
943
|
when :negotiation
|
1094
944
|
# +----+-----+-------+------+----------+----------+
|
1095
945
|
# |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
|
@@ -1127,19 +977,7 @@ module Girl
|
|
1127
977
|
puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
|
1128
978
|
end
|
1129
979
|
when :tunnel
|
1130
|
-
|
1131
|
-
src_ext = @tun_info[ :src_exts ][ src_id ]
|
1132
|
-
|
1133
|
-
unless src_ext
|
1134
|
-
# puts "debug1 not found src ext"
|
1135
|
-
set_is_closing( src )
|
1136
|
-
return
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
pack_id = src_info[ :biggest_pack_id ] + 1
|
1140
|
-
src_info[ :biggest_pack_id ] = pack_id
|
1141
|
-
|
1142
|
-
if src_ext[ :dst_port ]
|
980
|
+
if src_info[ :dst_id ]
|
1143
981
|
if @tun.closed?
|
1144
982
|
# puts "debug1 tun closed, close src"
|
1145
983
|
set_is_closing( src )
|
@@ -1150,10 +988,10 @@ module Girl
|
|
1150
988
|
data, _ = sub_http_request( data )
|
1151
989
|
end
|
1152
990
|
|
1153
|
-
|
991
|
+
tunnel_data( src, data )
|
1154
992
|
else
|
1155
993
|
# puts "debug1 remote dst not ready, save data to src rbuff"
|
1156
|
-
src_info[ :
|
994
|
+
src_info[ :rbuff ] << data
|
1157
995
|
end
|
1158
996
|
when :direct
|
1159
997
|
dst = src_info[ :dst ]
|
@@ -1172,7 +1010,7 @@ module Girl
|
|
1172
1010
|
add_dst_wbuff( dst, data )
|
1173
1011
|
else
|
1174
1012
|
# puts "debug1 dst not ready, save data to src rbuff"
|
1175
|
-
src_info[ :
|
1013
|
+
src_info[ :rbuff ] << data
|
1176
1014
|
end
|
1177
1015
|
end
|
1178
1016
|
end
|
@@ -1182,7 +1020,7 @@ module Girl
|
|
1182
1020
|
#
|
1183
1021
|
def read_dst( dst )
|
1184
1022
|
begin
|
1185
|
-
data = dst.read_nonblock(
|
1023
|
+
data = dst.read_nonblock( READ_SIZE )
|
1186
1024
|
rescue IO::WaitReadable, Errno::EINTR
|
1187
1025
|
return
|
1188
1026
|
rescue Exception => e
|
@@ -1224,143 +1062,194 @@ module Girl
|
|
1224
1062
|
|
1225
1063
|
tund_port = data[ 9, 2 ].unpack( 'n' ).first
|
1226
1064
|
|
1227
|
-
|
1065
|
+
puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
|
1228
1066
|
tund_addr = Socket.sockaddr_in( tund_port, @proxyd_host )
|
1229
1067
|
@tun_info[ :tund_addr ] = tund_addr
|
1230
1068
|
|
1231
|
-
if @tun_info[ :
|
1232
|
-
|
1233
|
-
|
1234
|
-
@tun_info[ :
|
1235
|
-
|
1069
|
+
if @tun_info[ :pending_sources ].any?
|
1070
|
+
puts "p#{ Process.pid } #{ Time.new } send pending sources"
|
1071
|
+
|
1072
|
+
@tun_info[ :pending_sources ].each do | src |
|
1073
|
+
loop_send_a_new_source( src )
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
@tun_info[ :pending_sources ].clear
|
1236
1077
|
end
|
1237
1078
|
when PAIRED
|
1238
1079
|
return if from_addr != @tun_info[ :tund_addr ]
|
1239
1080
|
|
1240
|
-
src_id,
|
1081
|
+
src_id, dst_id = data[ 9, 10 ].unpack( 'Q>n' )
|
1241
1082
|
|
1242
|
-
|
1243
|
-
return if src_ext.nil? || src_ext[ :dst_port ]
|
1244
|
-
|
1245
|
-
src = src_ext[ :src ]
|
1083
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1246
1084
|
return if src.closed?
|
1247
1085
|
|
1248
|
-
|
1086
|
+
src_info = @src_infos[ src ]
|
1087
|
+
return if src_info[ :dst_id ]
|
1088
|
+
|
1089
|
+
# puts "debug1 got paired #{ src_id } #{ dst_id }"
|
1249
1090
|
|
1250
|
-
if
|
1091
|
+
if dst_id == 0
|
1251
1092
|
set_is_closing( src )
|
1252
1093
|
return
|
1253
1094
|
end
|
1254
1095
|
|
1255
|
-
|
1256
|
-
@tun_info[ :src_ids ][
|
1257
|
-
|
1258
|
-
src_info = @src_infos[ src ]
|
1096
|
+
src_info[ :dst_id ] = dst_id
|
1097
|
+
@tun_info[ :src_ids ][ dst_id ] = src_id
|
1259
1098
|
|
1260
1099
|
if src_info[ :proxy_proto ] == :http
|
1261
1100
|
if src_info[ :is_connect ]
|
1262
1101
|
# puts "debug1 add src wbuff http ok"
|
1263
1102
|
add_src_wbuff( src, HTTP_OK )
|
1264
1103
|
else
|
1265
|
-
# puts "debug1
|
1266
|
-
|
1267
|
-
src_info[ :rbuffs ].each do | pack_id, _data |
|
1268
|
-
add_tun_wbuff( src_id, pack_id, _data )
|
1269
|
-
end
|
1104
|
+
# puts "debug1 send src rbuff to tund"
|
1105
|
+
tunnel_data( src, src_info[ :rbuff ] )
|
1270
1106
|
end
|
1271
1107
|
elsif src_info[ :proxy_proto ] == :socks5
|
1272
|
-
add_src_wbuff_socks5_conn_reply(
|
1108
|
+
add_src_wbuff_socks5_conn_reply( src )
|
1273
1109
|
end
|
1274
1110
|
when DEST_STATUS
|
1275
1111
|
return if from_addr != @tun_info[ :tund_addr ]
|
1276
1112
|
|
1277
|
-
|
1113
|
+
dst_id, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
1278
1114
|
|
1279
|
-
src_id = @tun_info[ :src_ids ][
|
1115
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1280
1116
|
return unless src_id
|
1281
1117
|
|
1282
|
-
|
1283
|
-
return unless
|
1118
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1119
|
+
return unless src
|
1120
|
+
|
1121
|
+
src_info = @src_infos[ src ]
|
1122
|
+
return unless src_info
|
1284
1123
|
|
1285
|
-
# puts "debug2 got dest status"
|
1124
|
+
# puts "debug2 got dest status #{ Time.new }"
|
1286
1125
|
|
1287
|
-
|
1126
|
+
# 消写后
|
1127
|
+
release_wmems( src_info, continue_src_pack_id )
|
1288
1128
|
|
1289
1129
|
# 发miss
|
1290
|
-
if !
|
1130
|
+
if !src.closed? && ( src_info[ :continue_dst_pack_id ] < relay_dst_pack_id )
|
1291
1131
|
ranges = []
|
1292
|
-
|
1132
|
+
ignored = false
|
1133
|
+
curr_pack_id = src_info[ :continue_dst_pack_id ] + 1
|
1293
1134
|
|
1294
|
-
|
1135
|
+
src_info[ :pieces ].keys.sort.each do | pack_id |
|
1295
1136
|
if pack_id > curr_pack_id
|
1296
1137
|
ranges << [ curr_pack_id, pack_id - 1 ]
|
1138
|
+
|
1139
|
+
if ranges.size >= MISS_RANGE_LIMIT
|
1140
|
+
puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
|
1141
|
+
ignored = true
|
1142
|
+
break
|
1143
|
+
end
|
1297
1144
|
end
|
1298
1145
|
|
1299
1146
|
curr_pack_id = pack_id + 1
|
1300
1147
|
end
|
1301
1148
|
|
1302
|
-
if curr_pack_id <= relay_dst_pack_id
|
1149
|
+
if !ignored && ( curr_pack_id <= relay_dst_pack_id )
|
1303
1150
|
ranges << [ curr_pack_id, relay_dst_pack_id ]
|
1304
1151
|
end
|
1305
1152
|
|
1306
|
-
|
1307
|
-
|
1153
|
+
# puts "debug1 continue/relay #{ src_info[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
|
1154
|
+
idx = 0
|
1155
|
+
ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
|
1308
1156
|
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1157
|
+
while idx < ranges.size
|
1158
|
+
chunk = ranges[ idx, MULTI_MISS_SIZE ].join
|
1159
|
+
data2 = [ [ 0, MULTI_MISS, dst_id ].pack( 'Q>Cn' ), chunk ].join
|
1160
|
+
send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1161
|
+
idx += MULTI_MISS_SIZE
|
1162
|
+
end
|
1163
|
+
end
|
1164
|
+
when MULTI_MISS
|
1165
|
+
src_id, *ranges = data[ 9..-1 ].unpack( 'Q>Q>*' )
|
1166
|
+
|
1167
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1168
|
+
return unless src
|
1169
|
+
|
1170
|
+
src_info = @src_infos[ src ]
|
1171
|
+
return unless src_info
|
1172
|
+
|
1173
|
+
return if ranges.empty? || ( ranges.size % 2 != 0 )
|
1314
1174
|
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1175
|
+
# puts "debug1 got multi miss #{ src_id } #{ ranges.size }"
|
1176
|
+
|
1177
|
+
idx = 0
|
1178
|
+
|
1179
|
+
while idx < ranges.size
|
1180
|
+
pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
|
1181
|
+
|
1182
|
+
( pack_id_begin..pack_id_end ).each do | pack_id |
|
1183
|
+
send_at = src_info[ :send_ats ][ pack_id ]
|
1184
|
+
|
1185
|
+
if send_at
|
1186
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
1187
|
+
data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
|
1188
|
+
|
1189
|
+
if data2
|
1190
|
+
if send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1191
|
+
src_info[ :last_continue_at ] = now
|
1192
|
+
end
|
1193
|
+
end
|
1194
|
+
end
|
1318
1195
|
end
|
1196
|
+
|
1197
|
+
idx += 2
|
1319
1198
|
end
|
1320
1199
|
when MISS
|
1321
1200
|
return if from_addr != @tun_info[ :tund_addr ]
|
1322
1201
|
|
1323
1202
|
src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
1324
1203
|
|
1325
|
-
|
1326
|
-
return unless
|
1204
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1205
|
+
return unless src
|
1206
|
+
|
1207
|
+
src_info = @src_infos[ src ]
|
1208
|
+
return unless src_info
|
1327
1209
|
|
1328
1210
|
( pack_id_begin..pack_id_end ).each do | pack_id |
|
1329
|
-
send_at =
|
1211
|
+
send_at = src_info[ :send_ats ][ pack_id ]
|
1330
1212
|
|
1331
1213
|
if send_at
|
1332
|
-
break if now - send_at <
|
1333
|
-
@tun_info[ :
|
1214
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
1215
|
+
data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
|
1216
|
+
|
1217
|
+
if data2
|
1218
|
+
if send_data( tun, data2, @tun_info[ :tund_addr ] )
|
1219
|
+
src_info[ :last_continue_at ] = now
|
1220
|
+
end
|
1221
|
+
end
|
1334
1222
|
end
|
1335
1223
|
end
|
1336
|
-
|
1337
|
-
add_write( tun )
|
1338
1224
|
when FIN1
|
1339
1225
|
return if from_addr != @tun_info[ :tund_addr ]
|
1340
1226
|
|
1341
|
-
|
1227
|
+
dst_id, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
1342
1228
|
|
1343
|
-
src_id = @tun_info[ :src_ids ][
|
1229
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1344
1230
|
return unless src_id
|
1345
1231
|
|
1346
|
-
|
1347
|
-
return unless
|
1232
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1233
|
+
return unless src
|
1348
1234
|
|
1349
|
-
|
1350
|
-
|
1351
|
-
src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
|
1352
|
-
release_wmems( src_ext, continue_src_pack_id )
|
1235
|
+
src_info = @src_infos[ src ]
|
1236
|
+
return unless src_info
|
1353
1237
|
|
1354
|
-
|
1238
|
+
# puts "debug1 got fin1 #{ dst_id } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
|
1239
|
+
src_info[ :is_dst_closed ] = true
|
1240
|
+
src_info[ :biggest_dst_pack_id ] = biggest_dst_pack_id
|
1241
|
+
release_wmems( src_info, continue_src_pack_id )
|
1242
|
+
|
1243
|
+
if ( biggest_dst_pack_id == src_info[ :continue_dst_pack_id ] )
|
1355
1244
|
# puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
|
1356
|
-
set_is_closing(
|
1245
|
+
set_is_closing( src )
|
1357
1246
|
end
|
1358
1247
|
when FIN2
|
1359
1248
|
return if from_addr != @tun_info[ :tund_addr ]
|
1360
1249
|
|
1361
|
-
|
1250
|
+
dst_id = data[ 9, 2 ].unpack( 'n' ).first
|
1362
1251
|
|
1363
|
-
src_id = @tun_info[ :src_ids ][
|
1252
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1364
1253
|
return unless src_id
|
1365
1254
|
|
1366
1255
|
# puts "debug1 1-2. tun recv fin2 -> del src ext"
|
@@ -1382,14 +1271,18 @@ module Girl
|
|
1382
1271
|
|
1383
1272
|
return if from_addr != @tun_info[ :tund_addr ]
|
1384
1273
|
|
1385
|
-
|
1274
|
+
dst_id = data[ 8, 2 ].unpack( 'n' ).first
|
1386
1275
|
|
1387
|
-
src_id = @tun_info[ :src_ids ][
|
1276
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1388
1277
|
return unless src_id
|
1389
1278
|
|
1390
|
-
|
1391
|
-
return
|
1392
|
-
|
1279
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1280
|
+
return unless src
|
1281
|
+
|
1282
|
+
src_info = @src_infos[ src ]
|
1283
|
+
return unless src_info
|
1284
|
+
|
1285
|
+
return if ( pack_id <= src_info[ :continue_dst_pack_id ] ) || src_info[ :pieces ].include?( pack_id )
|
1393
1286
|
|
1394
1287
|
data = data[ 10..-1 ]
|
1395
1288
|
# puts "debug2 got pack #{ pack_id }"
|
@@ -1401,24 +1294,25 @@ module Girl
|
|
1401
1294
|
end
|
1402
1295
|
|
1403
1296
|
# 放进写前,跳号放碎片缓存
|
1404
|
-
if pack_id -
|
1405
|
-
while
|
1406
|
-
data <<
|
1297
|
+
if pack_id - src_info[ :continue_dst_pack_id ] == 1
|
1298
|
+
while src_info[ :pieces ].include?( pack_id + 1 )
|
1299
|
+
data << src_info[ :pieces ].delete( pack_id + 1 )
|
1407
1300
|
pack_id += 1
|
1408
1301
|
end
|
1409
1302
|
|
1410
|
-
|
1411
|
-
|
1412
|
-
add_src_wbuff(
|
1303
|
+
src_info[ :continue_dst_pack_id ] = pack_id
|
1304
|
+
src_info[ :last_continue_at ] = now
|
1305
|
+
add_src_wbuff( src, data )
|
1413
1306
|
# puts "debug2 update continue dst pack #{ pack_id }"
|
1414
1307
|
|
1415
|
-
#
|
1416
|
-
if
|
1308
|
+
# 若对面已关闭,且流量正好收全,关闭src
|
1309
|
+
if src_info[ :is_dst_closed ] && ( pack_id == src_info[ :biggest_dst_pack_id ] )
|
1417
1310
|
# puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
|
1418
|
-
set_is_closing(
|
1311
|
+
set_is_closing( src )
|
1419
1312
|
end
|
1420
|
-
|
1421
|
-
|
1313
|
+
elsif !src_info[ :pieces ].include?( pack_id )
|
1314
|
+
src_info[ :pieces ][ pack_id ] = data
|
1315
|
+
src_info[ :last_continue_at ] = now
|
1422
1316
|
end
|
1423
1317
|
end
|
1424
1318
|
|