girl 3.9.0 → 4.0.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 -0
- data/lib/girl/concurrent_hash.rb +4 -0
- data/lib/girl/custom.rb +11 -0
- data/lib/girl/head.rb +11 -1
- data/lib/girl/proxy.rb +30 -31
- data/lib/girl/proxy_custom.rb +16 -13
- data/lib/girl/proxy_worker.rb +491 -595
- data/lib/girl/proxyd.rb +1 -15
- data/lib/girl/proxyd_custom.rb +12 -9
- data/lib/girl/proxyd_worker.rb +499 -481
- data/lib/girl/relay.rb +0 -1
- data/lib/girl/relay_worker.rb +460 -573
- data/lib/girl/resolvd_worker.rb +1 -1
- data/lib/girl/ssl.rb +1 -14
- data/lib/girl/ssl_worker.rb +124 -100
- data/lib/girl/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 826fa8949af020a9cf2e9158d0c95630f9ad0495370c22fd058542926e27dd72
|
4
|
+
data.tar.gz: b880ce49e5c125fb819626d0c124d7cae52b9da59627cfa7f87b6098fbd075c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a06cb288a4f42d3ad1f73c9e6effe6e3c85ba5485f24940b9a6f36fec254be990b313922273ae28308ef9ef7f9e339797a2b79ed4a4ff8607717da4911edd47e
|
7
|
+
data.tar.gz: f8c6f735a2553134112885bbb2462d2d1eed44ac7cd1bc4873881644393e7a861cd7345a006b898692ea8036f0d87a81901343658e674b4be23ebe49369facd2
|
data/girl.gemspec
CHANGED
data/lib/girl/concurrent_hash.rb
CHANGED
data/lib/girl/custom.rb
ADDED
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,34 @@ 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: tund port
|
18
|
+
3 a new source -> Q>: src id -> encoded destination address
|
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 -> Q>: src id -> encoded domain
|
36
|
+
21 resolved -> Q>: src id -> encoded ip
|
37
|
+
22 heartbeat NOT USE
|
38
|
+
23 unknown ctl addr
|
39
|
+
24 ctl fin
|
40
|
+
25 source eof -> Q>: dst id
|
41
|
+
26 dest eof -> Q>: src id
|
38
42
|
101 traff infos
|
39
|
-
101 traff infos
|
43
|
+
101 traff infos -> [ C: im len -> im -> Q>: traff in -> Q>: traff out ]
|
40
44
|
=end
|
41
45
|
|
42
46
|
module Girl
|
@@ -56,7 +60,6 @@ module Girl
|
|
56
60
|
direct_path = conf[ :direct_path ]
|
57
61
|
remote_path = conf[ :remote_path ]
|
58
62
|
im = conf[ :im ]
|
59
|
-
use_remote_resolv = conf[ :use_remote_resolv ]
|
60
63
|
worker_count = conf[ :worker_count ]
|
61
64
|
|
62
65
|
unless redir_port then
|
@@ -87,10 +90,6 @@ module Girl
|
|
87
90
|
im = 'girl'
|
88
91
|
end
|
89
92
|
|
90
|
-
unless use_remote_resolv then
|
91
|
-
use_remote_resolv = false
|
92
|
-
end
|
93
|
-
|
94
93
|
nprocessors = Etc.nprocessors
|
95
94
|
|
96
95
|
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
|
@@ -105,7 +104,7 @@ module Girl
|
|
105
104
|
|
106
105
|
title = "girl proxy #{ Girl::VERSION }"
|
107
106
|
puts title
|
108
|
-
puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im }
|
107
|
+
puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im } worker count #{ worker_count }"
|
109
108
|
puts "#{ direct_path } #{ directs.size } directs"
|
110
109
|
puts "#{ remote_path } #{ remotes.size } remotes"
|
111
110
|
|
@@ -116,7 +115,7 @@ module Girl
|
|
116
115
|
worker_count.times do | i |
|
117
116
|
workers << fork do
|
118
117
|
$0 = 'girl proxy worker'
|
119
|
-
worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im
|
118
|
+
worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
|
120
119
|
|
121
120
|
Signal.trap( :TERM ) do
|
122
121
|
puts "w#{ i } exit"
|
@@ -140,7 +139,7 @@ module Girl
|
|
140
139
|
|
141
140
|
Process.waitall
|
142
141
|
else
|
143
|
-
Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im
|
142
|
+
Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
|
144
143
|
end
|
145
144
|
end
|
146
145
|
|
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,27 @@ 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
9
|
@proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
|
10
10
|
@directs = directs
|
11
11
|
@remotes = remotes
|
12
12
|
@custom = Girl::ProxyCustom.new( im )
|
13
|
-
@use_remote_resolv = use_remote_resolv
|
14
13
|
@reads = []
|
15
14
|
@writes = []
|
16
15
|
@closing_srcs = []
|
17
16
|
@paused_srcs = []
|
18
17
|
@paused_dsts = []
|
19
|
-
@
|
18
|
+
@paused_btuns = []
|
20
19
|
@resume_srcs = []
|
21
20
|
@resume_dsts = []
|
22
|
-
@
|
21
|
+
@resume_btuns = []
|
23
22
|
@pending_srcs = [] # 还没配到tund,暂存的src
|
24
|
-
@roles = ConcurrentHash.new # sock => :dotr / :redir / :
|
23
|
+
@roles = ConcurrentHash.new # sock => :dotr / :redir / :ctl / :src / :dst / :atun / :btun
|
25
24
|
@src_infos = ConcurrentHash.new # src => {}
|
26
25
|
@dst_infos = ConcurrentHash.new # dst => {}
|
27
|
-
@
|
28
|
-
@
|
26
|
+
@atun_infos = ConcurrentHash.new # atun => {}
|
27
|
+
@btun_infos = ConcurrentHash.new # btun => {}
|
29
28
|
@resolv_caches = ConcurrentHash.new # domain => [ ip, created_at ]
|
30
29
|
@is_direct_caches = ConcurrentHash.new # ip => true / false
|
31
30
|
@srcs = ConcurrentHash.new # src_id => src
|
@@ -46,6 +45,7 @@ module Girl
|
|
46
45
|
loop_check_resume
|
47
46
|
|
48
47
|
loop do
|
48
|
+
# puts "debug select"
|
49
49
|
rs, ws = IO.select( @reads, @writes )
|
50
50
|
|
51
51
|
rs.each do | sock |
|
@@ -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,33 @@ 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_infos.delete( atun )
|
303
299
|
end
|
304
300
|
|
305
301
|
##
|
306
|
-
# close
|
302
|
+
# close btun
|
307
303
|
#
|
308
|
-
def
|
309
|
-
return if
|
310
|
-
# puts "
|
311
|
-
close_sock(
|
312
|
-
@
|
304
|
+
def close_btun( btun )
|
305
|
+
return if btun.closed?
|
306
|
+
# puts "debug close btun"
|
307
|
+
close_sock( btun )
|
308
|
+
@btun_infos.delete( btun )
|
309
|
+
@paused_btuns.delete( btun )
|
310
|
+
@resume_btuns.delete( btun )
|
313
311
|
end
|
314
312
|
|
315
313
|
##
|
316
|
-
# close
|
314
|
+
# close ctl
|
317
315
|
#
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
close_sock( proxy )
|
322
|
-
close_pre_proxy( @pre_proxy )
|
316
|
+
def close_ctl( ctl )
|
317
|
+
close_sock( ctl )
|
318
|
+
@ctl_info[ :resends ].clear
|
323
319
|
end
|
324
320
|
|
325
321
|
##
|
@@ -327,20 +323,15 @@ module Girl
|
|
327
323
|
#
|
328
324
|
def close_read_dst( dst )
|
329
325
|
return if dst.closed?
|
330
|
-
# puts "
|
326
|
+
# puts "debug close read dst"
|
331
327
|
dst.close_read
|
332
328
|
@reads.delete( dst )
|
333
329
|
|
334
330
|
if dst.closed? then
|
335
|
-
# puts "debug1 delete dst info"
|
336
331
|
@writes.delete( dst )
|
337
332
|
@roles.delete( dst )
|
338
|
-
|
339
|
-
else
|
340
|
-
dst_info = @dst_infos[ dst ]
|
333
|
+
del_dst_info( dst )
|
341
334
|
end
|
342
|
-
|
343
|
-
dst_info
|
344
335
|
end
|
345
336
|
|
346
337
|
##
|
@@ -348,39 +339,15 @@ module Girl
|
|
348
339
|
#
|
349
340
|
def close_read_src( src )
|
350
341
|
return if src.closed?
|
351
|
-
# puts "
|
342
|
+
# puts "debug close read src"
|
352
343
|
src.close_read
|
353
344
|
@reads.delete( src )
|
354
345
|
|
355
346
|
if src.closed? then
|
356
|
-
# puts "debug1 delete src info"
|
357
347
|
@writes.delete( src )
|
358
348
|
@roles.delete( src )
|
359
|
-
|
360
|
-
else
|
361
|
-
src_info = @src_infos[ src ]
|
349
|
+
del_src_info( src )
|
362
350
|
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
351
|
end
|
385
352
|
|
386
353
|
##
|
@@ -398,59 +365,42 @@ module Girl
|
|
398
365
|
#
|
399
366
|
def close_src( src )
|
400
367
|
return if src.closed?
|
401
|
-
# puts "
|
368
|
+
# puts "debug close src"
|
402
369
|
close_sock( src )
|
403
370
|
src_info = del_src_info( src )
|
404
371
|
dst = src_info[ :dst ]
|
405
372
|
|
406
373
|
if dst then
|
407
374
|
close_sock( dst )
|
408
|
-
|
375
|
+
del_dst_info( dst )
|
409
376
|
else
|
410
|
-
|
377
|
+
atun = src_info[ :atun ]
|
378
|
+
btun = src_info[ :btun ]
|
411
379
|
|
412
|
-
if
|
413
|
-
|
414
|
-
|
415
|
-
pre_tun = src_info[ :pre_tun ]
|
380
|
+
if atun then
|
381
|
+
close_atun( atun )
|
382
|
+
end
|
416
383
|
|
417
|
-
|
418
|
-
|
419
|
-
end
|
384
|
+
if btun then
|
385
|
+
close_btun( btun )
|
420
386
|
end
|
421
387
|
end
|
422
388
|
end
|
423
389
|
|
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
390
|
##
|
436
391
|
# close write dst
|
437
392
|
#
|
438
393
|
def close_write_dst( dst )
|
439
394
|
return if dst.closed?
|
440
|
-
# puts "
|
395
|
+
# puts "debug close write dst"
|
441
396
|
dst.close_write
|
442
397
|
@writes.delete( dst )
|
443
398
|
|
444
399
|
if dst.closed? then
|
445
|
-
# puts "debug1 delete dst info"
|
446
400
|
@reads.delete( dst )
|
447
401
|
@roles.delete( dst )
|
448
|
-
|
449
|
-
else
|
450
|
-
dst_info = @dst_infos[ dst ]
|
402
|
+
del_dst_info( dst )
|
451
403
|
end
|
452
|
-
|
453
|
-
dst_info
|
454
404
|
end
|
455
405
|
|
456
406
|
##
|
@@ -458,39 +408,15 @@ module Girl
|
|
458
408
|
#
|
459
409
|
def close_write_src( src )
|
460
410
|
return if src.closed?
|
461
|
-
# puts "
|
411
|
+
# puts "debug close write src"
|
462
412
|
src.close_write
|
463
413
|
@writes.delete( src )
|
464
414
|
|
465
415
|
if src.closed? then
|
466
|
-
# puts "debug1 delete src info"
|
467
416
|
@reads.delete( src )
|
468
417
|
@roles.delete( src )
|
469
|
-
|
470
|
-
else
|
471
|
-
src_info = @src_infos[ src ]
|
472
|
-
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 )
|
418
|
+
del_src_info( src )
|
491
419
|
end
|
492
|
-
|
493
|
-
tun_info
|
494
420
|
end
|
495
421
|
|
496
422
|
##
|
@@ -525,23 +451,36 @@ module Girl
|
|
525
451
|
end
|
526
452
|
|
527
453
|
if is_direct then
|
528
|
-
# puts "
|
454
|
+
# puts "debug #{ ip_info.inspect } hit directs"
|
529
455
|
new_a_dst( src, ip_info )
|
530
456
|
else
|
531
457
|
# 走远端
|
532
|
-
# puts "
|
458
|
+
# puts "debug #{ ip_info.inspect } go tunnel"
|
533
459
|
set_proxy_type_tunnel( src )
|
534
460
|
end
|
535
461
|
end
|
536
462
|
|
463
|
+
##
|
464
|
+
# del dst info
|
465
|
+
#
|
466
|
+
def del_dst_info( dst )
|
467
|
+
# puts "debug delete dst info"
|
468
|
+
dst_info = @dst_infos.delete( dst )
|
469
|
+
@paused_dsts.delete( dst )
|
470
|
+
@resume_dsts.delete( dst )
|
471
|
+
dst_info
|
472
|
+
end
|
473
|
+
|
537
474
|
##
|
538
475
|
# del src info
|
539
476
|
#
|
540
477
|
def del_src_info( src )
|
478
|
+
# puts "debug delete src info"
|
541
479
|
src_info = @src_infos.delete( src )
|
542
480
|
@srcs.delete( src_info[ :id ] )
|
543
481
|
@pending_srcs.delete( src )
|
544
|
-
|
482
|
+
@paused_srcs.delete( src )
|
483
|
+
@resume_srcs.delete( src )
|
545
484
|
src_info
|
546
485
|
end
|
547
486
|
|
@@ -554,37 +493,23 @@ module Girl
|
|
554
493
|
sleep CHECK_EXPIRE_INTERVAL
|
555
494
|
now = Time.new
|
556
495
|
|
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
|
496
|
+
if @ctl && !@ctl.closed? then
|
497
|
+
last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
|
565
498
|
|
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 )
|
499
|
+
if now - last_recv_at >= EXPIRE_AFTER then
|
500
|
+
puts "p#{ Process.pid } #{ Time.new } expire ctl"
|
501
|
+
@ctl_info[ :closing ] = true
|
502
|
+
next_tick
|
574
503
|
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
504
|
end
|
580
505
|
|
581
506
|
@src_infos.each do | src, src_info |
|
582
507
|
last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
|
583
508
|
last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
|
584
|
-
expire_after = ( src_info[ :dst ] || src_info[ :
|
509
|
+
expire_after = ( src_info[ :dst ] || src_info[ :atun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
|
585
510
|
|
586
511
|
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 ] }"
|
512
|
+
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
|
588
513
|
add_closing_src( src )
|
589
514
|
|
590
515
|
unless src_info[ :rbuff ].empty? then
|
@@ -605,64 +530,77 @@ module Girl
|
|
605
530
|
sleep CHECK_RESUME_INTERVAL
|
606
531
|
|
607
532
|
@paused_srcs.each do | src |
|
608
|
-
|
609
|
-
|
533
|
+
src_info = @src_infos[ src ]
|
534
|
+
dst = src_info[ :dst ]
|
535
|
+
|
536
|
+
if dst then
|
537
|
+
dst_info = @dst_infos[ dst ]
|
538
|
+
|
539
|
+
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
540
|
+
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
541
|
+
add_resume_src( src )
|
542
|
+
end
|
610
543
|
else
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
if
|
615
|
-
|
616
|
-
|
617
|
-
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
618
|
-
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
619
|
-
add_resume_src( src )
|
620
|
-
end
|
621
|
-
else
|
622
|
-
tun = src_info[ :tun ]
|
623
|
-
tun_info = @tun_infos[ tun ]
|
624
|
-
|
625
|
-
if tun_info[ :wbuff ].size < RESUME_BELOW then
|
626
|
-
puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
|
627
|
-
add_resume_src( src )
|
628
|
-
end
|
544
|
+
btun = src_info[ :btun ]
|
545
|
+
btun_info = @btun_infos[ btun ]
|
546
|
+
|
547
|
+
if btun_info[ :wbuff ].size < RESUME_BELOW then
|
548
|
+
puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
|
549
|
+
add_resume_src( src )
|
629
550
|
end
|
630
551
|
end
|
631
552
|
end
|
632
553
|
|
633
554
|
@paused_dsts.each do | dst |
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
dst_info = @dst_infos[ dst ]
|
638
|
-
src = dst_info[ :src ]
|
639
|
-
src_info = @src_infos[ src ]
|
555
|
+
dst_info = @dst_infos[ dst ]
|
556
|
+
src = dst_info[ :src ]
|
557
|
+
src_info = @src_infos[ src ]
|
640
558
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
end
|
559
|
+
if src_info[ :wbuff ].size < RESUME_BELOW then
|
560
|
+
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
|
561
|
+
add_resume_dst( dst )
|
645
562
|
end
|
646
563
|
end
|
647
564
|
|
648
|
-
@
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
tun_info = @tun_infos[ tun ]
|
653
|
-
src = tun_info[ :src ]
|
654
|
-
src_info = @src_infos[ src ]
|
565
|
+
@paused_btuns.each do | btun |
|
566
|
+
btun_info = @btun_infos[ btun ]
|
567
|
+
src = btun_info[ :src ]
|
568
|
+
src_info = @src_infos[ src ]
|
655
569
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
end
|
570
|
+
if src_info[ :wbuff ].size < RESUME_BELOW then
|
571
|
+
puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
|
572
|
+
add_resume_btun( btun )
|
660
573
|
end
|
661
574
|
end
|
662
575
|
end
|
663
576
|
end
|
664
577
|
end
|
665
578
|
|
579
|
+
##
|
580
|
+
# loop resend ctlmsg
|
581
|
+
#
|
582
|
+
def loop_resend_ctlmsg( key, ctlmsg )
|
583
|
+
Thread.new do
|
584
|
+
loop do
|
585
|
+
sleep RESEND_INTERVAL
|
586
|
+
|
587
|
+
resend = @ctl_info[ :resends ][ key ]
|
588
|
+
break unless resend
|
589
|
+
|
590
|
+
puts "p#{ Process.pid } #{ Time.new } resend #{ ctlmsg.inspect }"
|
591
|
+
send_ctlmsg( ctlmsg )
|
592
|
+
resend += 1
|
593
|
+
|
594
|
+
if resend >= RESEND_LIMIT then
|
595
|
+
@ctl_info[ :resends ].delete( key )
|
596
|
+
break
|
597
|
+
end
|
598
|
+
|
599
|
+
@ctl_info[ :resends ][ key ] = resend
|
600
|
+
end
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
666
604
|
##
|
667
605
|
# new a dst
|
668
606
|
#
|
@@ -672,7 +610,6 @@ module Girl
|
|
672
610
|
domain = src_info[ :destination_domain ]
|
673
611
|
destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
|
674
612
|
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
613
|
|
677
614
|
begin
|
678
615
|
dst.connect_nonblock( destination_addr )
|
@@ -685,7 +622,7 @@ module Girl
|
|
685
622
|
return
|
686
623
|
end
|
687
624
|
|
688
|
-
# puts "
|
625
|
+
# puts "debug a new dst #{ dst.local_address.inspect }"
|
689
626
|
dst_info = {
|
690
627
|
src: src, # 对应src
|
691
628
|
domain: domain, # 目的地
|
@@ -700,10 +637,10 @@ module Girl
|
|
700
637
|
|
701
638
|
if src_info[ :proxy_proto ] == :http then
|
702
639
|
if src_info[ :is_connect ] then
|
703
|
-
# puts "
|
640
|
+
# puts "debug add src.wbuff http ok"
|
704
641
|
add_src_wbuff( src, HTTP_OK )
|
705
642
|
elsif src_info[ :rbuff ] then
|
706
|
-
# puts "
|
643
|
+
# puts "debug move src.rbuff to dst.wbuff"
|
707
644
|
dst_info[ :wbuff ] << src_info[ :rbuff ]
|
708
645
|
add_write( dst )
|
709
646
|
end
|
@@ -713,65 +650,31 @@ module Girl
|
|
713
650
|
end
|
714
651
|
|
715
652
|
##
|
716
|
-
# new a
|
653
|
+
# new a ctl
|
717
654
|
#
|
718
|
-
def
|
719
|
-
|
720
|
-
pre_proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
655
|
+
def new_a_ctl
|
656
|
+
ctl = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
721
657
|
|
722
658
|
if RUBY_PLATFORM.include?( 'linux' ) then
|
723
|
-
|
724
|
-
pre_proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
659
|
+
ctl.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
725
660
|
end
|
726
661
|
|
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
|
662
|
+
@ctl = ctl
|
663
|
+
add_read( ctl, :ctl )
|
735
664
|
|
736
|
-
@
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
665
|
+
@ctl_info = {
|
666
|
+
resends: ConcurrentHash.new, # key => count
|
667
|
+
atund_addr: nil, # atund地址,src->dst
|
668
|
+
btund_addr: nil, # btund地址,dst->src
|
669
|
+
closing: false, # 准备关闭
|
670
|
+
created_at: Time.new, # 创建时间
|
671
|
+
last_recv_at: nil # 最近一次收到数据时间
|
741
672
|
}
|
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
|
-
|
754
|
-
pre_tun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
755
|
-
pre_tun.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
|
756
|
-
|
757
|
-
begin
|
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
673
|
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
destination_domain: src_info[ :destination_domain ],
|
771
|
-
created_at: Time.new
|
772
|
-
}
|
773
|
-
@roles[ pre_tun ] = :pre_tun
|
774
|
-
add_write( pre_tun )
|
674
|
+
hello = @custom.hello
|
675
|
+
puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect }"
|
676
|
+
key = [ HELLO ].pack( 'C' )
|
677
|
+
add_ctlmsg( key, hello )
|
775
678
|
end
|
776
679
|
|
777
680
|
##
|
@@ -783,7 +686,6 @@ module Girl
|
|
783
686
|
|
784
687
|
if RUBY_PLATFORM.include?( 'linux' ) then
|
785
688
|
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
786
|
-
redir.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
787
689
|
end
|
788
690
|
|
789
691
|
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
@@ -794,6 +696,84 @@ module Girl
|
|
794
696
|
@redir_local_address = redir.local_address
|
795
697
|
end
|
796
698
|
|
699
|
+
##
|
700
|
+
# new tuns
|
701
|
+
#
|
702
|
+
def new_tuns( src_id, dst_id )
|
703
|
+
src = @srcs[ src_id ]
|
704
|
+
return if src.nil? || src.closed?
|
705
|
+
src_info = @src_infos[ src ]
|
706
|
+
return if src_info[ :dst_id ]
|
707
|
+
|
708
|
+
# puts "debug new atun and btun"
|
709
|
+
atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
710
|
+
|
711
|
+
begin
|
712
|
+
atun.connect_nonblock( @ctl_info[ :atund_addr ] )
|
713
|
+
rescue IO::WaitWritable
|
714
|
+
rescue Exception => e
|
715
|
+
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
|
716
|
+
atun.close
|
717
|
+
return
|
718
|
+
end
|
719
|
+
|
720
|
+
btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
721
|
+
|
722
|
+
begin
|
723
|
+
btun.connect_nonblock( @ctl_info[ :btund_addr ] )
|
724
|
+
rescue IO::WaitWritable
|
725
|
+
rescue Exception => e
|
726
|
+
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
|
727
|
+
btun.close
|
728
|
+
return
|
729
|
+
end
|
730
|
+
|
731
|
+
domain = src_info[ :destination_domain ]
|
732
|
+
atun_wbuff = [ dst_id ].pack( 'n' )
|
733
|
+
|
734
|
+
until src_info[ :rbuff ].empty? do
|
735
|
+
data = src_info[ :rbuff ][ 0, 65535 ]
|
736
|
+
data_size = data.bytesize
|
737
|
+
# puts "debug move src.rbuff #{ data_size } to atun.wbuff"
|
738
|
+
atun_wbuff << pack_a_chunk( data )
|
739
|
+
src_info[ :rbuff ] = src_info[ :rbuff ][ data_size..-1 ]
|
740
|
+
end
|
741
|
+
|
742
|
+
@atun_infos[ atun ] = {
|
743
|
+
src: src, # 对应src
|
744
|
+
domain: domain, # 目的地
|
745
|
+
wbuff: atun_wbuff, # 写前
|
746
|
+
closing: false # 准备关闭
|
747
|
+
}
|
748
|
+
|
749
|
+
btun_wbuff = [ dst_id ].pack( 'n' )
|
750
|
+
|
751
|
+
@btun_infos[ btun ] = {
|
752
|
+
src: src, # 对应src
|
753
|
+
domain: domain, # 目的地
|
754
|
+
wbuff: btun_wbuff, # 写前
|
755
|
+
rbuff: '', # 暂存当前块没收全的流量
|
756
|
+
wait_bytes: 0 # 还差多少字节收全当前块
|
757
|
+
}
|
758
|
+
|
759
|
+
src_info[ :dst_id ] = dst_id
|
760
|
+
src_info[ :atun ] = atun
|
761
|
+
src_info[ :btun ] = btun
|
762
|
+
add_read( atun, :atun )
|
763
|
+
add_read( btun, :btun )
|
764
|
+
add_write( atun )
|
765
|
+
add_write( btun )
|
766
|
+
|
767
|
+
if src_info[ :proxy_proto ] == :http then
|
768
|
+
if src_info[ :is_connect ] then
|
769
|
+
# puts "debug add src.wbuff http ok"
|
770
|
+
add_src_wbuff( src, HTTP_OK )
|
771
|
+
end
|
772
|
+
elsif src_info[ :proxy_proto ] == :socks5 then
|
773
|
+
add_socks5_conn_reply( src )
|
774
|
+
end
|
775
|
+
end
|
776
|
+
|
797
777
|
##
|
798
778
|
# next tick
|
799
779
|
#
|
@@ -801,6 +781,15 @@ module Girl
|
|
801
781
|
@dotw.write( '.' )
|
802
782
|
end
|
803
783
|
|
784
|
+
##
|
785
|
+
# pack a chunk
|
786
|
+
#
|
787
|
+
def pack_a_chunk( data )
|
788
|
+
# puts "debug pack a chunk"
|
789
|
+
data = @custom.encode( data )
|
790
|
+
"#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
|
791
|
+
end
|
792
|
+
|
804
793
|
##
|
805
794
|
# resolve domain
|
806
795
|
#
|
@@ -817,24 +806,18 @@ module Girl
|
|
817
806
|
ip_info, created_at = resolv_cache
|
818
807
|
|
819
808
|
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
820
|
-
# puts "
|
809
|
+
# puts "debug #{ domain } hit resolv cache #{ ip_info.inspect }"
|
821
810
|
deal_with_destination_ip( src, ip_info )
|
822
811
|
return
|
823
812
|
end
|
824
813
|
|
825
|
-
# puts "
|
814
|
+
# puts "debug expire #{ domain } resolv cache"
|
826
815
|
@resolv_caches.delete( domain )
|
827
816
|
end
|
828
817
|
|
829
818
|
src_info = @src_infos[ src ]
|
830
819
|
src_info[ :proxy_type ] = :checking
|
831
820
|
|
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
821
|
Thread.new do
|
839
822
|
begin
|
840
823
|
ip_info = Addrinfo.ip( domain )
|
@@ -852,6 +835,33 @@ module Girl
|
|
852
835
|
end
|
853
836
|
end
|
854
837
|
|
838
|
+
##
|
839
|
+
# send ctlmsg
|
840
|
+
#
|
841
|
+
def send_ctlmsg( data )
|
842
|
+
return if @ctl.nil? || @ctl.closed?
|
843
|
+
|
844
|
+
begin
|
845
|
+
@ctl.sendmsg( data, 0, @proxyd_addr )
|
846
|
+
@ctl_info[ :last_sent_at ] = Time.new
|
847
|
+
rescue Exception => e
|
848
|
+
puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
|
849
|
+
close_ctl( @ctl )
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
##
|
854
|
+
# set atun closing
|
855
|
+
#
|
856
|
+
def set_atun_closing( atun )
|
857
|
+
return if atun.closed?
|
858
|
+
atun_info = @atun_infos[ atun ]
|
859
|
+
return if atun_info[ :closing ]
|
860
|
+
# puts "debug set atun closing"
|
861
|
+
atun_info[ :closing ] = true
|
862
|
+
add_write( atun )
|
863
|
+
end
|
864
|
+
|
855
865
|
##
|
856
866
|
# set dst closing write
|
857
867
|
#
|
@@ -859,6 +869,7 @@ module Girl
|
|
859
869
|
return if dst.closed?
|
860
870
|
dst_info = @dst_infos[ dst ]
|
861
871
|
return if dst_info[ :closing_write ]
|
872
|
+
# puts "debug set dst closing write"
|
862
873
|
dst_info[ :closing_write ] = true
|
863
874
|
add_write( dst )
|
864
875
|
end
|
@@ -872,7 +883,7 @@ module Girl
|
|
872
883
|
src_info[ :proxy_type ] = :tunnel
|
873
884
|
src_id = src_info[ :id ]
|
874
885
|
|
875
|
-
if @
|
886
|
+
if @ctl && !@ctl.closed? && @ctl_info[ :atund_addr ] then
|
876
887
|
add_a_new_source( src )
|
877
888
|
else
|
878
889
|
@pending_srcs << src
|
@@ -890,17 +901,6 @@ module Girl
|
|
890
901
|
add_write( src )
|
891
902
|
end
|
892
903
|
|
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
904
|
##
|
905
905
|
# sub http request
|
906
906
|
#
|
@@ -914,7 +914,7 @@ module Girl
|
|
914
914
|
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
915
915
|
domain_port = url.split( '/' )[ 2 ]
|
916
916
|
data = data.sub( "http://#{ domain_port }", '' )
|
917
|
-
# puts "
|
917
|
+
# puts "debug subed #{ data.inspect } #{ domain_port }"
|
918
918
|
end
|
919
919
|
|
920
920
|
[ data, domain_port ]
|
@@ -924,14 +924,11 @@ module Girl
|
|
924
924
|
# read dotr
|
925
925
|
#
|
926
926
|
def read_dotr( dotr )
|
927
|
-
dotr.read_nonblock(
|
927
|
+
dotr.read_nonblock( 65535 )
|
928
928
|
|
929
|
-
if @
|
930
|
-
|
931
|
-
|
932
|
-
end
|
933
|
-
elsif @pre_proxy && !@pre_proxy.closed? && @pre_proxy_info[ :closing ] then
|
934
|
-
close_pre_proxy( @pre_proxy )
|
929
|
+
if @ctl_info && @ctl_info[ :closing ] then
|
930
|
+
send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
|
931
|
+
close_ctl( @ctl )
|
935
932
|
end
|
936
933
|
|
937
934
|
if @closing_srcs.any? then
|
@@ -957,13 +954,13 @@ module Girl
|
|
957
954
|
@resume_dsts.clear
|
958
955
|
end
|
959
956
|
|
960
|
-
if @
|
961
|
-
@
|
962
|
-
add_read(
|
963
|
-
@
|
957
|
+
if @resume_btuns.any? then
|
958
|
+
@resume_btuns.each do | btun |
|
959
|
+
add_read( btun )
|
960
|
+
@paused_btuns.delete( btun )
|
964
961
|
end
|
965
962
|
|
966
|
-
@
|
963
|
+
@resume_btuns.clear
|
967
964
|
end
|
968
965
|
end
|
969
966
|
|
@@ -979,7 +976,7 @@ module Girl
|
|
979
976
|
end
|
980
977
|
|
981
978
|
src_id = rand( ( 2 ** 64 ) - 2 ) + 1
|
982
|
-
# puts "
|
979
|
+
# puts "debug accept a src #{ src_id } #{ addrinfo.ip_unpack.inspect }"
|
983
980
|
|
984
981
|
@srcs[ src_id ] = src
|
985
982
|
@src_infos[ src ] = {
|
@@ -991,10 +988,11 @@ module Girl
|
|
991
988
|
is_connect: true, # 代理协议是http的场合,是否是CONNECT
|
992
989
|
rbuff: '', # 读到的流量
|
993
990
|
dst: nil, # :direct的场合,对应的dst
|
994
|
-
|
995
|
-
|
991
|
+
ctl: nil, # :tunnel的场合,对应的ctl
|
992
|
+
atun: nil, # :tunnel的场合,对应的atun
|
993
|
+
btun: nil, # :tunnel的场合,对应的btun
|
996
994
|
dst_id: nil, # 远端dst id
|
997
|
-
wbuff: '', # 从dst/
|
995
|
+
wbuff: '', # 从dst/btun读到的流量
|
998
996
|
created_at: Time.new, # 创建时间
|
999
997
|
last_recv_at: nil, # 上一次收到新流量(由dst收到,或者由tun收到)的时间
|
1000
998
|
last_sent_at: nil, # 上一次发出流量(由dst发出,或者由tun发出)的时间
|
@@ -1003,75 +1001,50 @@ module Girl
|
|
1003
1001
|
|
1004
1002
|
add_read( src, :src )
|
1005
1003
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
new_a_pre_proxy
|
1004
|
+
if @ctl.nil? || @ctl.closed? then
|
1005
|
+
new_a_ctl
|
1009
1006
|
end
|
1010
1007
|
end
|
1011
1008
|
|
1012
1009
|
##
|
1013
|
-
# read
|
1010
|
+
# read ctl
|
1014
1011
|
#
|
1015
|
-
def
|
1016
|
-
if proxy.closed? then
|
1017
|
-
puts "p#{ Process.pid } #{ Time.new } read proxy but proxy closed?"
|
1018
|
-
return
|
1019
|
-
end
|
1020
|
-
|
1012
|
+
def read_ctl( ctl )
|
1021
1013
|
begin
|
1022
|
-
data =
|
1023
|
-
rescue IO::WaitReadable
|
1024
|
-
return
|
1025
|
-
rescue Errno::EINTR
|
1026
|
-
puts e.class
|
1027
|
-
return
|
1014
|
+
data, addrinfo, rflags, *controls = ctl.recvmsg
|
1028
1015
|
rescue Exception => e
|
1029
|
-
|
1030
|
-
|
1016
|
+
puts "p#{ Process.pid } #{ Time.new } recvmsg #{ e.class }"
|
1017
|
+
close_ctl( ctl )
|
1031
1018
|
return
|
1032
1019
|
end
|
1033
1020
|
|
1034
|
-
|
1021
|
+
ctl_num = data[ 0 ].unpack( 'C' ).first
|
1035
1022
|
|
1036
|
-
|
1037
|
-
|
1023
|
+
case ctl_num
|
1024
|
+
when TUND_PORT then
|
1025
|
+
return if @ctl_info[ :atund_addr ] || data.size != 5
|
1026
|
+
atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
|
1027
|
+
puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
|
1028
|
+
@ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
|
1029
|
+
@ctl_info[ :atund_addr ] = Socket.sockaddr_in( atund_port, @proxyd_host )
|
1030
|
+
@ctl_info[ :btund_addr ] = Socket.sockaddr_in( btund_port, @proxyd_host )
|
1031
|
+
@ctl_info[ :last_recv_at ] = Time.new
|
1038
1032
|
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
next if @proxy_info[ :tund_addr ] || ( ctlmsg.size != 3 )
|
1044
|
-
tund_port = ctlmsg[ 1, 2 ].unpack( 'n' ).first
|
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"
|
1033
|
+
if @pending_srcs.any? then
|
1034
|
+
puts "p#{ Process.pid } #{ Time.new } send pending sources"
|
1035
|
+
@pending_srcs.each { | src | add_a_new_source( src ) }
|
1036
|
+
@pending_srcs.clear
|
1074
1037
|
end
|
1038
|
+
when PAIRED then
|
1039
|
+
return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil? || data.size != 11
|
1040
|
+
src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
|
1041
|
+
# puts "debug got paired #{ src_id } #{ dst_id }"
|
1042
|
+
@ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
|
1043
|
+
@ctl_info[ :last_recv_at ] = Time.new
|
1044
|
+
new_tuns( src_id, dst_id )
|
1045
|
+
when UNKNOWN_CTL_ADDR then
|
1046
|
+
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
|
1047
|
+
close_ctl( ctl )
|
1075
1048
|
end
|
1076
1049
|
end
|
1077
1050
|
|
@@ -1084,33 +1057,38 @@ module Girl
|
|
1084
1057
|
return
|
1085
1058
|
end
|
1086
1059
|
|
1060
|
+
src_info = @src_infos[ src ]
|
1061
|
+
|
1087
1062
|
begin
|
1088
|
-
data = src.read_nonblock(
|
1089
|
-
rescue IO::WaitReadable
|
1063
|
+
data = src.read_nonblock( 65535 )
|
1064
|
+
rescue IO::WaitReadable
|
1090
1065
|
print 'r'
|
1091
1066
|
return
|
1092
1067
|
rescue Exception => e
|
1093
|
-
# puts "
|
1094
|
-
|
1068
|
+
# puts "debug read src #{ e.class }"
|
1069
|
+
close_read_src( src )
|
1095
1070
|
dst = src_info[ :dst ]
|
1096
1071
|
|
1097
1072
|
if dst then
|
1098
1073
|
set_dst_closing_write( dst )
|
1099
1074
|
else
|
1100
|
-
|
1101
|
-
|
1075
|
+
atun = src_info[ :atun ]
|
1076
|
+
|
1077
|
+
if atun then
|
1078
|
+
set_atun_closing( atun )
|
1079
|
+
end
|
1102
1080
|
end
|
1103
1081
|
|
1104
1082
|
return
|
1105
1083
|
end
|
1106
1084
|
|
1107
|
-
|
1085
|
+
# puts "debug read src #{ data.bytesize }"
|
1108
1086
|
proxy_type = src_info[ :proxy_type ]
|
1109
1087
|
|
1110
1088
|
case proxy_type
|
1111
1089
|
when :uncheck then
|
1112
1090
|
if data[ 0, 7 ] == 'CONNECT' then
|
1113
|
-
# puts "
|
1091
|
+
# puts "debug CONNECT"
|
1114
1092
|
domain_port = data.split( "\r\n" )[ 0 ].split( ' ' )[ 1 ]
|
1115
1093
|
|
1116
1094
|
unless domain_port then
|
@@ -1119,7 +1097,7 @@ module Girl
|
|
1119
1097
|
return
|
1120
1098
|
end
|
1121
1099
|
elsif data[ 0 ].unpack( 'C' ).first == 5 then
|
1122
|
-
# puts "
|
1100
|
+
# puts "debug socks5 #{ data.inspect }"
|
1123
1101
|
|
1124
1102
|
# https://tools.ietf.org/html/rfc1928
|
1125
1103
|
#
|
@@ -1148,11 +1126,11 @@ module Girl
|
|
1148
1126
|
src_info[ :proxy_type ] = :negotiation
|
1149
1127
|
return
|
1150
1128
|
else
|
1151
|
-
# puts "
|
1129
|
+
# puts "debug not CONNECT #{ data.inspect }"
|
1152
1130
|
host_line = data.split( "\r\n" ).find { | _line | _line[ 0, 6 ] == 'Host: ' }
|
1153
1131
|
|
1154
1132
|
unless host_line then
|
1155
|
-
# puts "
|
1133
|
+
# puts "debug not found host line"
|
1156
1134
|
add_closing_src( src )
|
1157
1135
|
return
|
1158
1136
|
end
|
@@ -1160,7 +1138,7 @@ module Girl
|
|
1160
1138
|
data, domain_port = sub_http_request( data )
|
1161
1139
|
|
1162
1140
|
unless domain_port then
|
1163
|
-
# puts "
|
1141
|
+
# puts "debug not HTTP"
|
1164
1142
|
domain_port = host_line.split( ' ' )[ 1 ]
|
1165
1143
|
|
1166
1144
|
unless domain_port then
|
@@ -1183,7 +1161,7 @@ module Girl
|
|
1183
1161
|
|
1184
1162
|
resolve_domain( src, domain )
|
1185
1163
|
when :checking then
|
1186
|
-
# puts "
|
1164
|
+
# puts "debug add src rbuff before resolved #{ data.inspect }"
|
1187
1165
|
src_info[ :rbuff ] << data
|
1188
1166
|
when :negotiation then
|
1189
1167
|
# +----+-----+-------+------+----------+----------+
|
@@ -1191,11 +1169,11 @@ module Girl
|
|
1191
1169
|
# +----+-----+-------+------+----------+----------+
|
1192
1170
|
# | 1 | 1 | X'00' | 1 | Variable | 2 |
|
1193
1171
|
# +----+-----+-------+------+----------+----------+
|
1194
|
-
# puts "
|
1172
|
+
# puts "debug negotiation #{ data.inspect }"
|
1195
1173
|
ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
|
1196
1174
|
|
1197
1175
|
if cmd == 1 then
|
1198
|
-
# puts "
|
1176
|
+
# puts "debug socks5 CONNECT"
|
1199
1177
|
|
1200
1178
|
if atyp == 1 then
|
1201
1179
|
destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
|
@@ -1204,7 +1182,7 @@ module Girl
|
|
1204
1182
|
destination_ip = destination_addrinfo.ip_address
|
1205
1183
|
src_info[ :destination_domain ] = destination_ip
|
1206
1184
|
src_info[ :destination_port ] = destination_port
|
1207
|
-
# puts "
|
1185
|
+
# puts "debug IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
|
1208
1186
|
deal_with_destination_ip( src, destination_addrinfo )
|
1209
1187
|
elsif atyp == 3 then
|
1210
1188
|
domain_len = data[ 4 ].unpack( 'C' ).first
|
@@ -1214,7 +1192,7 @@ module Girl
|
|
1214
1192
|
port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
|
1215
1193
|
src_info[ :destination_domain ] = domain
|
1216
1194
|
src_info[ :destination_port ] = port
|
1217
|
-
# puts "
|
1195
|
+
# puts "debug DOMAINNAME #{ domain } #{ port }"
|
1218
1196
|
resolve_domain( src, domain )
|
1219
1197
|
end
|
1220
1198
|
end
|
@@ -1222,35 +1200,29 @@ module Girl
|
|
1222
1200
|
puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
|
1223
1201
|
end
|
1224
1202
|
when :tunnel then
|
1225
|
-
|
1203
|
+
atun = src_info[ :atun ]
|
1226
1204
|
|
1227
|
-
if
|
1228
|
-
|
1229
|
-
|
1230
|
-
data, _ = sub_http_request( data )
|
1231
|
-
end
|
1205
|
+
if atun && !src_info[ :is_connect ] then
|
1206
|
+
data, _ = sub_http_request( data )
|
1207
|
+
end
|
1232
1208
|
|
1233
|
-
|
1234
|
-
|
1235
|
-
end
|
1209
|
+
if atun then
|
1210
|
+
add_atun_wbuff( atun, pack_a_chunk( data ) )
|
1236
1211
|
else
|
1237
|
-
# puts "
|
1212
|
+
# puts "debug add src.rbuff #{ data.bytesize }"
|
1238
1213
|
add_src_rbuff( src, data )
|
1239
1214
|
end
|
1240
1215
|
when :direct then
|
1241
1216
|
dst = src_info[ :dst ]
|
1242
1217
|
|
1243
1218
|
if dst then
|
1244
|
-
unless
|
1245
|
-
|
1246
|
-
data, _ = sub_http_request( data )
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
# puts "debug2 add dst.wbuff #{ data.bytesize }"
|
1250
|
-
add_dst_wbuff( dst, data )
|
1219
|
+
unless src_info[ :is_connect ] then
|
1220
|
+
data, _ = sub_http_request( data )
|
1251
1221
|
end
|
1222
|
+
|
1223
|
+
add_dst_wbuff( dst, data )
|
1252
1224
|
else
|
1253
|
-
# puts "
|
1225
|
+
# puts "debug add src.rbuff #{ data.bytesize }"
|
1254
1226
|
add_src_rbuff( src, data )
|
1255
1227
|
end
|
1256
1228
|
end
|
@@ -1265,82 +1237,88 @@ module Girl
|
|
1265
1237
|
return
|
1266
1238
|
end
|
1267
1239
|
|
1240
|
+
dst_info = @dst_infos[ dst ]
|
1241
|
+
src = dst_info[ :src ]
|
1242
|
+
|
1268
1243
|
begin
|
1269
|
-
data = dst.read_nonblock(
|
1270
|
-
rescue IO::WaitReadable
|
1244
|
+
data = dst.read_nonblock( 65535 )
|
1245
|
+
rescue IO::WaitReadable
|
1271
1246
|
print 'r'
|
1272
1247
|
return
|
1273
1248
|
rescue Exception => e
|
1274
|
-
# puts "
|
1275
|
-
|
1276
|
-
src = dst_info[ :src ]
|
1249
|
+
# puts "debug read dst #{ e.class }"
|
1250
|
+
close_read_dst( dst )
|
1277
1251
|
set_src_closing_write( src )
|
1278
1252
|
return
|
1279
1253
|
end
|
1280
1254
|
|
1281
|
-
|
1282
|
-
src = dst_info[ :src ]
|
1255
|
+
# puts "debug read dst #{ data.bytesize }"
|
1283
1256
|
add_src_wbuff( src, data )
|
1284
1257
|
end
|
1285
1258
|
|
1286
1259
|
##
|
1287
|
-
# read
|
1260
|
+
# read btun
|
1288
1261
|
#
|
1289
|
-
def
|
1290
|
-
if
|
1291
|
-
puts "p#{ Process.pid } #{ Time.new } read
|
1262
|
+
def read_btun( btun )
|
1263
|
+
if btun.closed? then
|
1264
|
+
puts "p#{ Process.pid } #{ Time.new } read btun but btun closed?"
|
1292
1265
|
return
|
1293
1266
|
end
|
1294
1267
|
|
1268
|
+
btun_info = @btun_infos[ btun ]
|
1269
|
+
src = btun_info[ :src ]
|
1270
|
+
|
1295
1271
|
begin
|
1296
|
-
data =
|
1297
|
-
rescue IO::WaitReadable
|
1298
|
-
return
|
1299
|
-
rescue Errno::EINTR
|
1300
|
-
puts e.class
|
1301
|
-
return
|
1272
|
+
data = btun.read_nonblock( READ_SIZE )
|
1302
1273
|
rescue Exception => e
|
1303
|
-
# puts "
|
1304
|
-
|
1305
|
-
src = tun_info[ :src ]
|
1306
|
-
set_src_closing_write( src )
|
1307
|
-
return
|
1308
|
-
end
|
1274
|
+
# puts "debug read btun #{ btun_info[ :im ] } #{ e.class }"
|
1275
|
+
close_btun( btun )
|
1309
1276
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
add_src_wbuff( src, data )
|
1314
|
-
end
|
1277
|
+
if src then
|
1278
|
+
set_src_closing_write( src )
|
1279
|
+
end
|
1315
1280
|
|
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
1281
|
return
|
1323
1282
|
end
|
1324
1283
|
|
1325
|
-
|
1326
|
-
|
1284
|
+
until data.empty? do
|
1285
|
+
rbuff = btun_info[ :rbuff ]
|
1286
|
+
wait_bytes = btun_info[ :wait_bytes ]
|
1327
1287
|
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1288
|
+
if wait_bytes > 0 then
|
1289
|
+
len = wait_bytes
|
1290
|
+
# puts "debug wait bytes #{ len }"
|
1291
|
+
else
|
1292
|
+
if data.bytesize <= 2 then
|
1293
|
+
# puts "debug unexpect data length #{ data.bytesize }"
|
1294
|
+
close_btun( btun )
|
1295
|
+
return
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
len = data[ 0, 2 ].unpack( 'n' ).first
|
1299
|
+
# puts "debug read len #{ len }"
|
1300
|
+
data = data[ 2..-1 ]
|
1338
1301
|
end
|
1339
1302
|
|
1340
|
-
|
1341
|
-
|
1303
|
+
chunk = data[ 0, len ]
|
1304
|
+
chunk_size = chunk.bytesize
|
1342
1305
|
|
1343
|
-
|
1306
|
+
if chunk_size == len then
|
1307
|
+
# 取完整了
|
1308
|
+
chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
|
1309
|
+
# puts "debug decode and add src.wbuff #{ chunk.bytesize }"
|
1310
|
+
add_src_wbuff( src, chunk )
|
1311
|
+
btun_info[ :rbuff ].clear
|
1312
|
+
btun_info[ :wait_bytes ] = 0
|
1313
|
+
else
|
1314
|
+
# 暂存
|
1315
|
+
# puts "debug add btun.rbuff #{ chunk_size } wait bytes #{ len - chunk_size }"
|
1316
|
+
btun_info[ :rbuff ] << chunk
|
1317
|
+
btun_info[ :wait_bytes ] = len - chunk_size
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
data = data[ chunk_size..-1 ]
|
1321
|
+
end
|
1344
1322
|
end
|
1345
1323
|
|
1346
1324
|
##
|
@@ -1370,24 +1348,27 @@ module Girl
|
|
1370
1348
|
# 写入
|
1371
1349
|
begin
|
1372
1350
|
written = src.write_nonblock( data )
|
1373
|
-
rescue IO::WaitWritable
|
1351
|
+
rescue IO::WaitWritable
|
1374
1352
|
print 'w'
|
1375
1353
|
return
|
1376
1354
|
rescue Exception => e
|
1377
|
-
# puts "
|
1355
|
+
# puts "debug write src #{ e.class }"
|
1378
1356
|
close_write_src( src )
|
1379
1357
|
|
1380
1358
|
if dst then
|
1381
1359
|
close_read_dst( dst )
|
1382
1360
|
else
|
1383
|
-
|
1384
|
-
|
1361
|
+
btun = src_info[ :btun ]
|
1362
|
+
|
1363
|
+
if btun then
|
1364
|
+
close_btun( btun )
|
1365
|
+
end
|
1385
1366
|
end
|
1386
1367
|
|
1387
1368
|
return
|
1388
1369
|
end
|
1389
1370
|
|
1390
|
-
# puts "
|
1371
|
+
# puts "debug write src #{ written }"
|
1391
1372
|
data = data[ written..-1 ]
|
1392
1373
|
src_info[ :wbuff ] = data
|
1393
1374
|
end
|
@@ -1419,11 +1400,11 @@ module Girl
|
|
1419
1400
|
# 写入
|
1420
1401
|
begin
|
1421
1402
|
written = dst.write_nonblock( data )
|
1422
|
-
rescue IO::WaitWritable
|
1403
|
+
rescue IO::WaitWritable
|
1423
1404
|
print 'w'
|
1424
1405
|
return
|
1425
1406
|
rescue Exception => e
|
1426
|
-
# puts "
|
1407
|
+
# puts "debug write dst #{ e.class }"
|
1427
1408
|
close_write_dst( dst )
|
1428
1409
|
close_read_src( src )
|
1429
1410
|
return
|
@@ -1439,24 +1420,24 @@ module Girl
|
|
1439
1420
|
end
|
1440
1421
|
|
1441
1422
|
##
|
1442
|
-
# write
|
1423
|
+
# write atun
|
1443
1424
|
#
|
1444
|
-
def
|
1445
|
-
if
|
1446
|
-
puts "p#{ Process.pid } #{ Time.new } write
|
1425
|
+
def write_atun( atun )
|
1426
|
+
if atun.closed? then
|
1427
|
+
puts "p#{ Process.pid } #{ Time.new } write atun but atun closed?"
|
1447
1428
|
return
|
1448
1429
|
end
|
1449
1430
|
|
1450
|
-
|
1451
|
-
src =
|
1452
|
-
data =
|
1431
|
+
atun_info = @atun_infos[ atun ]
|
1432
|
+
src = atun_info[ :src ]
|
1433
|
+
data = atun_info[ :wbuff ]
|
1453
1434
|
|
1454
1435
|
# 写前为空,处理关闭写
|
1455
1436
|
if data.empty? then
|
1456
|
-
if
|
1457
|
-
|
1437
|
+
if atun_info[ :closing ] then
|
1438
|
+
close_atun( atun )
|
1458
1439
|
else
|
1459
|
-
@writes.delete(
|
1440
|
+
@writes.delete( atun )
|
1460
1441
|
end
|
1461
1442
|
|
1462
1443
|
return
|
@@ -1464,23 +1445,20 @@ module Girl
|
|
1464
1445
|
|
1465
1446
|
# 写入
|
1466
1447
|
begin
|
1467
|
-
written =
|
1468
|
-
rescue IO::
|
1469
|
-
# OpenSSL::SSL::SSLErrorWaitReadable
|
1470
|
-
return
|
1471
|
-
rescue IO::WaitWritable, Errno::EINTR
|
1448
|
+
written = atun.write_nonblock( data )
|
1449
|
+
rescue IO::WaitWritable
|
1472
1450
|
print 'w'
|
1473
1451
|
return
|
1474
1452
|
rescue Exception => e
|
1475
|
-
# puts "
|
1476
|
-
|
1453
|
+
# puts "debug write atun #{ e.class }"
|
1454
|
+
close_atun( atun )
|
1477
1455
|
close_read_src( src )
|
1478
1456
|
return
|
1479
1457
|
end
|
1480
1458
|
|
1481
|
-
# puts "
|
1459
|
+
# puts "debug write atun #{ written }"
|
1482
1460
|
data = data[ written..-1 ]
|
1483
|
-
|
1461
|
+
atun_info[ :wbuff ] = data
|
1484
1462
|
|
1485
1463
|
unless src.closed? then
|
1486
1464
|
src_info = @src_infos[ src ]
|
@@ -1489,112 +1467,30 @@ module Girl
|
|
1489
1467
|
end
|
1490
1468
|
|
1491
1469
|
##
|
1492
|
-
# write
|
1470
|
+
# write btun
|
1493
1471
|
#
|
1494
|
-
def
|
1495
|
-
if
|
1496
|
-
puts "p#{ Process.pid } #{ Time.new } write
|
1472
|
+
def write_btun( btun )
|
1473
|
+
if btun.closed? then
|
1474
|
+
puts "p#{ Process.pid } #{ Time.new } write btun but btun closed?"
|
1497
1475
|
return
|
1498
1476
|
end
|
1499
1477
|
|
1500
|
-
|
1478
|
+
btun_info = @btun_infos[ btun ]
|
1479
|
+
data = btun_info[ :wbuff ]
|
1501
1480
|
|
1481
|
+
# 写入dst id
|
1502
1482
|
begin
|
1503
|
-
|
1504
|
-
rescue IO::WaitReadable
|
1505
|
-
rescue IO::WaitWritable
|
1483
|
+
written = btun.write( data )
|
1506
1484
|
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 )
|
1485
|
+
# puts "debug write btun #{ e.class }"
|
1486
|
+
src = btun_info[ :src ]
|
1487
|
+
close_btun( btun )
|
1488
|
+
add_closing_src( src )
|
1558
1489
|
return
|
1559
1490
|
end
|
1560
1491
|
|
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 )
|
1492
|
+
# puts "debug write btun #{ written }"
|
1493
|
+
@writes.delete( btun )
|
1598
1494
|
end
|
1599
1495
|
|
1600
1496
|
end
|