girl 4.8.0 → 4.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 944b2055e93c9751113af05107dce4dc040bb40a41602388350c292af2286e0b
4
- data.tar.gz: 71c9b4cb592f41750a5f21d751afeb4d13be0b2c20da2f10eb0df42a8cfbe2fd
3
+ metadata.gz: 011aa472a00bf6cb2d5c73af7f5a9f685897bcafa782cb5080c53f830775738a
4
+ data.tar.gz: 05a8c74a0a96a65f77432c2b64fe384283ed0a15178f4e09f820ce1b2d82f706
5
5
  SHA512:
6
- metadata.gz: 8a01d46a18c169d0d4773168379b0aa1106157872554444d166156dbaf7d55966d8f941561754d5e506c91d098383bf419ad42a8cd59432dc0270e7f879dc355
7
- data.tar.gz: a9ed3e588404a191c0c7b38abdb1ec3573af2139022258dd9f2ee469ce6ad335b21ab5595002638d73946130535b6f92ac8c7bb429da7cd3c5b005e1dffdb3f8
6
+ metadata.gz: 10e71a4842eb5ab95edb29411607502e073ae0c7f7f371163d42d9ac85dcb5fcda39363c572ddef67565e6eefa17706f836bec0eb48c16f31422d34838691277
7
+ data.tar.gz: facd9596a3518f80d587e436cbbb8fe76da4f7be6657b75d40cf076b11fa4f92c8ea0cb1fde9d8c0a496c3e8667d231a29e47da0ae463cf2a2d06e53ef8f1c07
data/girl.gemspec CHANGED
@@ -31,8 +31,6 @@ lib/girl/relay.rb
31
31
  lib/girl/resolv_custom.rb
32
32
  lib/girl/resolvd_worker.rb
33
33
  lib/girl/resolvd.rb
34
- lib/girl/ssl_worker.rb
35
- lib/girl/ssl.rb
36
34
  lib/girl/version.rb
37
35
  ]
38
36
 
data/lib/girl/head.rb CHANGED
@@ -49,6 +49,7 @@ module Girl
49
49
  172.16.0.0/12
50
50
  192.168.0.0/16
51
51
  255.255.255.255/32
52
+ ::1
52
53
  EOF
