girl 3.9.0 → 4.4.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/concurrent_hash.rb +4 -0
- data/lib/girl/{custom_dns_query.rb → custom.rb} +1 -1
- data/lib/girl/head.rb +11 -1
- data/lib/girl/proxy.rb +28 -31
- data/lib/girl/proxy_custom.rb +16 -13
- data/lib/girl/proxy_worker.rb +529 -604
- data/lib/girl/proxyd.rb +1 -15
- data/lib/girl/proxyd_custom.rb +12 -9
- data/lib/girl/proxyd_worker.rb +550 -472
- data/lib/girl/relay.rb +1 -2
- data/lib/girl/relay_worker.rb +498 -585
- data/lib/girl/resolv_custom.rb +2 -2
- data/lib/girl/resolvd_worker.rb +4 -4
- data/lib/girl/ssl.rb +1 -14
- data/lib/girl/ssl_worker.rb +131 -91
- 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: d7b905d2180abe835d892f44038fdf2f96b6710ad942fa2d762a2484430ea48f
|
4
|
+
data.tar.gz: d0a95baf185ce66219c7ce783c975d5bdd4bd9e00273ae77842f70697301ac40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6659b516924a9a43be0b7cf9c3d85ae8bda57e22d131089ae295f24ca7247d628e7d8fc795e6625cadac81a785b6390ae1ec3e170a42d5c3403e023879ff11ea
|
7
|
+
data.tar.gz: 6800db65291e870d6a87c3b22328a9415210c73b8535d5077609f0a957901a05f6832e621321ad9b5f2e78c609c640f1fe18ad8321e44ee195a4af7da2b62239
|
data/girl.gemspec
CHANGED
data/lib/girl/concurrent_hash.rb
CHANGED
data/lib/girl/head.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
module Girl
|
2
|
-
READ_SIZE = 1024 * 1024 # 一次读多少
|
2
|
+
READ_SIZE = 1024 * 1024 # atun, btun一次读多少
|
3
3
|
WBUFF_LIMIT = 50 * 1024 * 1024 # 写前上限,超过上限暂停读
|
4
4
|
RESUME_BELOW = WBUFF_LIMIT / 2 # 降到多少以下恢复读
|
5
5
|
EXPIRE_NEW = 5 # 多久没有建立通道,过期
|
6
6
|
EXPIRE_AFTER = 300 # 多久没有新流量,过期
|
7
|
+
EXPIRE_CTL = 86400 # 多久没有ctlmsg来,过期
|
7
8
|
RESET_TRAFF_DAY = 1 # 流量计数重置日,0为不重置
|
8
9
|
CHECK_TRAFF_INTERVAL = 86400 # 检查今天是否是流量计数重置日间隔
|
9
10
|
CHECK_EXPIRE_INTERVAL = 5 # 检查过期间隔
|
10
11
|
CHECK_RESUME_INTERVAL = 1 # 检查恢复读间隔
|
11
12
|
RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
|
13
|
+
RESEND_LIMIT = 5 # ctlmsg重传次数
|
14
|
+
RESEND_INTERVAL = 1 # ctlmsg重传间隔
|
12
15
|
HELLO = 1
|
13
16
|
TUND_PORT = 2
|
14
17
|
A_NEW_SOURCE = 3
|
@@ -31,6 +34,8 @@ module Girl
|
|
31
34
|
RESOLV = 20
|
32
35
|
RESOLVED = 21
|
33
36
|
HEARTBEAT = 22
|
37
|
+
UNKNOWN_CTL_ADDR = 23
|
38
|
+
CTL_FIN = 24
|
34
39
|
TRAFF_INFOS = 101
|
35
40
|
SEPARATE = "\r\n\r\n"
|
36
41
|
HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
|
@@ -49,8 +54,13 @@ EOF
|
|
49
54
|
RESUME_BELOW
|
50
55
|
EXPIRE_NEW
|
51
56
|
EXPIRE_AFTER
|
57
|
+
EXPIRE_CTL
|
58
|
+
RESET_TRAFF_DAY
|
59
|
+
CHECK_TRAFF_INTERVAL
|
52
60
|
CHECK_EXPIRE_INTERVAL
|
53
61
|
CHECK_RESUME_INTERVAL
|
54
62
|
RESOLV_CACHE_EXPIRE
|
63
|
+
RESEND_LIMIT
|
64
|
+
RESEND_INTERVAL
|
55
65
|
]
|
56
66
|
end
|
data/lib/girl/proxy.rb
CHANGED
@@ -6,7 +6,6 @@ require 'girl/proxy_worker'
|
|
6
6
|
require 'girl/version'
|
7
7
|
require 'ipaddr'
|
8
8
|
require 'json'
|
9
|
-
require 'openssl'
|
10
9
|
require 'socket'
|
11
10
|
|
12
11
|
##
|
@@ -14,29 +13,32 @@ require 'socket'
|
|
14
13
|
#
|
15
14
|
#
|
16
15
|
=begin
|
17
|
-
C: 1 hello
|
18
|
-
2 tund port
|
19
|
-
3 a new source
|
20
|
-
4 paired
|
21
|
-
5 dest status
|
22
|
-
6 source status
|
23
|
-
7 miss
|
24
|
-
8 fin1
|
25
|
-
9 confirm fin1
|
26
|
-
10 fin2
|
27
|
-
11 confirm fin2
|
28
|
-
12 tund fin
|
29
|
-
13 tun fin
|
30
|
-
14 tun ip changed
|
31
|
-
15 single miss
|
32
|
-
16 range miss
|
33
|
-
17 continue
|
34
|
-
18 is resend ready
|
35
|
-
19 resend ready
|
36
|
-
20 resolv
|
37
|
-
21 resolved
|
16
|
+
C: 1 hello -> hello
|
17
|
+
2 tund port -> n: atund port -> n: btund port
|
18
|
+
3 a new source -> Q>: src id -> destination
|
19
|
+
4 paired -> Q>: src id -> n: dst id
|
20
|
+
5 dest status NOT USE
|
21
|
+
6 source status NOT USE
|
22
|
+
7 miss NOT USE
|
23
|
+
8 fin1 NOT USE
|
24
|
+
9 confirm fin1 NOT USE
|
25
|
+
10 fin2 NOT USE
|
26
|
+
11 confirm fin2 NOT USE
|
27
|
+
12 tund fin NOT USE
|
28
|
+
13 tun fin NOT USE
|
29
|
+
14 tun ip changed NOT USE
|
30
|
+
15 single miss NOT USE
|
31
|
+
16 range miss NOT USE
|
32
|
+
17 continue NOT USE
|
33
|
+
18 is resend ready NOT USE
|
34
|
+
19 resend ready NOT USE
|
35
|
+
20 resolv NOT USE
|
36
|
+
21 resolved NOT USE
|
37
|
+
22 heartbeat NOT USE
|
38
|
+
23 unknown ctl addr
|
39
|
+
24 ctl fin
|
38
40
|
101 traff infos
|
39
|
-
101 traff infos
|
41
|
+
101 traff infos -> [ C: im len -> im -> Q>: traff in -> Q>: traff out ]
|
40
42
|
=end
|
41
43
|
|
42
44
|
module Girl
|
@@ -56,7 +58,6 @@ module Girl
|
|
56
58
|
direct_path = conf[ :direct_path ]
|
57
59
|
remote_path = conf[ :remote_path ]
|
58
60
|
im = conf[ :im ]
|
59
|
-
use_remote_resolv = conf[ :use_remote_resolv ]
|
60
61
|
worker_count = conf[ :worker_count ]
|
61
62
|
|
62
63
|
unless redir_port then
|
@@ -87,10 +88,6 @@ module Girl
|
|
87
88
|
im = 'girl'
|
88
89
|
end
|
89
90
|
|
90
|
-
unless use_remote_resolv then
|
91
|
-
use_remote_resolv = false
|
92
|
-
end
|
93
|
-
|
94
91
|
nprocessors = Etc.nprocessors
|
95
92
|
|
96
93
|
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
|
@@ -105,7 +102,7 @@ module Girl
|
|
105
102
|
|
106
103
|
title = "girl proxy #{ Girl::VERSION }"
|
107
104
|
puts title
|
108
|
-
puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im }
|
105
|
+
puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im } worker count #{ worker_count }"
|
109
106
|
puts "#{ direct_path } #{ directs.size } directs"
|
110
107
|
puts "#{ remote_path } #{ remotes.size } remotes"
|
111
108
|
|
@@ -116,7 +113,7 @@ module Girl
|
|
116
113
|
worker_count.times do | i |
|
117
114
|
workers << fork do
|
118
115
|
$0 = 'girl proxy worker'
|
119
|
-
worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im
|
116
|
+
worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
|
120
117
|
|
121
118
|
Signal.trap( :TERM ) do
|
122
119
|
puts "w#{ i } exit"
|
@@ -140,7 +137,7 @@ module Girl
|
|
140
137
|
|
141
138
|
Process.waitall
|
142
139
|
else
|
143
|
-
Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im
|
140
|
+
Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
|
144
141
|
end
|
145
142
|
end
|
146
143
|
|
data/lib/girl/proxy_custom.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
1
|
+
require 'girl/custom'
|
2
|
+
|
3
|
+
module Girl
|
4
|
+
class ProxyCustom
|
5
|
+
include Custom
|
6
|
+
|
7
|
+
def initialize( im )
|
8
|
+
@im = im
|
9
|
+
end
|
10
|
+
|
11
|
+
def hello
|
12
|
+
@im
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -4,28 +4,28 @@ module Girl
|
|
4
4
|
##
|
5
5
|
# initialize
|
6
6
|
#
|
7
|
-
def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im
|
7
|
+
def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
|
8
8
|
@proxyd_host = proxyd_host
|
9
|
+
@proxyd_port = proxyd_port
|
9
10
|
@proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
|
10
11
|
@directs = directs
|
11
12
|
@remotes = remotes
|
12
13
|
@custom = Girl::ProxyCustom.new( im )
|
13
|
-
@use_remote_resolv = use_remote_resolv
|
14
14
|
@reads = []
|
15
15
|
@writes = []
|
16
16
|
@closing_srcs = []
|
17
17
|
@paused_srcs = []
|
18
18
|
@paused_dsts = []
|
19
|
-
@
|
19
|
+
@paused_btuns = []
|
20
20
|
@resume_srcs = []
|
21
21
|
@resume_dsts = []
|
22
|
-
@
|
23
|
-
@pending_srcs = [] #
|
24
|
-
@roles = ConcurrentHash.new # sock => :dotr / :redir / :
|
22
|
+
@resume_btuns = []
|
23
|
+
@pending_srcs = [] # 还没得到atund和btund地址,暂存的src
|
24
|
+
@roles = ConcurrentHash.new # sock => :dotr / :redir / :ctl / :src / :dst / :atun / :btun
|
25
25
|
@src_infos = ConcurrentHash.new # src => {}
|
26
26
|
@dst_infos = ConcurrentHash.new # dst => {}
|
27
|
-
@
|
28
|
-
@
|
27
|
+
@atun_infos = ConcurrentHash.new # atun => {}
|
28
|
+
@btun_infos = ConcurrentHash.new # btun => {}
|
29
29
|
@resolv_caches = ConcurrentHash.new # domain => [ ip, created_at ]
|
30
30
|
@is_direct_caches = ConcurrentHash.new # ip => true / false
|
31
31
|
@srcs = ConcurrentHash.new # src_id => src
|
@@ -54,31 +54,27 @@ module Girl
|
|
54
54
|
read_dotr( sock )
|
55
55
|
when :redir then
|
56
56
|
read_redir( sock )
|
57
|
-
when :
|
58
|
-
|
57
|
+
when :ctl then
|
58
|
+
read_ctl( sock )
|
59
59
|
when :src then
|
60
60
|
read_src( sock )
|
61
61
|
when :dst then
|
62
62
|
read_dst( sock )
|
63
|
-
when :
|
64
|
-
|
63
|
+
when :btun then
|
64
|
+
read_btun( sock )
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
ws.each do | sock |
|
69
69
|
case @roles[ sock ]
|
70
|
-
when :proxy then
|
71
|
-
write_proxy( sock )
|
72
70
|
when :src then
|
73
71
|
write_src( sock )
|
74
72
|
when :dst then
|
75
73
|
write_dst( sock )
|
76
|
-
when :
|
77
|
-
|
78
|
-
when :
|
79
|
-
|
80
|
-
when :pre_tun then
|
81
|
-
write_pre_tun( sock )
|
74
|
+
when :atun then
|
75
|
+
write_atun( sock )
|
76
|
+
when :btun then
|
77
|
+
write_btun( sock )
|
82
78
|
end
|
83
79
|
end
|
84
80
|
end
|
@@ -91,13 +87,8 @@ module Girl
|
|
91
87
|
# quit!
|
92
88
|
#
|
93
89
|
def quit!
|
94
|
-
|
95
|
-
|
96
|
-
data = [ TUN_FIN ].pack( 'C' )
|
97
|
-
@proxy.write( data )
|
98
|
-
end
|
99
|
-
|
100
|
-
# puts "debug1 exit"
|
90
|
+
# puts "debug exit"
|
91
|
+
send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
|
101
92
|
exit
|
102
93
|
end
|
103
94
|
|
@@ -111,8 +102,24 @@ module Girl
|
|
111
102
|
destination_domain = src_info[ :destination_domain ]
|
112
103
|
destination_port = src_info[ :destination_port ]
|
113
104
|
domain_port = [ destination_domain, destination_port ].join( ':' )
|
114
|
-
|
115
|
-
|
105
|
+
# puts "debug add a new source #{ src_info[ :id ] } #{ domain_port }"
|
106
|
+
key = [ A_NEW_SOURCE, src_info[ :id ] ].pack( 'CQ>' )
|
107
|
+
add_ctlmsg( key, domain_port )
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# add atun wbuff
|
112
|
+
#
|
113
|
+
def add_atun_wbuff( atun, data )
|
114
|
+
return if atun.closed?
|
115
|
+
atun_info = @atun_infos[ atun ]
|
116
|
+
atun_info[ :wbuff ] << data
|
117
|
+
add_write( atun )
|
118
|
+
|
119
|
+
if atun_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
120
|
+
puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ atun_info[ :domain ] }"
|
121
|
+
add_paused_src( atun_info[ :src ] )
|
122
|
+
end
|
116
123
|
end
|
117
124
|
|
118
125
|
##
|
@@ -127,16 +134,18 @@ module Girl
|
|
127
134
|
##
|
128
135
|
# add ctlmsg
|
129
136
|
#
|
130
|
-
def add_ctlmsg( data )
|
131
|
-
|
132
|
-
|
133
|
-
|
137
|
+
def add_ctlmsg( key, data )
|
138
|
+
ctlmsg = "#{ key }#{ data }"
|
139
|
+
send_ctlmsg( ctlmsg )
|
140
|
+
@ctl_info[ :resends ][ key ] = 0
|
141
|
+
loop_resend_ctlmsg( key, ctlmsg )
|
134
142
|
end
|
135
143
|
|
136
144
|
##
|
137
145
|
# add dst wbuff
|
138
146
|
#
|
139
147
|
def add_dst_wbuff( dst, data )
|
148
|
+
return if dst.closed?
|
140
149
|
dst_info = @dst_infos[ dst ]
|
141
150
|
dst_info[ :wbuff ] << data
|
142
151
|
add_write( dst )
|
@@ -147,6 +156,15 @@ module Girl
|
|
147
156
|
end
|
148
157
|
end
|
149
158
|
|
159
|
+
##
|
160
|
+
# add paused btun
|
161
|
+
#
|
162
|
+
def add_paused_btun( btun )
|
163
|
+
return if btun.closed? || @paused_btuns.include?( btun )
|
164
|
+
@reads.delete( btun )
|
165
|
+
@paused_btuns << btun
|
166
|
+
end
|
167
|
+
|
150
168
|
##
|
151
169
|
# add paused dst
|
152
170
|
#
|
@@ -165,15 +183,6 @@ module Girl
|
|
165
183
|
@paused_srcs << src
|
166
184
|
end
|
167
185
|
|
168
|
-
##
|
169
|
-
# add paused tun
|
170
|
-
#
|
171
|
-
def add_paused_tun( tun )
|
172
|
-
return if tun.closed? || @paused_tuns.include?( tun )
|
173
|
-
@reads.delete( tun )
|
174
|
-
@paused_tuns << tun
|
175
|
-
end
|
176
|
-
|
177
186
|
##
|
178
187
|
# add read
|
179
188
|
#
|
@@ -188,6 +197,15 @@ module Girl
|
|
188
197
|
next_tick
|
189
198
|
end
|
190
199
|
|
200
|
+
##
|
201
|
+
# add resume btun
|
202
|
+
#
|
203
|
+
def add_resume_btun( btun )
|
204
|
+
return if @resume_btuns.include?( btun )
|
205
|
+
@resume_btuns << btun
|
206
|
+
next_tick
|
207
|
+
end
|
208
|
+
|
191
209
|
##
|
192
210
|
# add resume dst
|
193
211
|
#
|
@@ -206,15 +224,6 @@ module Girl
|
|
206
224
|
next_tick
|
207
225
|
end
|
208
226
|
|
209
|
-
##
|
210
|
-
# add resume tun
|
211
|
-
#
|
212
|
-
def add_resume_tun( tun )
|
213
|
-
return if @resume_tuns.include?( tun )
|
214
|
-
@resume_tuns << tun
|
215
|
-
next_tick
|
216
|
-
end
|
217
|
-
|
218
227
|
##
|
219
228
|
# add socks5 conn reply
|
220
229
|
#
|
@@ -226,7 +235,7 @@ module Girl
|
|
226
235
|
# +----+-----+-------+------+----------+----------+
|
227
236
|
redir_ip, redir_port = @redir_local_address.ip_unpack
|
228
237
|
data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( redir_ip ).hton, [ redir_port ].pack( 'n' ) ].join
|
229
|
-
# puts "
|
238
|
+
# puts "debug add src.wbuff socks5 conn reply #{ data.inspect }"
|
230
239
|
add_src_wbuff( src, data )
|
231
240
|
end
|
232
241
|
|
@@ -238,7 +247,7 @@ module Girl
|
|
238
247
|
src_info[ :rbuff ] << data
|
239
248
|
|
240
249
|
if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
|
241
|
-
# puts "
|
250
|
+
# puts "debug src.rbuff full"
|
242
251
|
add_closing_src( src )
|
243
252
|
end
|
244
253
|
end
|
@@ -260,30 +269,16 @@ module Girl
|
|
260
269
|
puts "p#{ Process.pid } #{ Time.new } pause dst #{ src_info[ :destination_domain ] }"
|
261
270
|
add_paused_dst( dst )
|
262
271
|
else
|
263
|
-
|
272
|
+
btun = src_info[ :btun ]
|
264
273
|
|
265
|
-
if
|
266
|
-
puts "p#{ Process.pid } #{ Time.new } pause
|
267
|
-
|
274
|
+
if btun then
|
275
|
+
puts "p#{ Process.pid } #{ Time.new } pause btun #{ src_info[ :destination_domain ] }"
|
276
|
+
add_paused_btun( btun )
|
268
277
|
end
|
269
278
|
end
|
270
279
|
end
|
271
280
|
end
|
272
281
|
|
273
|
-
##
|
274
|
-
# add tun wbuff
|
275
|
-
#
|
276
|
-
def add_tun_wbuff( tun, data )
|
277
|
-
tun_info = @tun_infos[ tun ]
|
278
|
-
tun_info[ :wbuff ] << data
|
279
|
-
add_write( tun )
|
280
|
-
|
281
|
-
if tun_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
282
|
-
puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ tun_info[ :domain ] }"
|
283
|
-
add_paused_src( tun_info[ :src ] )
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
282
|
##
|
288
283
|
# add write
|
289
284
|
#
|
@@ -294,32 +289,36 @@ module Girl
|
|
294
289
|
end
|
295
290
|
|
296
291
|
##
|
297
|
-
# close
|
292
|
+
# close atun
|
298
293
|
#
|
299
|
-
def
|
300
|
-
return if
|
301
|
-
# puts "
|
302
|
-
close_sock(
|
294
|
+
def close_atun( atun )
|
295
|
+
return if atun.closed?
|
296
|
+
# puts "debug close atun"
|
297
|
+
close_sock( atun )
|
298
|
+
atun_info = @atun_infos.delete( atun )
|
299
|
+
src = atun_info[ :src ]
|
300
|
+
|
301
|
+
if src then
|
302
|
+
@paused_srcs.delete( src )
|
303
|
+
end
|
303
304
|
end
|
304
305
|
|
305
306
|
##
|
306
|
-
# close
|
307
|
+
# close btun
|
307
308
|
#
|
308
|
-
def
|
309
|
-
return if
|
310
|
-
# puts "
|
311
|
-
close_sock(
|
312
|
-
|
309
|
+
def close_btun( btun )
|
310
|
+
return if btun.closed?
|
311
|
+
# puts "debug close btun"
|
312
|
+
close_sock( btun )
|
313
|
+
del_btun_info( btun )
|
313
314
|
end
|
314
315
|
|
315
316
|
##
|
316
|
-
# close
|
317
|
+
# close ctl
|
317
318
|
#
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
close_sock( proxy )
|
322
|
-
close_pre_proxy( @pre_proxy )
|
319
|
+
def close_ctl( ctl )
|
320
|
+
close_sock( ctl )
|
321
|
+
@ctl_info[ :resends ].clear
|
323
322
|
end
|
324
323
|
|
325
324
|
##
|
@@ -327,20 +326,15 @@ module Girl
|
|
327
326
|
#
|
328
327
|
def close_read_dst( dst )
|
329
328
|
return if dst.closed?
|
330
|
-
# puts "
|
329
|
+
# puts "debug close read dst"
|
331
330
|
dst.close_read
|
332
331
|
@reads.delete( dst )
|
333
332
|
|
334
333
|
if dst.closed? then
|
335
|
-
# puts "debug1 delete dst info"
|
336
334
|
@writes.delete( dst )
|
337
335
|
@roles.delete( dst )
|
338
|
-
|
339
|
-
else
|
340
|
-
dst_info = @dst_infos[ dst ]
|
336
|
+
del_dst_info( dst )
|
341
337
|
end
|
342
|
-
|
343
|
-
dst_info
|
344
338
|
end
|
345
339
|
|
346
340
|
##
|
@@ -348,39 +342,15 @@ module Girl
|
|
348
342
|
#
|
349
343
|
def close_read_src( src )
|
350
344
|
return if src.closed?
|
351
|
-
# puts "
|
345
|
+
# puts "debug close read src"
|
352
346
|
src.close_read
|
353
347
|
@reads.delete( src )
|
354
348
|
|
355
349
|
if src.closed? then
|
356
|
-
# puts "debug1 delete src info"
|
357
350
|
@writes.delete( src )
|
358
351
|
@roles.delete( src )
|
359
|
-
|
360
|
-
else
|
361
|
-
src_info = @src_infos[ src ]
|
352
|
+
del_src_info( src )
|
362
353
|
end
|
363
|
-
|
364
|
-
src_info
|
365
|
-
end
|
366
|
-
|
367
|
-
##
|
368
|
-
# close read tun
|
369
|
-
#
|
370
|
-
def close_read_tun( tun )
|
371
|
-
return if tun.closed?
|
372
|
-
# puts "debug1 close read tun"
|
373
|
-
tun_info = @tun_infos[ tun ]
|
374
|
-
tun_info[ :close_read ] = true
|
375
|
-
|
376
|
-
if tun_info[ :close_write ] then
|
377
|
-
# puts "debug1 close tun"
|
378
|
-
close_tun( tun )
|
379
|
-
else
|
380
|
-
@reads.delete( tun )
|
381
|
-
end
|
382
|
-
|
383
|
-
tun_info
|
384
354
|
end
|
385
355
|
|
386
356
|
##
|
@@ -398,59 +368,44 @@ module Girl
|
|
398
368
|
#
|
399
369
|
def close_src( src )
|
400
370
|
return if src.closed?
|
401
|
-
# puts "
|
371
|
+
# puts "debug close src"
|
402
372
|
close_sock( src )
|
403
373
|
src_info = del_src_info( src )
|
404
374
|
dst = src_info[ :dst ]
|
405
375
|
|
406
376
|
if dst then
|
407
377
|
close_sock( dst )
|
408
|
-
|
378
|
+
del_dst_info( dst )
|
409
379
|
else
|
410
|
-
|
380
|
+
atun = src_info[ :atun ]
|
381
|
+
btun = src_info[ :btun ]
|
411
382
|
|
412
|
-
if
|
413
|
-
|
414
|
-
|
415
|
-
|
383
|
+
if atun then
|
384
|
+
close_sock( atun )
|
385
|
+
@atun_infos.delete( atun )
|
386
|
+
end
|
416
387
|
|
417
|
-
|
418
|
-
|
419
|
-
|
388
|
+
if btun then
|
389
|
+
close_sock( btun )
|
390
|
+
del_btun_info( btun )
|
420
391
|
end
|
421
392
|
end
|
422
393
|
end
|
423
394
|
|
424
|
-
##
|
425
|
-
# close tun
|
426
|
-
#
|
427
|
-
def close_tun( tun )
|
428
|
-
return if tun.closed?
|
429
|
-
# puts "debug1 close tun"
|
430
|
-
close_sock( tun )
|
431
|
-
tun_info = @tun_infos.delete( tun )
|
432
|
-
close_pre_tun( tun_info[ :pre_tun ] )
|
433
|
-
end
|
434
|
-
|
435
395
|
##
|
436
396
|
# close write dst
|
437
397
|
#
|
438
398
|
def close_write_dst( dst )
|
439
399
|
return if dst.closed?
|
440
|
-
# puts "
|
400
|
+
# puts "debug close write dst"
|
441
401
|
dst.close_write
|
442
402
|
@writes.delete( dst )
|
443
403
|
|
444
404
|
if dst.closed? then
|
445
|
-
# puts "debug1 delete dst info"
|
446
405
|
@reads.delete( dst )
|
447
406
|
@roles.delete( dst )
|
448
|
-
|
449
|
-
else
|
450
|
-
dst_info = @dst_infos[ dst ]
|
407
|
+
del_dst_info( dst )
|
451
408
|
end
|
452
|
-
|
453
|
-
dst_info
|
454
409
|
end
|
455
410
|
|
456
411
|
##
|
@@ -458,39 +413,15 @@ module Girl
|
|
458
413
|
#
|
459
414
|
def close_write_src( src )
|
460
415
|
return if src.closed?
|
461
|
-
# puts "
|
416
|
+
# puts "debug close write src"
|
462
417
|
src.close_write
|
463
418
|
@writes.delete( src )
|
464
419
|
|
465
420
|
if src.closed? then
|
466
|
-
# puts "debug1 delete src info"
|
467
421
|
@reads.delete( src )
|
468
422
|
@roles.delete( src )
|
469
|
-
|
470
|
-
else
|
471
|
-
src_info = @src_infos[ src ]
|
423
|
+
del_src_info( src )
|
472
424
|
end
|
473
|
-
|
474
|
-
src_info
|
475
|
-
end
|
476
|
-
|
477
|
-
##
|
478
|
-
# close write tun
|
479
|
-
#
|
480
|
-
def close_write_tun( tun )
|
481
|
-
return if tun.closed?
|
482
|
-
# puts "debug1 close write tun"
|
483
|
-
tun_info = @tun_infos[ tun ]
|
484
|
-
tun_info[ :close_write ] = true
|
485
|
-
|
486
|
-
if tun_info[ :close_read ] then
|
487
|
-
# puts "debug1 close tun"
|
488
|
-
close_tun( tun )
|
489
|
-
else
|
490
|
-
@writes.delete( tun )
|
491
|
-
end
|
492
|
-
|
493
|
-
tun_info
|
494
425
|
end
|
495
426
|
|
496
427
|
##
|
@@ -500,9 +431,8 @@ module Girl
|
|
500
431
|
return if src.closed?
|
501
432
|
src_info = @src_infos[ src ]
|
502
433
|
|
503
|
-
if
|
504
|
-
|| ip_info.
|
505
|
-
|| ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) then
|
434
|
+
if ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) \
|
435
|
+
|| ( ( ip_info.ip_address == @proxyd_host ) && ( src_info[ :destination_port ] == @proxyd_port ) ) then
|
506
436
|
puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
|
507
437
|
add_closing_src( src )
|
508
438
|
return
|
@@ -519,29 +449,49 @@ module Girl
|
|
519
449
|
is_direct = @is_direct_caches[ ip_info.ip_address ]
|
520
450
|
else
|
521
451
|
is_direct = @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
|
522
|
-
# 判断直连耗时较长(树莓派 0.27秒),这里可能切去主线程,回来src可能已关闭
|
523
452
|
puts "p#{ Process.pid } #{ Time.new } cache is direct #{ ip_info.ip_address } #{ is_direct }"
|
524
453
|
@is_direct_caches[ ip_info.ip_address ] = is_direct
|
525
454
|
end
|
526
455
|
|
527
456
|
if is_direct then
|
528
|
-
# puts "
|
457
|
+
# puts "debug #{ ip_info.inspect } hit directs"
|
529
458
|
new_a_dst( src, ip_info )
|
530
459
|
else
|
531
|
-
#
|
532
|
-
# puts "debug1 #{ ip_info.inspect } go tunnel"
|
460
|
+
# puts "debug #{ ip_info.inspect } go tunnel"
|
533
461
|
set_proxy_type_tunnel( src )
|
534
462
|
end
|
535
463
|
end
|
536
464
|
|
465
|
+
##
|
466
|
+
# del btun info
|
467
|
+
#
|
468
|
+
def del_btun_info( btun )
|
469
|
+
@btun_infos.delete( btun )
|
470
|
+
@paused_btuns.delete( btun )
|
471
|
+
@resume_btuns.delete( btun )
|
472
|
+
end
|
473
|
+
|
474
|
+
##
|
475
|
+
# del dst info
|
476
|
+
#
|
477
|
+
def del_dst_info( dst )
|
478
|
+
# puts "debug delete dst info"
|
479
|
+
dst_info = @dst_infos.delete( dst )
|
480
|
+
@paused_dsts.delete( dst )
|
481
|
+
@resume_dsts.delete( dst )
|
482
|
+
dst_info
|
483
|
+
end
|
484
|
+
|
537
485
|
##
|
538
486
|
# del src info
|
539
487
|
#
|
540
488
|
def del_src_info( src )
|
489
|
+
# puts "debug delete src info"
|
541
490
|
src_info = @src_infos.delete( src )
|
542
491
|
@srcs.delete( src_info[ :id ] )
|
543
492
|
@pending_srcs.delete( src )
|
544
|
-
|
493
|
+
@paused_srcs.delete( src )
|
494
|
+
@resume_srcs.delete( src )
|
545
495
|
src_info
|
546
496
|
end
|
547
497
|
|
@@ -554,37 +504,23 @@ module Girl
|
|
554
504
|
sleep CHECK_EXPIRE_INTERVAL
|
555
505
|
now = Time.new
|
556
506
|
|
557
|
-
if @
|
558
|
-
|
559
|
-
last_recv_at = @proxy_info[ :last_recv_at ]
|
560
|
-
expire_after = EXPIRE_AFTER
|
561
|
-
else
|
562
|
-
last_recv_at = @proxy_info[ :created_at ]
|
563
|
-
expire_after = EXPIRE_NEW
|
564
|
-
end
|
507
|
+
if @ctl && !@ctl.closed? then
|
508
|
+
last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
|
565
509
|
|
566
|
-
if now - last_recv_at >=
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
else
|
571
|
-
# puts "debug1 #{ Time.new } send heartbeat"
|
572
|
-
data = [ HEARTBEAT ].pack( 'C' )
|
573
|
-
add_ctlmsg( data )
|
510
|
+
if now - last_recv_at >= EXPIRE_AFTER then
|
511
|
+
puts "p#{ Process.pid } #{ Time.new } expire ctl"
|
512
|
+
@ctl_info[ :closing ] = true
|
513
|
+
next_tick
|
574
514
|
end
|
575
|
-
elsif @pre_proxy && !@pre_proxy.closed? && ( now - @pre_proxy_info[ :created_at ] > EXPIRE_NEW ) then
|
576
|
-
puts "p#{ Process.pid } #{ Time.new } expire pre proxy"
|
577
|
-
@pre_proxy_info[ :closing ] = true
|
578
|
-
next_tick
|
579
515
|
end
|
580
516
|
|
581
517
|
@src_infos.each do | src, src_info |
|
582
518
|
last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
|
583
519
|
last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
|
584
|
-
expire_after = ( src_info[ :dst ] || src_info[ :
|
520
|
+
expire_after = ( src_info[ :dst ] || src_info[ :atun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
|
585
521
|
|
586
522
|
if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
|
587
|
-
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :destination_domain ] }"
|
523
|
+
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
|
588
524
|
add_closing_src( src )
|
589
525
|
|
590
526
|
unless src_info[ :rbuff ].empty? then
|
@@ -605,24 +541,25 @@ module Girl
|
|
605
541
|
sleep CHECK_RESUME_INTERVAL
|
606
542
|
|
607
543
|
@paused_srcs.each do | src |
|
608
|
-
|
609
|
-
|
610
|
-
else
|
611
|
-
src_info = @src_infos[ src ]
|
612
|
-
dst = src_info[ :dst ]
|
544
|
+
src_info = @src_infos[ src ]
|
545
|
+
dst = src_info[ :dst ]
|
613
546
|
|
614
|
-
|
547
|
+
if dst then
|
548
|
+
if !dst.closed? then
|
615
549
|
dst_info = @dst_infos[ dst ]
|
616
550
|
|
617
551
|
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
618
552
|
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
619
553
|
add_resume_src( src )
|
620
554
|
end
|
621
|
-
|
622
|
-
|
623
|
-
|
555
|
+
end
|
556
|
+
else
|
557
|
+
atun = src_info[ :atun ]
|
558
|
+
|
559
|
+
if atun && !atun.closed? then
|
560
|
+
atun_info = @atun_infos[ atun ]
|
624
561
|
|
625
|
-
if
|
562
|
+
if atun_info[ :wbuff ].size < RESUME_BELOW then
|
626
563
|
puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
|
627
564
|
add_resume_src( src )
|
628
565
|
end
|
@@ -631,11 +568,10 @@ module Girl
|
|
631
568
|
end
|
632
569
|
|
633
570
|
@paused_dsts.each do | dst |
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
src = dst_info[ :src ]
|
571
|
+
dst_info = @dst_infos[ dst ]
|
572
|
+
src = dst_info[ :src ]
|
573
|
+
|
574
|
+
if src && !src.closed? then
|
639
575
|
src_info = @src_infos[ src ]
|
640
576
|
|
641
577
|
if src_info[ :wbuff ].size < RESUME_BELOW then
|
@@ -645,17 +581,16 @@ module Girl
|
|
645
581
|
end
|
646
582
|
end
|
647
583
|
|
648
|
-
@
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
src = tun_info[ :src ]
|
584
|
+
@paused_btuns.each do | btun |
|
585
|
+
btun_info = @btun_infos[ btun ]
|
586
|
+
src = btun_info[ :src ]
|
587
|
+
|
588
|
+
if src && !src.closed? then
|
654
589
|
src_info = @src_infos[ src ]
|
655
590
|
|
656
591
|
if src_info[ :wbuff ].size < RESUME_BELOW then
|
657
|
-
puts "p#{ Process.pid } #{ Time.new } resume
|
658
|
-
|
592
|
+
puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
|
593
|
+
add_resume_btun( btun )
|
659
594
|
end
|
660
595
|
end
|
661
596
|
end
|
@@ -663,6 +598,31 @@ module Girl
|
|
663
598
|
end
|
664
599
|
end
|
665
600
|
|
601
|
+
##
|
602
|
+
# loop resend ctlmsg
|
603
|
+
#
|
604
|
+
def loop_resend_ctlmsg( key, ctlmsg )
|
605
|
+
Thread.new do
|
606
|
+
loop do
|
607
|
+
sleep RESEND_INTERVAL
|
608
|
+
|
609
|
+
resend = @ctl_info[ :resends ][ key ]
|
610
|
+
break unless resend
|
611
|
+
|
612
|
+
puts "p#{ Process.pid } #{ Time.new } resend #{ ctlmsg.inspect }"
|
613
|
+
send_ctlmsg( ctlmsg )
|
614
|
+
resend += 1
|
615
|
+
|
616
|
+
if resend >= RESEND_LIMIT then
|
617
|
+
@ctl_info[ :resends ].delete( key )
|
618
|
+
break
|
619
|
+
end
|
620
|
+
|
621
|
+
@ctl_info[ :resends ][ key ] = resend
|
622
|
+
end
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
666
626
|
##
|
667
627
|
# new a dst
|
668
628
|
#
|
@@ -672,7 +632,6 @@ module Girl
|
|
672
632
|
domain = src_info[ :destination_domain ]
|
673
633
|
destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
|
674
634
|
dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
675
|
-
dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
|
676
635
|
|
677
636
|
begin
|
678
637
|
dst.connect_nonblock( destination_addr )
|
@@ -685,7 +644,7 @@ module Girl
|
|
685
644
|
return
|
686
645
|
end
|
687
646
|
|
688
|
-
# puts "
|
647
|
+
# puts "debug a new dst #{ dst.local_address.inspect }"
|
689
648
|
dst_info = {
|
690
649
|
src: src, # 对应src
|
691
650
|
domain: domain, # 目的地
|
@@ -700,10 +659,10 @@ module Girl
|
|
700
659
|
|
701
660
|
if src_info[ :proxy_proto ] == :http then
|
702
661
|
if src_info[ :is_connect ] then
|
703
|
-
# puts "
|
662
|
+
# puts "debug add src.wbuff http ok"
|
704
663
|
add_src_wbuff( src, HTTP_OK )
|
705
664
|
elsif src_info[ :rbuff ] then
|
706
|
-
# puts "
|
665
|
+
# puts "debug move src.rbuff to dst.wbuff"
|
707
666
|
dst_info[ :wbuff ] << src_info[ :rbuff ]
|
708
667
|
add_write( dst )
|
709
668
|
end
|
@@ -713,65 +672,31 @@ module Girl
|
|
713
672
|
end
|
714
673
|
|
715
674
|
##
|
716
|
-
# new a
|
675
|
+
# new a ctl
|
717
676
|
#
|
718
|
-
def
|
719
|
-
|
720
|
-
pre_proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
677
|
+
def new_a_ctl
|
678
|
+
ctl = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
721
679
|
|
722
680
|
if RUBY_PLATFORM.include?( 'linux' ) then
|
723
|
-
|
724
|
-
pre_proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
681
|
+
ctl.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
725
682
|
end
|
726
683
|
|
727
|
-
|
728
|
-
|
729
|
-
rescue IO::WaitWritable
|
730
|
-
rescue Exception => e
|
731
|
-
puts "p#{ Process.pid } #{ Time.new } connect proxyd #{ e.class }, close pre proxy"
|
732
|
-
pre_proxy.close
|
733
|
-
return
|
734
|
-
end
|
684
|
+
@ctl = ctl
|
685
|
+
add_read( ctl, :ctl )
|
735
686
|
|
736
|
-
@
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
687
|
+
@ctl_info = {
|
688
|
+
resends: ConcurrentHash.new, # key => count
|
689
|
+
atund_addr: nil, # atund地址,src->dst
|
690
|
+
btund_addr: nil, # btund地址,dst->src
|
691
|
+
closing: false, # 准备关闭
|
692
|
+
created_at: Time.new, # 创建时间
|
693
|
+
last_recv_at: nil # 最近一次收到数据时间
|
741
694
|
}
|
742
|
-
add_write( pre_proxy )
|
743
|
-
end
|
744
|
-
|
745
|
-
##
|
746
|
-
# new a pre tun
|
747
|
-
#
|
748
|
-
def new_a_pre_tun( src_id, dst_id )
|
749
|
-
src = @srcs[ src_id ]
|
750
|
-
return if src.nil? || src.closed?
|
751
|
-
src_info = @src_infos[ src ]
|
752
|
-
return if src_info[ :dst_id ]
|
753
695
|
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
pre_tun.connect_nonblock( @proxy_info[ :tund_addr ] )
|
759
|
-
rescue IO::WaitWritable
|
760
|
-
rescue Exception => e
|
761
|
-
puts "p#{ Process.pid } #{ Time.new } connect tund #{ e.class }, close pre tun"
|
762
|
-
pre_tun.close
|
763
|
-
return
|
764
|
-
end
|
765
|
-
|
766
|
-
src_info[ :pre_tun ] = pre_tun
|
767
|
-
src_info[ :dst_id ] = dst_id
|
768
|
-
@pre_tun_infos[ pre_tun ] = {
|
769
|
-
src: src,
|
770
|
-
destination_domain: src_info[ :destination_domain ],
|
771
|
-
created_at: Time.new
|
772
|
-
}
|
773
|
-
@roles[ pre_tun ] = :pre_tun
|
774
|
-
add_write( pre_tun )
|
696
|
+
hello = @custom.hello
|
697
|
+
puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect }"
|
698
|
+
key = [ HELLO ].pack( 'C' )
|
699
|
+
add_ctlmsg( key, hello )
|
775
700
|
end
|
776
701
|
|
777
702
|
##
|
@@ -783,7 +708,6 @@ module Girl
|
|
783
708
|
|
784
709
|
if RUBY_PLATFORM.include?( 'linux' ) then
|
785
710
|
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
786
|
-
redir.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
787
711
|
end
|
788
712
|
|
789
713
|
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
@@ -794,6 +718,86 @@ module Girl
|
|
794
718
|
@redir_local_address = redir.local_address
|
795
719
|
end
|
796
720
|
|
721
|
+
##
|
722
|
+
# new tuns
|
723
|
+
#
|
724
|
+
def new_tuns( src_id, dst_id )
|
725
|
+
return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil?
|
726
|
+
src = @srcs[ src_id ]
|
727
|
+
return if src.nil? || src.closed?
|
728
|
+
src_info = @src_infos[ src ]
|
729
|
+
return if src_info[ :dst_id ]
|
730
|
+
|
731
|
+
# puts "debug new atun and btun"
|
732
|
+
atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
733
|
+
|
734
|
+
begin
|
735
|
+
atun.connect_nonblock( @ctl_info[ :atund_addr ] )
|
736
|
+
rescue IO::WaitWritable
|
737
|
+
rescue Exception => e
|
738
|
+
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
|
739
|
+
atun.close
|
740
|
+
return
|
741
|
+
end
|
742
|
+
|
743
|
+
btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
744
|
+
|
745
|
+
begin
|
746
|
+
btun.connect_nonblock( @ctl_info[ :btund_addr ] )
|
747
|
+
rescue IO::WaitWritable
|
748
|
+
rescue Exception => e
|
749
|
+
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
|
750
|
+
btun.close
|
751
|
+
return
|
752
|
+
end
|
753
|
+
|
754
|
+
domain = src_info[ :destination_domain ]
|
755
|
+
atun_wbuff = [ dst_id ].pack( 'n' )
|
756
|
+
|
757
|
+
until src_info[ :rbuff ].empty? do
|
758
|
+
data = src_info[ :rbuff ][ 0, 65535 ]
|
759
|
+
data_size = data.bytesize
|
760
|
+
# puts "debug move src.rbuff #{ data_size } to atun.wbuff"
|
761
|
+
atun_wbuff << pack_a_chunk( data )
|
762
|
+
src_info[ :rbuff ] = src_info[ :rbuff ][ data_size..-1 ]
|
763
|
+
end
|
764
|
+
|
765
|
+
@atun_infos[ atun ] = {
|
766
|
+
src: src, # 对应src
|
767
|
+
domain: domain, # 目的地
|
768
|
+
wbuff: atun_wbuff, # 写前
|
769
|
+
closing: false # 准备关闭
|
770
|
+
}
|
771
|
+
|
772
|
+
btun_wbuff = [ dst_id ].pack( 'n' )
|
773
|
+
|
774
|
+
@btun_infos[ btun ] = {
|
775
|
+
src: src, # 对应src
|
776
|
+
domain: domain, # 目的地
|
777
|
+
wbuff: btun_wbuff, # 写前
|
778
|
+
rbuff: '', # 暂存当前块没收全的流量
|
779
|
+
wait_bytes: 0, # 还差多少字节收全当前块
|
780
|
+
lbuff: '' # 流量截断在长度前缀处
|
781
|
+
}
|
782
|
+
|
783
|
+
src_info[ :dst_id ] = dst_id
|
784
|
+
src_info[ :atun ] = atun
|
785
|
+
src_info[ :btun ] = btun
|
786
|
+
add_read( atun, :atun )
|
787
|
+
add_read( btun, :btun )
|
788
|
+
add_write( atun )
|
789
|
+
add_write( btun )
|
790
|
+
|
791
|
+
if src_info[ :proxy_proto ] == :http then
|
792
|
+
if src_info[ :is_connect ] then
|
793
|
+
# puts "debug add src.wbuff http ok"
|
794
|
+
add_src_wbuff( src, HTTP_OK )
|
795
|
+
end
|
796
|
+
elsif src_info[ :proxy_proto ] == :socks5 then
|
797
|
+
add_socks5_conn_reply( src )
|
798
|
+
end
|
799
|
+
end
|
800
|
+
|
797
801
|
##
|
798
802
|
# next tick
|
799
803
|
#
|
@@ -801,6 +805,14 @@ module Girl
|
|
801
805
|
@dotw.write( '.' )
|
802
806
|
end
|
803
807
|
|
808
|
+
##
|
809
|
+
# pack a chunk
|
810
|
+
#
|
811
|
+
def pack_a_chunk( data )
|
812
|
+
data = @custom.encode( data )
|
813
|
+
"#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
|
814
|
+
end
|
815
|
+
|
804
816
|
##
|
805
817
|
# resolve domain
|
806
818
|
#
|
@@ -817,24 +829,18 @@ module Girl
|
|
817
829
|
ip_info, created_at = resolv_cache
|
818
830
|
|
819
831
|
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
820
|
-
# puts "
|
832
|
+
# puts "debug #{ domain } hit resolv cache #{ ip_info.inspect }"
|
821
833
|
deal_with_destination_ip( src, ip_info )
|
822
834
|
return
|
823
835
|
end
|
824
836
|
|
825
|
-
# puts "
|
837
|
+
# puts "debug expire #{ domain } resolv cache"
|
826
838
|
@resolv_caches.delete( domain )
|
827
839
|
end
|
828
840
|
|
829
841
|
src_info = @src_infos[ src ]
|
830
842
|
src_info[ :proxy_type ] = :checking
|
831
843
|
|
832
|
-
if @use_remote_resolv then
|
833
|
-
data = "#{ [ RESOLV, src_info[ :id ] ].pack( 'CQ>' ) }#{ domain }"
|
834
|
-
add_ctlmsg( data )
|
835
|
-
return
|
836
|
-
end
|
837
|
-
|
838
844
|
Thread.new do
|
839
845
|
begin
|
840
846
|
ip_info = Addrinfo.ip( domain )
|
@@ -852,6 +858,34 @@ module Girl
|
|
852
858
|
end
|
853
859
|
end
|
854
860
|
|
861
|
+
##
|
862
|
+
# send ctlmsg
|
863
|
+
#
|
864
|
+
def send_ctlmsg( data )
|
865
|
+
return if @ctl.nil? || @ctl.closed?
|
866
|
+
data = @custom.encode( data )
|
867
|
+
|
868
|
+
begin
|
869
|
+
@ctl.sendmsg( data, 0, @proxyd_addr )
|
870
|
+
@ctl_info[ :last_sent_at ] = Time.new
|
871
|
+
rescue Exception => e
|
872
|
+
puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
|
873
|
+
close_ctl( @ctl )
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
##
|
878
|
+
# set atun closing
|
879
|
+
#
|
880
|
+
def set_atun_closing( atun )
|
881
|
+
return if atun.closed?
|
882
|
+
atun_info = @atun_infos[ atun ]
|
883
|
+
return if atun_info[ :closing ]
|
884
|
+
# puts "debug set atun closing"
|
885
|
+
atun_info[ :closing ] = true
|
886
|
+
add_write( atun )
|
887
|
+
end
|
888
|
+
|
855
889
|
##
|
856
890
|
# set dst closing write
|
857
891
|
#
|
@@ -859,6 +893,7 @@ module Girl
|
|
859
893
|
return if dst.closed?
|
860
894
|
dst_info = @dst_infos[ dst ]
|
861
895
|
return if dst_info[ :closing_write ]
|
896
|
+
# puts "debug set dst closing write"
|
862
897
|
dst_info[ :closing_write ] = true
|
863
898
|
add_write( dst )
|
864
899
|
end
|
@@ -872,7 +907,7 @@ module Girl
|
|
872
907
|
src_info[ :proxy_type ] = :tunnel
|
873
908
|
src_id = src_info[ :id ]
|
874
909
|
|
875
|
-
if @
|
910
|
+
if @ctl && !@ctl.closed? && @ctl_info[ :atund_addr ] then
|
876
911
|
add_a_new_source( src )
|
877
912
|
else
|
878
913
|
@pending_srcs << src
|
@@ -890,48 +925,15 @@ module Girl
|
|
890
925
|
add_write( src )
|
891
926
|
end
|
892
927
|
|
893
|
-
##
|
894
|
-
# set tun closing write
|
895
|
-
#
|
896
|
-
def set_tun_closing_write( tun )
|
897
|
-
return if tun.closed?
|
898
|
-
tun_info = @tun_infos[ tun ]
|
899
|
-
return if tun_info[ :closing_write ]
|
900
|
-
tun_info[ :closing_write ] = true
|
901
|
-
add_write( tun )
|
902
|
-
end
|
903
|
-
|
904
|
-
##
|
905
|
-
# sub http request
|
906
|
-
#
|
907
|
-
def sub_http_request( data )
|
908
|
-
lines = data.split( "\r\n" )
|
909
|
-
|
910
|
-
return [ data, nil ] if lines.empty?
|
911
|
-
|
912
|
-
method, url, proto = lines.first.split( ' ' )
|
913
|
-
|
914
|
-
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
915
|
-
domain_port = url.split( '/' )[ 2 ]
|
916
|
-
data = data.sub( "http://#{ domain_port }", '' )
|
917
|
-
# puts "debug1 subed #{ data.inspect } #{ domain_port }"
|
918
|
-
end
|
919
|
-
|
920
|
-
[ data, domain_port ]
|
921
|
-
end
|
922
|
-
|
923
928
|
##
|
924
929
|
# read dotr
|
925
930
|
#
|
926
931
|
def read_dotr( dotr )
|
927
|
-
dotr.read_nonblock(
|
932
|
+
dotr.read_nonblock( 65535 )
|
928
933
|
|
929
|
-
if @
|
930
|
-
|
931
|
-
|
932
|
-
end
|
933
|
-
elsif @pre_proxy && !@pre_proxy.closed? && @pre_proxy_info[ :closing ] then
|
934
|
-
close_pre_proxy( @pre_proxy )
|
934
|
+
if @ctl_info && @ctl_info[ :closing ] then
|
935
|
+
send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
|
936
|
+
close_ctl( @ctl )
|
935
937
|
end
|
936
938
|
|
937
939
|
if @closing_srcs.any? then
|
@@ -957,13 +959,13 @@ module Girl
|
|
957
959
|
@resume_dsts.clear
|
958
960
|
end
|
959
961
|
|
960
|
-
if @
|
961
|
-
@
|
962
|
-
add_read(
|
963
|
-
@
|
962
|
+
if @resume_btuns.any? then
|
963
|
+
@resume_btuns.each do | btun |
|
964
|
+
add_read( btun )
|
965
|
+
@paused_btuns.delete( btun )
|
964
966
|
end
|
965
967
|
|
966
|
-
@
|
968
|
+
@resume_btuns.clear
|
967
969
|
end
|
968
970
|
end
|
969
971
|
|
@@ -979,7 +981,7 @@ module Girl
|
|
979
981
|
end
|
980
982
|
|
981
983
|
src_id = rand( ( 2 ** 64 ) - 2 ) + 1
|
982
|
-
# puts "
|
984
|
+
# puts "debug accept a src #{ src_id } #{ addrinfo.ip_unpack.inspect }"
|
983
985
|
|
984
986
|
@srcs[ src_id ] = src
|
985
987
|
@src_infos[ src ] = {
|
@@ -991,10 +993,11 @@ module Girl
|
|
991
993
|
is_connect: true, # 代理协议是http的场合,是否是CONNECT
|
992
994
|
rbuff: '', # 读到的流量
|
993
995
|
dst: nil, # :direct的场合,对应的dst
|
994
|
-
|
995
|
-
|
996
|
+
ctl: nil, # :tunnel的场合,对应的ctl
|
997
|
+
atun: nil, # :tunnel的场合,对应的atun
|
998
|
+
btun: nil, # :tunnel的场合,对应的btun
|
996
999
|
dst_id: nil, # 远端dst id
|
997
|
-
wbuff: '', # 从dst/
|
1000
|
+
wbuff: '', # 从dst/btun读到的流量
|
998
1001
|
created_at: Time.new, # 创建时间
|
999
1002
|
last_recv_at: nil, # 上一次收到新流量(由dst收到,或者由tun收到)的时间
|
1000
1003
|
last_sent_at: nil, # 上一次发出流量(由dst发出,或者由tun发出)的时间
|
@@ -1003,75 +1006,51 @@ module Girl
|
|
1003
1006
|
|
1004
1007
|
add_read( src, :src )
|
1005
1008
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
new_a_pre_proxy
|
1009
|
+
if @ctl.nil? || @ctl.closed? then
|
1010
|
+
new_a_ctl
|
1009
1011
|
end
|
1010
1012
|
end
|
1011
1013
|
|
1012
1014
|
##
|
1013
|
-
# read
|
1015
|
+
# read ctl
|
1014
1016
|
#
|
1015
|
-
def
|
1016
|
-
if proxy.closed? then
|
1017
|
-
puts "p#{ Process.pid } #{ Time.new } read proxy but proxy closed?"
|
1018
|
-
return
|
1019
|
-
end
|
1020
|
-
|
1017
|
+
def read_ctl( ctl )
|
1021
1018
|
begin
|
1022
|
-
data =
|
1023
|
-
rescue IO::WaitReadable
|
1024
|
-
return
|
1025
|
-
rescue Errno::EINTR
|
1026
|
-
puts e.class
|
1027
|
-
return
|
1019
|
+
data, addrinfo, rflags, *controls = ctl.recvmsg
|
1028
1020
|
rescue Exception => e
|
1029
|
-
|
1030
|
-
|
1021
|
+
puts "p#{ Process.pid } #{ Time.new } recvmsg #{ e.class }"
|
1022
|
+
close_ctl( ctl )
|
1031
1023
|
return
|
1032
1024
|
end
|
1033
1025
|
|
1034
|
-
|
1035
|
-
|
1036
|
-
data.split( SEPARATE ).each do | ctlmsg |
|
1037
|
-
next unless ctlmsg[ 0 ]
|
1026
|
+
data = @custom.decode( data )
|
1027
|
+
ctl_num = data[ 0 ].unpack( 'C' ).first
|
1038
1028
|
|
1039
|
-
|
1029
|
+
case ctl_num
|
1030
|
+
when TUND_PORT then
|
1031
|
+
return if @ctl_info[ :atund_addr ] || data.size != 5
|
1032
|
+
atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
|
1033
|
+
puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
|
1034
|
+
@ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
|
1035
|
+
@ctl_info[ :atund_addr ] = Socket.sockaddr_in( atund_port, @proxyd_host )
|
1036
|
+
@ctl_info[ :btund_addr ] = Socket.sockaddr_in( btund_port, @proxyd_host )
|
1037
|
+
@ctl_info[ :last_recv_at ] = Time.new
|
1040
1038
|
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
|
1046
|
-
@proxy_info[ :tund_addr ] = Socket.sockaddr_in( tund_port, @proxyd_host )
|
1047
|
-
|
1048
|
-
if @pending_srcs.any? then
|
1049
|
-
puts "p#{ Process.pid } #{ Time.new } send pending sources"
|
1050
|
-
@pending_srcs.each { | src | add_a_new_source( src ) }
|
1051
|
-
@pending_srcs.clear
|
1052
|
-
end
|
1053
|
-
when PAIRED then
|
1054
|
-
next if ctlmsg.size != 11
|
1055
|
-
src_id, dst_id = ctlmsg[ 1, 10 ].unpack( 'Q>n' )
|
1056
|
-
# puts "debug1 got paired #{ src_id } #{ dst_id }"
|
1057
|
-
new_a_pre_tun( src_id, dst_id )
|
1058
|
-
when RESOLVED then
|
1059
|
-
next if ctlmsg.size <= 9
|
1060
|
-
src_id = ctlmsg[ 1, 8 ].unpack( 'Q>' ).first
|
1061
|
-
src = @srcs[ src_id ]
|
1062
|
-
next if src.nil? || src.closed?
|
1063
|
-
src_info = @src_infos[ src ]
|
1064
|
-
ip = ctlmsg[ 9..-1 ]
|
1065
|
-
puts "p#{ Process.pid } #{ Time.new } remote resolved #{ src_info[ :destination_domain ] } #{ ip }"
|
1066
|
-
ip_info = Addrinfo.ip( ip )
|
1067
|
-
deal_with_destination_ip( src, ip_info )
|
1068
|
-
when TUND_FIN then
|
1069
|
-
puts "p#{ Process.pid } #{ Time.new } got tund fin"
|
1070
|
-
close_proxy( proxy )
|
1071
|
-
return
|
1072
|
-
when HEARTBEAT
|
1073
|
-
# puts "debug1 #{ Time.new } got heartbeat"
|
1039
|
+
if @pending_srcs.any? then
|
1040
|
+
puts "p#{ Process.pid } #{ Time.new } send pending sources"
|
1041
|
+
@pending_srcs.each { | src | add_a_new_source( src ) }
|
1042
|
+
@pending_srcs.clear
|
1074
1043
|
end
|
1044
|
+
when PAIRED then
|
1045
|
+
return if data.size != 11
|
1046
|
+
src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
|
1047
|
+
# puts "debug got paired #{ src_id } #{ dst_id }"
|
1048
|
+
@ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
|
1049
|
+
@ctl_info[ :last_recv_at ] = Time.new
|
1050
|
+
new_tuns( src_id, dst_id )
|
1051
|
+
when UNKNOWN_CTL_ADDR then
|
1052
|
+
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
|
1053
|
+
close_ctl( ctl )
|
1075
1054
|
end
|
1076
1055
|
end
|
1077
1056
|
|
@@ -1084,33 +1063,38 @@ module Girl
|
|
1084
1063
|
return
|
1085
1064
|
end
|
1086
1065
|
|
1066
|
+
src_info = @src_infos[ src ]
|
1067
|
+
|
1087
1068
|
begin
|
1088
|
-
data = src.read_nonblock(
|
1089
|
-
rescue IO::WaitReadable
|
1069
|
+
data = src.read_nonblock( 65535 )
|
1070
|
+
rescue IO::WaitReadable
|
1090
1071
|
print 'r'
|
1091
1072
|
return
|
1092
1073
|
rescue Exception => e
|
1093
|
-
# puts "
|
1094
|
-
|
1074
|
+
# puts "debug read src #{ e.class }"
|
1075
|
+
close_read_src( src )
|
1095
1076
|
dst = src_info[ :dst ]
|
1096
1077
|
|
1097
1078
|
if dst then
|
1098
1079
|
set_dst_closing_write( dst )
|
1099
1080
|
else
|
1100
|
-
|
1101
|
-
|
1081
|
+
atun = src_info[ :atun ]
|
1082
|
+
|
1083
|
+
if atun then
|
1084
|
+
set_atun_closing( atun )
|
1085
|
+
end
|
1102
1086
|
end
|
1103
1087
|
|
1104
1088
|
return
|
1105
1089
|
end
|
1106
1090
|
|
1107
|
-
|
1091
|
+
# puts "debug read src #{ data.bytesize }"
|
1108
1092
|
proxy_type = src_info[ :proxy_type ]
|
1109
1093
|
|
1110
1094
|
case proxy_type
|
1111
1095
|
when :uncheck then
|
1112
1096
|
if data[ 0, 7 ] == 'CONNECT' then
|
1113
|
-
# puts "
|
1097
|
+
# puts "debug CONNECT"
|
1114
1098
|
domain_port = data.split( "\r\n" )[ 0 ].split( ' ' )[ 1 ]
|
1115
1099
|
|
1116
1100
|
unless domain_port then
|
@@ -1119,7 +1103,7 @@ module Girl
|
|
1119
1103
|
return
|
1120
1104
|
end
|
1121
1105
|
elsif data[ 0 ].unpack( 'C' ).first == 5 then
|
1122
|
-
# puts "
|
1106
|
+
# puts "debug socks5 #{ data.inspect }"
|
1123
1107
|
|
1124
1108
|
# https://tools.ietf.org/html/rfc1928
|
1125
1109
|
#
|
@@ -1148,19 +1132,28 @@ module Girl
|
|
1148
1132
|
src_info[ :proxy_type ] = :negotiation
|
1149
1133
|
return
|
1150
1134
|
else
|
1151
|
-
# puts "
|
1135
|
+
# puts "debug not CONNECT #{ data.inspect }"
|
1152
1136
|
host_line = data.split( "\r\n" ).find { | _line | _line[ 0, 6 ] == 'Host: ' }
|
1153
1137
|
|
1154
1138
|
unless host_line then
|
1155
|
-
# puts "
|
1139
|
+
# puts "debug not found host line"
|
1156
1140
|
add_closing_src( src )
|
1157
1141
|
return
|
1158
1142
|
end
|
1159
1143
|
|
1160
|
-
|
1144
|
+
lines = data.split( "\r\n" )
|
1145
|
+
|
1146
|
+
unless lines.empty? then
|
1147
|
+
method, url, proto = lines.first.split( ' ' )
|
1148
|
+
|
1149
|
+
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
1150
|
+
domain_port = url.split( '/' )[ 2 ]
|
1151
|
+
# puts "debug domain port #{ domain_port }"
|
1152
|
+
end
|
1153
|
+
end
|
1161
1154
|
|
1162
1155
|
unless domain_port then
|
1163
|
-
# puts "
|
1156
|
+
# puts "debug not HTTP"
|
1164
1157
|
domain_port = host_line.split( ' ' )[ 1 ]
|
1165
1158
|
|
1166
1159
|
unless domain_port then
|
@@ -1183,7 +1176,7 @@ module Girl
|
|
1183
1176
|
|
1184
1177
|
resolve_domain( src, domain )
|
1185
1178
|
when :checking then
|
1186
|
-
# puts "
|
1179
|
+
# puts "debug add src rbuff before resolved #{ data.inspect }"
|
1187
1180
|
src_info[ :rbuff ] << data
|
1188
1181
|
when :negotiation then
|
1189
1182
|
# +----+-----+-------+------+----------+----------+
|
@@ -1191,11 +1184,11 @@ module Girl
|
|
1191
1184
|
# +----+-----+-------+------+----------+----------+
|
1192
1185
|
# | 1 | 1 | X'00' | 1 | Variable | 2 |
|
1193
1186
|
# +----+-----+-------+------+----------+----------+
|
1194
|
-
# puts "
|
1187
|
+
# puts "debug negotiation #{ data.inspect }"
|
1195
1188
|
ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
|
1196
1189
|
|
1197
1190
|
if cmd == 1 then
|
1198
|
-
# puts "
|
1191
|
+
# puts "debug socks5 CONNECT"
|
1199
1192
|
|
1200
1193
|
if atyp == 1 then
|
1201
1194
|
destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
|
@@ -1204,7 +1197,7 @@ module Girl
|
|
1204
1197
|
destination_ip = destination_addrinfo.ip_address
|
1205
1198
|
src_info[ :destination_domain ] = destination_ip
|
1206
1199
|
src_info[ :destination_port ] = destination_port
|
1207
|
-
# puts "
|
1200
|
+
# puts "debug IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
|
1208
1201
|
deal_with_destination_ip( src, destination_addrinfo )
|
1209
1202
|
elsif atyp == 3 then
|
1210
1203
|
domain_len = data[ 4 ].unpack( 'C' ).first
|
@@ -1214,7 +1207,7 @@ module Girl
|
|
1214
1207
|
port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
|
1215
1208
|
src_info[ :destination_domain ] = domain
|
1216
1209
|
src_info[ :destination_port ] = port
|
1217
|
-
# puts "
|
1210
|
+
# puts "debug DOMAINNAME #{ domain } #{ port }"
|
1218
1211
|
resolve_domain( src, domain )
|
1219
1212
|
end
|
1220
1213
|
end
|
@@ -1222,35 +1215,21 @@ module Girl
|
|
1222
1215
|
puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
|
1223
1216
|
end
|
1224
1217
|
when :tunnel then
|
1225
|
-
|
1226
|
-
|
1227
|
-
if tun then
|
1228
|
-
unless tun.closed? then
|
1229
|
-
unless src_info[ :is_connect ] then
|
1230
|
-
data, _ = sub_http_request( data )
|
1231
|
-
end
|
1218
|
+
atun = src_info[ :atun ]
|
1232
1219
|
|
1233
|
-
|
1234
|
-
|
1235
|
-
end
|
1220
|
+
if atun then
|
1221
|
+
add_atun_wbuff( atun, pack_a_chunk( data ) )
|
1236
1222
|
else
|
1237
|
-
# puts "
|
1223
|
+
# puts "debug add src.rbuff #{ data.bytesize }"
|
1238
1224
|
add_src_rbuff( src, data )
|
1239
1225
|
end
|
1240
1226
|
when :direct then
|
1241
1227
|
dst = src_info[ :dst ]
|
1242
1228
|
|
1243
1229
|
if dst then
|
1244
|
-
|
1245
|
-
unless src_info[ :is_connect ] then
|
1246
|
-
data, _ = sub_http_request( data )
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
# puts "debug2 add dst.wbuff #{ data.bytesize }"
|
1250
|
-
add_dst_wbuff( dst, data )
|
1251
|
-
end
|
1230
|
+
add_dst_wbuff( dst, data )
|
1252
1231
|
else
|
1253
|
-
# puts "
|
1232
|
+
# puts "debug add src.rbuff #{ data.bytesize }"
|
1254
1233
|
add_src_rbuff( src, data )
|
1255
1234
|
end
|
1256
1235
|
end
|
@@ -1265,82 +1244,110 @@ module Girl
|
|
1265
1244
|
return
|
1266
1245
|
end
|
1267
1246
|
|
1247
|
+
dst_info = @dst_infos[ dst ]
|
1248
|
+
src = dst_info[ :src ]
|
1249
|
+
|
1268
1250
|
begin
|
1269
|
-
data = dst.read_nonblock(
|
1270
|
-
rescue IO::WaitReadable
|
1251
|
+
data = dst.read_nonblock( 65535 )
|
1252
|
+
rescue IO::WaitReadable
|
1271
1253
|
print 'r'
|
1272
1254
|
return
|
1273
1255
|
rescue Exception => e
|
1274
|
-
# puts "
|
1275
|
-
|
1276
|
-
src = dst_info[ :src ]
|
1256
|
+
# puts "debug read dst #{ e.class }"
|
1257
|
+
close_read_dst( dst )
|
1277
1258
|
set_src_closing_write( src )
|
1278
1259
|
return
|
1279
1260
|
end
|
1280
1261
|
|
1281
|
-
|
1282
|
-
src = dst_info[ :src ]
|
1262
|
+
# puts "debug read dst #{ data.bytesize }"
|
1283
1263
|
add_src_wbuff( src, data )
|
1284
1264
|
end
|
1285
1265
|
|
1286
1266
|
##
|
1287
|
-
# read
|
1267
|
+
# read btun
|
1288
1268
|
#
|
1289
|
-
def
|
1290
|
-
if
|
1291
|
-
puts "p#{ Process.pid } #{ Time.new } read
|
1269
|
+
def read_btun( btun )
|
1270
|
+
if btun.closed? then
|
1271
|
+
puts "p#{ Process.pid } #{ Time.new } read btun but btun closed?"
|
1292
1272
|
return
|
1293
1273
|
end
|
1294
1274
|
|
1275
|
+
btun_info = @btun_infos[ btun ]
|
1276
|
+
src = btun_info[ :src ]
|
1277
|
+
|
1295
1278
|
begin
|
1296
|
-
data =
|
1297
|
-
rescue IO::WaitReadable
|
1298
|
-
return
|
1299
|
-
rescue Errno::EINTR
|
1300
|
-
puts e.class
|
1301
|
-
return
|
1279
|
+
data = btun.read_nonblock( READ_SIZE )
|
1302
1280
|
rescue Exception => e
|
1303
|
-
# puts "
|
1304
|
-
|
1305
|
-
src = tun_info[ :src ]
|
1306
|
-
set_src_closing_write( src )
|
1307
|
-
return
|
1308
|
-
end
|
1281
|
+
# puts "debug read btun #{ btun_info[ :im ] } #{ e.class }"
|
1282
|
+
close_btun( btun )
|
1309
1283
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
add_src_wbuff( src, data )
|
1314
|
-
end
|
1284
|
+
if src then
|
1285
|
+
set_src_closing_write( src )
|
1286
|
+
end
|
1315
1287
|
|
1316
|
-
##
|
1317
|
-
# write proxy
|
1318
|
-
#
|
1319
|
-
def write_proxy( proxy )
|
1320
|
-
if proxy.closed? then
|
1321
|
-
puts "p#{ Process.pid } #{ Time.new } write proxy but proxy closed?"
|
1322
1288
|
return
|
1323
1289
|
end
|
1324
1290
|
|
1325
|
-
|
1326
|
-
|
1291
|
+
until data.empty? do
|
1292
|
+
wait_bytes = btun_info[ :wait_bytes ]
|
1327
1293
|
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1294
|
+
if wait_bytes > 0 then
|
1295
|
+
len = wait_bytes
|
1296
|
+
# puts "debug wait bytes #{ len }"
|
1297
|
+
else
|
1298
|
+
lbuff = btun_info[ :lbuff ]
|
1299
|
+
|
1300
|
+
if lbuff.empty? then
|
1301
|
+
# 长度缓存为空,从读到的流量里取长度
|
1302
|
+
# 两个字节以下,记进长度缓存
|
1303
|
+
if data.bytesize <= 2 then
|
1304
|
+
# puts "debug set btun.lbuff #{ data.inspect }"
|
1305
|
+
btun_info[ :lbuff ] = data
|
1306
|
+
return
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
len = data[ 0, 2 ].unpack( 'n' ).first
|
1310
|
+
data = data[ 2..-1 ]
|
1311
|
+
elsif lbuff.bytesize == 1 then
|
1312
|
+
# 长度缓存记有一个字节,补一个字节
|
1313
|
+
lbuff = "#{ lbuff }#{ data[ 0 ] }"
|
1314
|
+
|
1315
|
+
if data.bytesize == 1 then
|
1316
|
+
# puts "debug add btun.lbuff a byte #{ data.inspect }"
|
1317
|
+
btun_info[ :lbuff ] = lbuff
|
1318
|
+
return
|
1319
|
+
end
|
1320
|
+
|
1321
|
+
# 使用长度缓存
|
1322
|
+
len = lbuff.unpack( 'n' ).first
|
1323
|
+
btun_info[ :lbuff ].clear
|
1324
|
+
data = data[ 1..-1 ]
|
1325
|
+
else
|
1326
|
+
# 使用长度缓存
|
1327
|
+
len = lbuff.unpack( 'n' ).first
|
1328
|
+
btun_info[ :lbuff ].clear
|
1329
|
+
end
|
1338
1330
|
end
|
1339
1331
|
|
1340
|
-
|
1341
|
-
|
1332
|
+
chunk = data[ 0, len ]
|
1333
|
+
chunk_size = chunk.bytesize
|
1342
1334
|
|
1343
|
-
|
1335
|
+
if chunk_size == len then
|
1336
|
+
# 取完整了
|
1337
|
+
chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
|
1338
|
+
# puts "debug decode and add src.wbuff #{ chunk.bytesize }"
|
1339
|
+
add_src_wbuff( src, chunk )
|
1340
|
+
btun_info[ :rbuff ].clear
|
1341
|
+
btun_info[ :wait_bytes ] = 0
|
1342
|
+
else
|
1343
|
+
# 暂存
|
1344
|
+
# puts "debug add btun.rbuff #{ chunk_size } wait bytes #{ len - chunk_size }"
|
1345
|
+
btun_info[ :rbuff ] << chunk
|
1346
|
+
btun_info[ :wait_bytes ] = len - chunk_size
|
1347
|
+
end
|
1348
|
+
|
1349
|
+
data = data[ chunk_size..-1 ]
|
1350
|
+
end
|
1344
1351
|
end
|
1345
1352
|
|
1346
1353
|
##
|
@@ -1370,24 +1377,27 @@ module Girl
|
|
1370
1377
|
# 写入
|
1371
1378
|
begin
|
1372
1379
|
written = src.write_nonblock( data )
|
1373
|
-
rescue IO::WaitWritable
|
1380
|
+
rescue IO::WaitWritable
|
1374
1381
|
print 'w'
|
1375
1382
|
return
|
1376
1383
|
rescue Exception => e
|
1377
|
-
# puts "
|
1384
|
+
# puts "debug write src #{ e.class }"
|
1378
1385
|
close_write_src( src )
|
1379
1386
|
|
1380
1387
|
if dst then
|
1381
1388
|
close_read_dst( dst )
|
1382
1389
|
else
|
1383
|
-
|
1384
|
-
|
1390
|
+
btun = src_info[ :btun ]
|
1391
|
+
|
1392
|
+
if btun then
|
1393
|
+
close_btun( btun )
|
1394
|
+
end
|
1385
1395
|
end
|
1386
1396
|
|
1387
1397
|
return
|
1388
1398
|
end
|
1389
1399
|
|
1390
|
-
# puts "
|
1400
|
+
# puts "debug write src #{ written }"
|
1391
1401
|
data = data[ written..-1 ]
|
1392
1402
|
src_info[ :wbuff ] = data
|
1393
1403
|
end
|
@@ -1419,11 +1429,11 @@ module Girl
|
|
1419
1429
|
# 写入
|
1420
1430
|
begin
|
1421
1431
|
written = dst.write_nonblock( data )
|
1422
|
-
rescue IO::WaitWritable
|
1432
|
+
rescue IO::WaitWritable
|
1423
1433
|
print 'w'
|
1424
1434
|
return
|
1425
1435
|
rescue Exception => e
|
1426
|
-
# puts "
|
1436
|
+
# puts "debug write dst #{ e.class }"
|
1427
1437
|
close_write_dst( dst )
|
1428
1438
|
close_read_src( src )
|
1429
1439
|
return
|
@@ -1439,24 +1449,24 @@ module Girl
|
|
1439
1449
|
end
|
1440
1450
|
|
1441
1451
|
##
|
1442
|
-
# write
|
1452
|
+
# write atun
|
1443
1453
|
#
|
1444
|
-
def
|
1445
|
-
if
|
1446
|
-
puts "p#{ Process.pid } #{ Time.new } write
|
1454
|
+
def write_atun( atun )
|
1455
|
+
if atun.closed? then
|
1456
|
+
puts "p#{ Process.pid } #{ Time.new } write atun but atun closed?"
|
1447
1457
|
return
|
1448
1458
|
end
|
1449
1459
|
|
1450
|
-
|
1451
|
-
src =
|
1452
|
-
data =
|
1460
|
+
atun_info = @atun_infos[ atun ]
|
1461
|
+
src = atun_info[ :src ]
|
1462
|
+
data = atun_info[ :wbuff ]
|
1453
1463
|
|
1454
1464
|
# 写前为空,处理关闭写
|
1455
1465
|
if data.empty? then
|
1456
|
-
if
|
1457
|
-
|
1466
|
+
if atun_info[ :closing ] then
|
1467
|
+
close_atun( atun )
|
1458
1468
|
else
|
1459
|
-
@writes.delete(
|
1469
|
+
@writes.delete( atun )
|
1460
1470
|
end
|
1461
1471
|
|
1462
1472
|
return
|
@@ -1464,23 +1474,20 @@ module Girl
|
|
1464
1474
|
|
1465
1475
|
# 写入
|
1466
1476
|
begin
|
1467
|
-
written =
|
1468
|
-
rescue IO::
|
1469
|
-
# OpenSSL::SSL::SSLErrorWaitReadable
|
1470
|
-
return
|
1471
|
-
rescue IO::WaitWritable, Errno::EINTR
|
1477
|
+
written = atun.write_nonblock( data )
|
1478
|
+
rescue IO::WaitWritable
|
1472
1479
|
print 'w'
|
1473
1480
|
return
|
1474
1481
|
rescue Exception => e
|
1475
|
-
# puts "
|
1476
|
-
|
1482
|
+
# puts "debug write atun #{ e.class }"
|
1483
|
+
close_atun( atun )
|
1477
1484
|
close_read_src( src )
|
1478
1485
|
return
|
1479
1486
|
end
|
1480
1487
|
|
1481
|
-
# puts "
|
1488
|
+
# puts "debug write atun #{ written }"
|
1482
1489
|
data = data[ written..-1 ]
|
1483
|
-
|
1490
|
+
atun_info[ :wbuff ] = data
|
1484
1491
|
|
1485
1492
|
unless src.closed? then
|
1486
1493
|
src_info = @src_infos[ src ]
|
@@ -1489,112 +1496,30 @@ module Girl
|
|
1489
1496
|
end
|
1490
1497
|
|
1491
1498
|
##
|
1492
|
-
# write
|
1499
|
+
# write btun
|
1493
1500
|
#
|
1494
|
-
def
|
1495
|
-
if
|
1496
|
-
puts "p#{ Process.pid } #{ Time.new } write
|
1501
|
+
def write_btun( btun )
|
1502
|
+
if btun.closed? then
|
1503
|
+
puts "p#{ Process.pid } #{ Time.new } write btun but btun closed?"
|
1497
1504
|
return
|
1498
1505
|
end
|
1499
1506
|
|
1500
|
-
|
1507
|
+
btun_info = @btun_infos[ btun ]
|
1508
|
+
data = btun_info[ :wbuff ]
|
1501
1509
|
|
1510
|
+
# 写入dst id
|
1502
1511
|
begin
|
1503
|
-
|
1504
|
-
rescue IO::WaitReadable
|
1505
|
-
rescue IO::WaitWritable
|
1512
|
+
written = btun.write( data )
|
1506
1513
|
rescue Exception => e
|
1507
|
-
puts "
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
end
|
1512
|
-
|
1513
|
-
@proxy = proxy
|
1514
|
-
@proxy_info = {
|
1515
|
-
ctlmsgs: [], # ctlmsg
|
1516
|
-
tund_addr: nil, # tund地址
|
1517
|
-
created_at: Time.new, # 创建时间
|
1518
|
-
last_recv_at: nil, # 上一次收到流量的时间
|
1519
|
-
closing: false # 是否准备关闭
|
1520
|
-
}
|
1521
|
-
add_read( proxy, :proxy )
|
1522
|
-
hello = @custom.hello
|
1523
|
-
puts "p#{ Process.pid } #{ Time.new } tunnel #{ hello.inspect }"
|
1524
|
-
data = "#{ [ HELLO ].pack( 'C' ) }#{ hello }"
|
1525
|
-
add_ctlmsg( data )
|
1526
|
-
|
1527
|
-
@roles.delete( pre_proxy )
|
1528
|
-
@writes.delete( pre_proxy )
|
1529
|
-
end
|
1530
|
-
|
1531
|
-
##
|
1532
|
-
# write pre tun
|
1533
|
-
#
|
1534
|
-
def write_pre_tun( pre_tun )
|
1535
|
-
if pre_tun.closed? then
|
1536
|
-
puts "p#{ Process.pid } #{ Time.new } write pre tun but pre tun closed?"
|
1537
|
-
return
|
1538
|
-
end
|
1539
|
-
|
1540
|
-
pre_tun_info = @pre_tun_infos[ pre_tun ]
|
1541
|
-
src = pre_tun_info[ :src ]
|
1542
|
-
|
1543
|
-
if src.closed? then
|
1544
|
-
puts "p#{ Process.pid } #{ Time.new } new a tun but src closed?"
|
1545
|
-
return
|
1546
|
-
end
|
1547
|
-
|
1548
|
-
tun = OpenSSL::SSL::SSLSocket.new pre_tun
|
1549
|
-
|
1550
|
-
begin
|
1551
|
-
tun.connect_nonblock
|
1552
|
-
rescue IO::WaitReadable
|
1553
|
-
rescue IO::WaitWritable
|
1554
|
-
rescue Exception => e
|
1555
|
-
puts "p#{ Process.pid } #{ Time.new } tun connect #{ e.class }, close tun"
|
1556
|
-
tun.close
|
1557
|
-
close_pre_tun( pre_tun )
|
1514
|
+
# puts "debug write btun #{ e.class }"
|
1515
|
+
src = btun_info[ :src ]
|
1516
|
+
close_btun( btun )
|
1517
|
+
add_closing_src( src )
|
1558
1518
|
return
|
1559
1519
|
end
|
1560
1520
|
|
1561
|
-
|
1562
|
-
|
1563
|
-
# puts "debug1 set tun.wbuff #{ dst_id }"
|
1564
|
-
data = [ dst_id ].pack( 'n' )
|
1565
|
-
|
1566
|
-
unless src_info[ :rbuff ].empty? then
|
1567
|
-
# puts "debug1 move src.rbuff to tun.wbuff"
|
1568
|
-
data << src_info[ :rbuff ]
|
1569
|
-
end
|
1570
|
-
|
1571
|
-
domain = src_info[ :destination_domain ]
|
1572
|
-
@tun_infos[ tun ] = {
|
1573
|
-
pre_tun: pre_tun, # 对应pre tun
|
1574
|
-
src: src, # 对应src
|
1575
|
-
domain: domain, # 目的地
|
1576
|
-
wbuff: data, # 写前
|
1577
|
-
closing_write: false, # 准备关闭写
|
1578
|
-
close_read: false, # 已经关闭读
|
1579
|
-
close_write: false # 已经关闭写
|
1580
|
-
}
|
1581
|
-
|
1582
|
-
src_info[ :tun ] = tun
|
1583
|
-
add_read( tun, :tun )
|
1584
|
-
add_write( tun )
|
1585
|
-
|
1586
|
-
if src_info[ :proxy_proto ] == :http then
|
1587
|
-
if src_info[ :is_connect ] then
|
1588
|
-
# puts "debug1 add src.wbuff http ok"
|
1589
|
-
add_src_wbuff( src, HTTP_OK )
|
1590
|
-
end
|
1591
|
-
elsif src_info[ :proxy_proto ] == :socks5 then
|
1592
|
-
add_socks5_conn_reply( src )
|
1593
|
-
end
|
1594
|
-
|
1595
|
-
@pre_tun_infos.delete( pre_tun )
|
1596
|
-
@roles.delete( pre_tun )
|
1597
|
-
@writes.delete( pre_tun )
|
1521
|
+
# puts "debug write btun #{ written }"
|
1522
|
+
@writes.delete( btun )
|
1598
1523
|
end
|
1599
1524
|
|
1600
1525
|
end
|