53
54
  CONSTS = %w[
54
55
  READ_SIZE
@@ -644,13 +644,20 @@ module Girl
644
644
  src_info = @src_infos[ src ]
645
645
  domain = src_info[ :destination_domain ]
646
646
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
647
- dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
647
+
648
+ begin
649
+ dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
650
+ rescue Exception => e
651
+ puts "p#{ Process.pid } #{ Time.new } new a dst #{ src_info[ :destination_domain ] } #{ src_info[ :destination_port ] } #{ e.class }"
652
+ add_closing_src( src )
653
+ return
654
+ end
655
+
648
656
  dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
649
657
 
650
658
  begin
651
659
  dst.connect_nonblock( destination_addr )
652
660
  rescue IO::WaitWritable
653
- # connect nonblock 必抛 wait writable
654
661
  rescue Exception => e
655
662
  puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
656
663
  dst.close
@@ -1200,9 +1207,18 @@ module Girl
1200
1207
  src_info[ :rbuff ] << data
1201
1208
  end
1202
1209
 
1203
- domain, port = domain_port.split( ':' )
1204
- port = port ? port.to_i : 80
1210
+ colon_idx = domain_port.rindex( ':' )
1211
+ close_idx = domain_port.rindex( ']' )
1205
1212
 
1213
+ if colon_idx && ( close_idx.nil? || ( colon_idx > close_idx ) ) then
1214
+ domain = domain_port[ 0...colon_idx ]
1215
+ port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
1216
+ else
1217
+ domain = domain_port
1218
+ port = 80
1219
+ end
1220
+
1221
+ domain = domain.gsub( /\[|\]/, '' )
1206
1222
  src_info[ :proxy_proto ] = :http
1207
1223
  src_info[ :destination_domain ] = domain
1208
1224
  src_info[ :destination_port ] = port
@@ -1243,9 +1259,13 @@ module Girl
1243
1259
  # puts "debug DOMAINNAME #{ domain } #{ port }"
1244
1260
  resolve_domain( src, domain )
1245
1261
  end
1262
+ else
1263
+ puts "p#{ Process.pid } #{ Time.new } socks5 atyp #{ atyp } not implement"
1264
+ add_closing_src( src )
1246
1265
  end
1247
1266
  else
1248
1267
  puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
1268
+ add_closing_src( src )
1249
1269
  end
1250
1270
  when :tunnel then
1251
1271
  atun = src_info[ :atun ]
@@ -305,7 +305,13 @@ module Girl
305
305
  # deal with destination addr
306
306
  #
307
307
  def deal_with_destination_addr( ctl_addr, src_id, destination_addr, domain_port )
308
- dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
308
+ begin
309
+ dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
310
+ rescue Exception => e
311
+ puts "p#{ Process.pid } #{ Time.new } new a dst #{ destination_addr.inspect } #{ domain_port } #{ e.class }"
312
+ return
313
+ end
314
+
309
315
  dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
310
316
 
311
317
  begin
@@ -665,13 +665,20 @@ module Girl
665
665
  src_info = @src_infos[ src ]
666
666
  domain = src_info[ :destination_domain ]
667
667
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
668
- dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
668
+
669
+ begin
670
+ dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
671
+ rescue Exception => e
672
+ puts "p#{ Process.pid } #{ Time.new } new a dst #{ src_info[ :destination_domain ] } #{ src_info[ :destination_port ] } #{ e.class }"
673
+ add_closing_src( src )
674
+ return
675
+ end
676
+
669
677
  dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
670
678
 
671
679
  begin
672
680
  dst.connect_nonblock( destination_addr )
673
681
  rescue IO::WaitWritable
674
- # connect nonblock 必抛 wait writable
675
682
  rescue Exception => e
676
683
  puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
677
684
  dst.close
@@ -49,7 +49,7 @@ module Girl
49
49
  # quit!
50
50
  #
51
51
  def quit!
52
- # puts "debug1 exit"
52
+ # puts "debug exit"
53
53
  exit
54
54
  end
55
55
 
@@ -82,7 +82,7 @@ module Girl
82
82
  # close dst
83
83
  #
84
84
  def close_dst( dst )
85
- # puts "debug1 close dst"
85
+ # puts "debug close dst"
86
86
  dst.close
87
87
  @reads.delete( dst )
88
88
  @roles.delete( dst )
@@ -116,7 +116,7 @@ module Girl
116
116
  dst.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
117
117
  dst.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
118
118
 
119
- puts "p#{ Process.pid } #{ Time.new } new a dst"
119
+ # puts "debug new a dst"
120
120
  @dst_infos[ dst ] = {
121
121
  resolvd: resolvd,
122
122
  src_addr: src_addr,
@@ -178,7 +178,7 @@ module Girl
178
178
  #
179
179
  def read_resolvd( resolvd )
180
180
  data, addrinfo, rflags, *controls = resolvd.recvmsg
181
- # puts "debug1 resolvd recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
181
+ # puts "debug resolvd recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
182
182
  data = @custom.decode( data )
183
183
  new_a_dst( resolvd, addrinfo.to_sockaddr, data )
184
184
  end
@@ -188,7 +188,7 @@ module Girl
188
188
  #
189
189
  def read_dst( dst )
190
190
  data, addrinfo, rflags, *controls = dst.recvmsg
191
- # puts "debug1 dst recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
191
+ # puts "debug dst recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
192
192
  dst_info = @dst_infos[ dst ]
193
193
  data = @custom.encode( data )
194
194
  send_data( dst_info[ :resolvd ], dst_info[ :src_addr ], data )
data/lib/girl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '4.8.0'.freeze
2
+ VERSION = '4.9.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: girl
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-22 00:00:00.000000000 Z
11
+ date: 2021-05-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: escape evil.
14
14
  email:
@@ -33,8 +33,6 @@ files:
33
33
  - lib/girl/resolv_custom.rb
34
34
  - lib/girl/resolvd.rb
35
35
  - lib/girl/resolvd_worker.rb
36
- - lib/girl/ssl.rb
37
- - lib/girl/ssl_worker.rb
38
36
  - lib/girl/version.rb
39
37
  homepage: https://github.com/takafan/girl
40
38
  licenses:
data/lib/girl/ssl.rb DELETED
@@ -1,79 +0,0 @@
1
- require 'etc'
2
- require 'girl/concurrent_hash'
3
- require 'girl/head'
4
- require 'girl/ssl_worker'
5
- require 'girl/version'
6
- require 'json'
7
- require 'openssl'
8
- require 'socket'
9
-
10
- ##
11
- # Girl::Ssl
12
- #
13
- module Girl
14
- class Ssl
15
-
16
- def initialize( config_path = nil )
17
- unless config_path then
18
- config_path = File.expand_path( '../girl.conf.json', __FILE__ )
19
- end
20
-
21
- raise "missing config file #{ config_path }" unless File.exist?( config_path )
22
-
23
- conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
24
- redir_port = conf[ :ssl_port ]
25
- worker_count = conf[ :worker_count ]
26
-
27
- unless redir_port then
28
- redir_port = 1080
29
- end
30
-
31
- nprocessors = Etc.nprocessors
32
-
33
- if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
34
- worker_count = nprocessors
35
- end
36
-
37
- len = CONSTS.map{ | name | name.size }.max
38
-
39
- CONSTS.each do | name |
40
- puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
41
- end
42
-
43
- title = "girl ssl #{ Girl::VERSION }"
44
- puts title
45
- puts "redir port #{ redir_port } worker count #{ worker_count }"
46
-
47
- $0 = title
48
- workers = []
49
-
50
- worker_count.times do | i |
51
- workers << fork do
52
- $0 = 'girl ssl worker'
53
- worker = Girl::SslWorker.new( redir_port )
54
-
55
- Signal.trap( :TERM ) do
56
- puts "w#{ i } exit"
57
- worker.quit!
58
- end
59
-
60
- worker.looping
61
- end
62
- end
63
-
64
- Signal.trap( :TERM ) do
65
- puts 'trap TERM'
66
- workers.each do | pid |
67
- begin
68
- Process.kill( :TERM, pid )
69
- rescue Errno::ESRCH => e
70
- puts e.class
71
- end
72
- end
73
- end
74
-
75
- Process.waitall
76
- end
77
-
78
- end
79
- end
@@ -1,874 +0,0 @@
1
- module Girl
2
- class SslWorker
3
-
4
- ##
5
- # initialize
6
- #
7
- def initialize( redir_port )
8
- @redir_port = redir_port
9
- @reads = []
10
- @writes = []
11
- @closing_srcs = []
12
- @paused_srcs = []
13
- @paused_dsts = []
14
- @resume_srcs = []
15
- @resume_dsts = []
16
- @roles = ConcurrentHash.new # sock => :dotr / :redir / :src / :dst
17
- @src_infos = ConcurrentHash.new # src => {}
18
- @dst_infos = ConcurrentHash.new # dst => {}
19
- @resolv_caches = ConcurrentHash.new # domain => [ ip, created_at ]
20
-
21
- dotr, dotw = IO.pipe
22
- @dotw = dotw
23
- add_read( dotr, :dotr )
24
- new_a_redir
25
- end
26
-
27
- ##
28
- # looping
29
- #
30
- def looping
31
- puts "p#{ Process.pid } #{ Time.new } looping"
32
- loop_check_expire
33
- loop_check_resume
34
-
35
- loop do
36
- rs, ws = IO.select( @reads, @writes )
37
-
38
- rs.each do | sock |
39
- case @roles[ sock ]
40
- when :dotr then
41
- read_dotr( sock )
42
- when :redir then
43
- read_redir( sock )
44
- when :src then
45
- read_src( sock )
46
- when :dst then
47
- read_dst( sock )
48
- end
49
- end
50
-
51
- ws.each do | sock |
52
- case @roles[ sock ]
53
- when :src then
54
- write_src( sock )
55
- when :dst then
56
- write_dst( sock )
57
- end
58
- end
59
- end
60
- rescue Interrupt => e
61
- puts e.class
62
- quit!
63
- end
64
-
65
- ##
66
- # quit!
67
- #
68
- def quit!
69
- # puts "debug exit"
70
- exit
71
- end
72
-
73
- private
74
-
75
- ##
76
- # add closing src
77
- #
78
- def add_closing_src( src )
79
- return if src.closed? || @closing_srcs.include?( src )
80
- @closing_srcs << src
81
- next_tick
82
- end
83
-
84
- ##
85
- # add dst wbuff
86
- #
87
- def add_dst_wbuff( dst, data )
88
- return if dst.closed?
89
- dst_info = @dst_infos[ dst ]
90
- dst_info[ :wbuff ] << data
91
- add_write( dst )
92
-
93
- if dst_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
94
- puts "p#{ Process.pid } #{ Time.new } pause direct src #{ dst_info[ :domain ] }"
95
- add_paused_src( dst_info[ :src ] )
96
- end
97
- end
98
-
99
- ##
100
- # add paused dst
101
- #
102
- def add_paused_dst( dst )
103
- return if dst.closed? || @paused_dsts.include?( dst )
104
- @reads.delete( dst )
105
- @paused_dsts << dst
106
- end
107
-
108
- ##
109
- # add paused src
110
- #
111
- def add_paused_src( src )
112
- return if src.closed? || @paused_srcs.include?( src )
113
- @reads.delete( src )
114
- @paused_srcs << src
115
- end
116
-
117
- ##
118
- # add read
119
- #
120
- def add_read( sock, role = nil )
121
- return if sock.closed? || @reads.include?( sock )
122
- @reads << sock
123
-
124
- if role then
125
- @roles[ sock ] = role
126
- end
127
-
128
- next_tick
129
- end
130
-
131
- ##
132
- # add resume dst
133
- #
134
- def add_resume_dst( dst )
135
- return if @resume_dsts.include?( dst )
136
- @resume_dsts << dst
137
- next_tick
138
- end
139
-
140
- ##
141
- # add resume src
142
- #
143
- def add_resume_src( src )
144
- return if @resume_srcs.include?( src )
145
- @resume_srcs << src
146
- next_tick
147
- end
148
-
149
- ##
150
- # add socks5 conn reply
151
- #
152
- def add_socks5_conn_reply( src )
153
- # +----+-----+-------+------+----------+----------+
154
- # |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
155
- # +----+-----+-------+------+----------+----------+
156
- # | 1 | 1 | X'00' | 1 | Variable | 2 |
157
- # +----+-----+-------+------+----------+----------+
158
- redir_ip, redir_port = @redir_local_address.ip_unpack
159
- data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( redir_ip ).hton, [ redir_port ].pack( 'n' ) ].join
160
- # puts "debug add src.wbuff socks5 conn reply #{ data.inspect }"
161
- add_src_wbuff( src, data )
162
- end
163
-
164
- ##
165
- # add src rbuff
166
- #
167
- def add_src_rbuff( src, data )
168
- src_info = @src_infos[ src ]
169
- src_info[ :rbuff ] << data
170
-
171
- if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
172
- # puts "debug src.rbuff full"
173
- add_closing_src( src )
174
- end
175
- end
176
-
177
- ##
178
- # add src wbuff
179
- #
180
- def add_src_wbuff( src, data )
181
- return if src.closed? || @closing_srcs.include?( src )
182
- src_info = @src_infos[ src ]
183
- src_info[ :wbuff ] << data
184
- src_info[ :last_recv_at ] = Time.new
185
- add_write( src )
186
-
187
- if src_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
188
- dst = src_info[ :dst ]
189
-
190
- if dst then
191
- puts "p#{ Process.pid } #{ Time.new } pause dst #{ src_info[ :destination_domain ] }"
192
- add_paused_dst( dst )
193
- end
194
- end
195
- end
196
-
197
- ##
198
- # add write
199
- #
200
- def add_write( sock )
201
- return if sock.closed? || @writes.include?( sock )
202
- @writes << sock
203
- next_tick
204
- end
205
-
206
- ##
207
- # close read dst
208
- #
209
- def close_read_dst( dst )
210
- return if dst.closed?
211
- # puts "debug close read dst"
212
- dst.close_read
213
- @reads.delete( dst )
214
-
215
- if dst.closed? then
216
- @writes.delete( dst )
217
- @roles.delete( dst )
218
- del_dst_info( dst )
219
- end
220
- end
221
-
222
- ##
223
- # close read src
224
- #
225
- def close_read_src( src )
226
- return if src.closed?
227
- # puts "debug close read src"
228
- src_info = @src_infos[ src ]
229
- src_info[ :close_read ] = true
230
-
231
- if src_info[ :close_write ] then
232
- close_sock( src )
233
- del_src_info( src )
234
- else
235
- @reads.delete( src )
236
- end
237
- end
238
-
239
- ##
240
- # close redir
241
- #
242
- def close_redir( redir )
243
- return if redir.closed?
244
- redir.close
245
- @roles.delete( redir )
246
- @reads.delete( redir )
247
- @src_infos.keys.each { | src | close_src( src ) }
248
- end
249
-
250
- ##
251
- # close sock
252
- #
253
- def close_sock( sock )
254
- sock.close
255
- @reads.delete( sock )
256
- @writes.delete( sock )
257
- @roles.delete( sock )
258
- end
259
-
260
- ##
261
- # close src
262
- #
263
- def close_src( src )
264
- return if src.closed?
265
- # puts "debug close src"
266
- close_sock( src )
267
- src_info = del_src_info( src )
268
- dst = src_info[ :dst ]
269
-
270
- if dst then
271
- close_sock( dst )
272
- del_dst_info( dst )
273
- end
274
- end
275
-
276
- ##
277
- # close write dst
278
- #
279
- def close_write_dst( dst )
280
- return if dst.closed?
281
- # puts "debug close write dst"
282
- dst.close_write
283
- @writes.delete( dst )
284
-
285
- if dst.closed? then
286
- @reads.delete( dst )
287
- @roles.delete( dst )
288
- del_dst_info( dst )
289
- end
290
- end
291
-
292
- ##
293
- # close write src
294
- #
295
- def close_write_src( src )
296
- return if src.closed?
297
- # puts "debug close write src"
298
- src_info = @src_infos[ src ]
299
- src_info[ :close_write ] = true
300
-
301
- if src_info[ :close_read ] then
302
- close_sock( src )
303
- del_src_info( src )
304
- else
305
- @writes.delete( src )
306
- end
307
- end
308
-
309
- ##
310
- # del dst info
311
- #
312
- def del_dst_info( dst )
313
- # puts "debug delete dst info"
314
- dst_info = @dst_infos.delete( dst )
315
- @paused_dsts.delete( dst )
316
- @resume_dsts.delete( dst )
317
- dst_info
318
- end
319
-
320
- ##
321
- # del src info
322
- #
323
- def del_src_info( src )
324
- # puts "debug delete src info"
325
- src_info = @src_infos.delete( src )
326
- @paused_srcs.delete( src )
327
- @resume_srcs.delete( src )
328
- src_info
329
- end
330
-
331
- ##
332
- # loop check expire
333
- #
334
- def loop_check_expire
335
- Thread.new do
336
- loop do
337
- sleep CHECK_EXPIRE_INTERVAL
338
- now = Time.new
339
-
340
- @src_infos.each do | src, src_info |
341
- last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
342
- last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
343
-
344
- if src_info[ :dst ] then
345
- if src_info[ :dst_connected ] then
346
- expire_after = EXPIRE_AFTER
347
- is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
348
- else
349
- expire_after = EXPIRE_CONNECTING
350
- is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
351
- end
352
- else
353
- expire_after = EXPIRE_NEW
354
- is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
355
- end
356
-
357
- if is_expire then
358
- puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
359
- add_closing_src( src )
360
-
361
- unless src_info[ :rbuff ].empty? then
362
- puts "p#{ Process.pid } #{ Time.new } lost rbuff #{ src_info[ :rbuff ].inspect }"
363
- end
364
- end
365
- end
366
- end
367
- end
368
- end
369
-
370
- ##
371
- # loop check resume
372
- #
373
- def loop_check_resume
374
- Thread.new do
375
- loop do
376
- sleep CHECK_RESUME_INTERVAL
377
-
378
- @paused_srcs.each do | src |
379
- src_info = @src_infos[ src ]
380
- dst = src_info[ :dst ]
381
-
382
- if dst && !dst.closed? then
383
- dst_info = @dst_infos[ dst ]
384
-
385
- if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
386
- puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
387
- add_resume_src( src )
388
- end
389
- end
390
- end
391
-
392
- @paused_dsts.each do | dst |
393
- dst_info = @dst_infos[ dst ]
394
- src = dst_info[ :src ]
395
-
396
- if src && !src.closed? then
397
- src_info = @src_infos[ src ]
398
-
399
- if src_info[ :wbuff ].bytesize < RESUME_BELOW then
400
- puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
401
- add_resume_dst( dst )
402
- end
403
- end
404
- end
405
- end
406
- end
407
- end
408
-
409
- ##
410
- # new a dst
411
- #
412
- def new_a_dst( src, ip_info )
413
- return if src.closed?
414
- src_info = @src_infos[ src ]
415
- domain = src_info[ :destination_domain ]
416
- destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
417
- dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
418
- dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
419
-
420
- begin
421
- dst.connect_nonblock( destination_addr )
422
- rescue IO::WaitWritable
423
- # connect nonblock 必抛 wait writable
424
- rescue Exception => e
425
- puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
426
- dst.close
427
- add_closing_src( src )
428
- return
429
- end
430
-
431
- # puts "debug a new dst #{ dst.local_address.inspect }"
432
- dst_info = {
433
- src: src, # 对应src
434
- domain: domain, # 目的地
435
- wbuff: '', # 写前
436
- closing_write: false # 准备关闭写
437
- }
438
-
439
- @dst_infos[ dst ] = dst_info
440
- src_info[ :proxy_type ] = :direct
441
- src_info[ :dst ] = dst
442
- src_info[ :dst_created_at ] = Time.new
443
- add_socks5_conn_reply( src )
444
- add_read( dst, :dst )
445
- add_write( dst )
446
- end
447
-
448
- ##
449
- # new a redir
450
- #
451
- def new_a_redir
452
- pre = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
453
- pre.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
454
- pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
455
- pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
456
- pre.bind( Socket.sockaddr_in( @redir_port, '0.0.0.0' ) )
457
- @redir_local_address = pre.local_address
458
- puts "p#{ Process.pid } #{ Time.new } pre bind on #{ @redir_port } local address #{ pre.local_address.inspect }"
459
-
460
- now = Time.new
461
- name = OpenSSL::X509::Name.new
462
- key = OpenSSL::PKey::RSA.new 1024
463
- cert = OpenSSL::X509::Certificate.new
464
- cert.version = 2
465
- cert.serial = 0
466
- cert.not_before = now
467
- cert.not_after = now + 365 * 24 * 60 * 60
468
- cert.public_key = key.public_key
469
- cert.subject = name
470
- cert.issuer = name
471
- cert.sign key, OpenSSL::Digest.new('SHA1')
472
- context = OpenSSL::SSL::SSLContext.new
473
- context.security_level = 1
474
- context.add_certificate( cert, key )
475
- redir = OpenSSL::SSL::SSLServer.new pre, context
476
- redir.listen( 127 )
477
- puts "p#{ Process.pid } #{ Time.new } redir listening"
478
- add_read( redir, :redir )
479
- end
480
-
481
- ##
482
- # next tick
483
- #
484
- def next_tick
485
- @dotw.write( '.' )
486
- end
487
-
488
- ##
489
- # resolve domain
490
- #
491
- def resolve_domain( src, domain )
492
- resolv_cache = @resolv_caches[ domain ]
493
-
494
- if resolv_cache then
495
- ip_info, created_at = resolv_cache
496
-
497
- if Time.new - created_at < RESOLV_CACHE_EXPIRE then
498
- # puts "debug #{ domain } hit resolv cache #{ ip_info.inspect }"
499
- new_a_dst( src, ip_info )
500
- return
501
- end
502
-
503
- # puts "debug expire #{ domain } resolv cache"
504
- @resolv_caches.delete( domain )
505
- end
506
-
507
- src_info = @src_infos[ src ]
508
- src_info[ :proxy_type ] = :checking
509
-
510
- Thread.new do
511
- begin
512
- ip_info = Addrinfo.ip( domain )
513
- rescue Exception => e
514
- puts "p#{ Process.pid } #{ Time.new } resolv #{ domain.inspect } #{ e.class }"
515
- end
516
-
517
- if ip_info then
518
- @resolv_caches[ domain ] = [ ip_info, Time.new ]
519
- puts "p#{ Process.pid } #{ Time.new } resolved #{ domain } #{ ip_info.ip_address }"
520
- new_a_dst( src, ip_info )
521
- else
522
- add_closing_src( src )
523
- end
524
- end
525
- end
526
-
527
- ##
528
- # set dst closing write
529
- #
530
- def set_dst_closing_write( dst )
531
- return if dst.closed?
532
- dst_info = @dst_infos[ dst ]
533
- return if dst_info[ :closing_write ]
534
- dst_info[ :closing_write ] = true
535
- add_write( dst )
536
- end
537
-
538
- ##
539
- # set src closing write
540
- #
541
- def set_src_closing_write( src )
542
- return if src.closed? || @closing_srcs.include?( src )
543
- src_info = @src_infos[ src ]
544
- return if src_info[ :closing_write ]
545
- src_info[ :closing_write ] = true
546
- add_write( src )
547
- end
548
-
549
- ##
550
- # read dotr
551
- #
552
- def read_dotr( dotr )
553
- dotr.read_nonblock( READ_SIZE )
554
-
555
- if @closing_srcs.any? then
556
- @closing_srcs.each { | src | close_src( src ) }
557
- @closing_srcs.clear
558
- end
559
-
560
- if @resume_srcs.any? then
561
- @resume_srcs.each do | src |
562
- add_read( src )
563
- @paused_srcs.delete( src )
564
- end
565
-
566
- @resume_srcs.clear
567
- end
568
-
569
- if @resume_dsts.any? then
570
- @resume_dsts.each do | dst |
571
- add_read( dst )
572
- @paused_dsts.delete( dst )
573
- end
574
-
575
- @resume_dsts.clear
576
- end
577
- end
578
-
579
- ##
580
- # read redir
581
- #
582
- def read_redir( redir )
583
- accepted = false
584
-
585
- Thread.new do
586
- sleep 1
587
-
588
- unless accepted then
589
- puts "p#{ Process.pid } #{ Time.new } accept timeout"
590
- close_redir( redir )
591
- new_a_redir
592
- end
593
- end
594
-
595
- begin
596
- src = redir.accept
597
- rescue SystemExit => e
598
- puts "p#{ Process.pid } #{ Time.new } redir accept #{ e.class }"
599
- close_redir( redir )
600
- return
601
- rescue Exception => e
602
- puts "p#{ Process.pid } #{ Time.new } redir accept #{ e.class }"
603
- puts e.full_message
604
- return
605
- end
606
-
607
- accepted = true
608
- # puts "debug accept a src"
609
-
610
- @src_infos[ src ] = {
611
- proxy_proto: :uncheck, # :uncheck / :socks5
612
- proxy_type: :uncheck, # :uncheck / :checking / :direct / :negotiation
613
- destination_domain: nil, # 目的地域名
614
- destination_port: nil, # 目的地端口
615
- is_connect: true, # 代理协议是http的场合,是否是CONNECT
616
- rbuff: '', # 读到的流量
617
- dst: nil, # 对应的dst
618
- dst_created_at: nil, # 对应的dst的创建时间
619
- dst_connected: false, # 对应的dst是否已连接
620
- wbuff: '', # 从dst读到的流量
621
- created_at: Time.new, # 创建时间
622
- last_recv_at: nil, # 上一次收到新流量(由dst收到)的时间
623
- last_sent_at: nil, # 上一次发出流量(由dst发出)的时间
624
- closing_write: false, # 准备关闭写
625
- close_read: false, # 已经关闭读
626
- close_write: false # 已经关闭写
627
- }
628
-
629
- add_read( src, :src )
630
- end
631
-
632
- ##
633
- # read src
634
- #
635
- def read_src( src )
636
- if src.closed? then
637
- puts "p#{ Process.pid } #{ Time.new } read src but src closed?"
638
- return
639
- end
640
-
641
- src_info = @src_infos[ src ]
642
-
643
- begin
644
- data = src.read_nonblock( READ_SIZE )
645
- rescue IO::WaitReadable
646
- return
647
- rescue Errno::EINTR => e
648
- puts e.class
649
- return
650
- rescue Exception => e
651
- # puts "debug read src #{ e.class }"
652
- dst = src_info[ :dst ]
653
- close_read_src( src )
654
-
655
- if dst then
656
- set_dst_closing_write( dst )
657
- end
658
-
659
- return
660
- end
661
-
662
- src_info = @src_infos[ src ]
663
- proxy_type = src_info[ :proxy_type ]
664
-
665
- case proxy_type
666
- when :uncheck then
667
- if data[ 0 ].unpack( 'C' ).first != 5 then
668
- "p#{ Process.pid } #{ Time.new } unknown data #{ data.inspect }"
669
- end
670
-
671
- # puts "debug socks5 #{ data.inspect }"
672
-
673
- # https://tools.ietf.org/html/rfc1928
674
- #
675
- # +----+----------+----------+
676
- # |VER | NMETHODS | METHODS |
677
- # +----+----------+----------+
678
- # | 1 | 1 | 1 to 255 |
679
- # +----+----------+----------+
680
- nmethods = data[ 1 ].unpack( 'C' ).first
681
- methods = data[ 2, nmethods ].unpack( 'C*' )
682
-
683
- unless methods.include?( 0 ) then
684
- puts "p#{ Process.pid } #{ Time.new } miss method 0x00"
685
- add_closing_src( src )
686
- return
687
- end
688
-
689
- # +----+--------+
690
- # |VER | METHOD |
691
- # +----+--------+
692
- # | 1 | 1 |
693
- # +----+--------+
694
- data2 = [ 5, 0 ].pack( 'CC' )
695
- add_src_wbuff( src, data2 )
696
- src_info[ :proxy_proto ] = :socks5
697
- src_info[ :proxy_type ] = :negotiation
698
- when :checking then
699
- # puts "debug add src rbuff before resolved #{ data.inspect }"
700
- src_info[ :rbuff ] << data
701
- when :negotiation then
702
- # +----+-----+-------+------+----------+----------+
703
- # |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
704
- # +----+-----+-------+------+----------+----------+
705
- # | 1 | 1 | X'00' | 1 | Variable | 2 |
706
- # +----+-----+-------+------+----------+----------+
707
- # puts "debug negotiation #{ data.inspect }"
708
- ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
709
-
710
- if cmd == 1 then
711
- # puts "debug socks5 CONNECT"
712
-
713
- if atyp == 1 then
714
- destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
715
- destination_addr = Socket.sockaddr_in( destination_port, destination_host )
716
- destination_addrinfo = Addrinfo.new( destination_addr )
717
- destination_ip = destination_addrinfo.ip_address
718
- src_info[ :destination_domain ] = destination_ip
719
- src_info[ :destination_port ] = destination_port
720
- # puts "debug IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
721
- new_a_dst( src, destination_addrinfo )
722
- elsif atyp == 3 then
723
- domain_len = data[ 4 ].unpack( 'C' ).first
724
-
725
- if ( domain_len + 7 ) == data.bytesize then
726
- domain = data[ 5, domain_len ]
727
- port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
728
- src_info[ :destination_domain ] = domain
729
- src_info[ :destination_port ] = port
730
- # puts "debug DOMAINNAME #{ domain } #{ port }"
731
- resolve_domain( src, domain )
732
- end
733
- end
734
- else
735
- puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
736
- end
737
- when :direct then
738
- dst = src_info[ :dst ]
739
-
740
- if dst then
741
- add_dst_wbuff( dst, data )
742
- else
743
- # puts "debug add src.rbuff #{ data.bytesize }"
744
- add_src_rbuff( src, data )
745
- end
746
- end
747
- end
748
-
749
- ##
750
- # read dst
751
- #
752
- def read_dst( dst )
753
- if dst.closed? then
754
- puts "p#{ Process.pid } #{ Time.new } read dst but dst closed?"
755
- return
756
- end
757
-
758
- dst_info = @dst_infos[ dst ]
759
- src = dst_info[ :src ]
760
-
761
- begin
762
- data = dst.read_nonblock( READ_SIZE )
763
- rescue IO::WaitReadable, Errno::EINTR
764
- print 'r'
765
- return
766
- rescue Exception => e
767
- # puts "debug read dst #{ e.class }"
768
- close_read_dst( dst )
769
- set_src_closing_write( src )
770
- return
771
- end
772
-
773
- # puts "debug read dst #{ data.bytesize }"
774
- add_src_wbuff( src, data )
775
- end
776
-
777
- ##
778
- # write src
779
- #
780
- def write_src( src )
781
- if src.closed? then
782
- puts "p#{ Process.pid } #{ Time.new } write src but src closed?"
783
- return
784
- end
785
-
786
- src_info = @src_infos[ src ]
787
- dst = src_info[ :dst ]
788
- data = src_info[ :wbuff ]
789
-
790
- # 写前为空,处理关闭写
791
- if data.empty? then
792
- if src_info[ :closing_write ] then
793
- close_write_src( src )
794
- else
795
- @writes.delete( src )
796
- end
797
-
798
- return
799
- end
800
-
801
- # 写入
802
- begin
803
- written = src.write_nonblock( data )
804
- rescue IO::WaitWritable, Errno::EINTR
805
- print 'w'
806
- return
807
- rescue Exception => e
808
- # puts "debug write src #{ e.class }"
809
- close_write_src( src )
810
-
811
- if dst then
812
- close_read_dst( dst )
813
- end
814
-
815
- return
816
- end
817
-
818
- data = data[ written..-1 ]
819
- src_info[ :wbuff ] = data
820
- end
821
-
822
- ##
823
- # write dst
824
- #
825
- def write_dst( dst )
826
- if dst.closed? then
827
- puts "p#{ Process.pid } #{ Time.new } write dst but dst closed?"
828
- return
829
- end
830
-
831
- dst_info = @dst_infos[ dst ]
832
- src = dst_info[ :src ]
833
- src_info = @src_infos[ src ]
834
-
835
- unless src.closed? then
836
- src_info[ :dst_connected ] = true
837
- end
838
-
839
- data = dst_info[ :wbuff ]
840
-
841
- # 写前为空,处理关闭写
842
- if data.empty? then
843
- if dst_info[ :closing_write ] then
844
- close_write_dst( dst )
845
- else
846
- @writes.delete( dst )
847
- end
848
-
849
- return
850
- end
851
-
852
- # 写入
853
- begin
854
- written = dst.write_nonblock( data )
855
- rescue IO::WaitWritable, Errno::EINTR
856
- print 'w'
857
- return
858
- rescue Exception => e
859
- # puts "debug write dst #{ e.class }"
860
- close_write_dst( dst )
861
- close_read_src( src )
862
- return
863
- end
864
-
865
- data = data[ written..-1 ]
866
- dst_info[ :wbuff ] = data
867
-
868
- unless src.closed? then
869
- src_info[ :last_sent_at ] = Time.new
870
- end
871
- end
872
-
873
- end
874
- end