girl 0.99.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9256dd41425122dd6c8f579d7821c70213b042090c2ce3320b20931c6aa9f8e
4
- data.tar.gz: 7af6d01468ee207a768d52ecaf96b3baadb89bb81130f37850776b4ed6bf0393
3
+ metadata.gz: 0c0254d6f9509721f13f14148087071820ae5ad13a3a7a87884d5372e7d93035
4
+ data.tar.gz: 2e718e248d7b3967e350a0dd4b6266c2a396a7eb5193a2fcd419222606b9ac19
5
5
  SHA512:
6
- metadata.gz: ff1e09096efc25f66473d85e34652b76841ffa533a538c75f63562c3593afd48089d40398f74abebd40338f4af12bfc2277669ec9550f0b599b30437b681ed51
7
- data.tar.gz: 95c954a9651bc636c20298a94a39a1ec334867283bd24d0b53423528d0047a82e0a89ea6764015d6d0cfc1598210aba586ef9fdf7e75ceea4a50e3797f85f356
6
+ metadata.gz: f9546abfd9b420cf80fa128670ba0db60e95bf54ed88466e1309820bb247ced3e7aa552d6afb93db12388a35b3d432d6994dfe2ea9a5f80580c82dce8655ff66
7
+ data.tar.gz: 7e3b2c573cd03bb284cc5d51a44b0c4aa882f7c069759f63075216759cf5abdab44f80babe5f3dbe81c126a05d9e1449c9e65bab0d34e3a9f184a417e922d326
@@ -25,8 +25,6 @@ lib/girl/proxy.rb
25
25
  lib/girl/proxyd_custom.rb
26
26
  lib/girl/proxyd_worker.rb
27
27
  lib/girl/proxyd.rb
28
- lib/girl/udp.rb
29
- lib/girl/udpd.rb
30
28
  lib/girl/version.rb
31
29
  ]
32
30
 
@@ -121,12 +121,17 @@ module Girl
121
121
  end
122
122
 
123
123
  ##
124
- # add paused src
124
+ # add dst wbuff
125
125
  #
126
- def add_paused_src( src )
127
- return if src.closed? || @paused_srcs.include?( src )
128
- @reads.delete( src )
129
- @paused_srcs << src
126
+ def add_dst_wbuff( dst, data )
127
+ dst_info = @dst_infos[ dst ]
128
+ dst_info[ :wbuff ] << data
129
+ add_write( dst )
130
+
131
+ if dst_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
132
+ puts "p#{ Process.pid } #{ Time.new } pause direct src #{ dst_info[ :domain ] }"
133
+ add_paused_src( dst_info[ :src ] )
134
+ end
130
135
  end
131
136
 
132
137
  ##
@@ -138,6 +143,15 @@ module Girl
138
143
  @paused_dsts << dst
139
144
  end
140
145
 
146
+ ##
147
+ # add paused src
148
+ #
149
+ def add_paused_src( src )
150
+ return if src.closed? || @paused_srcs.include?( src )
151
+ @reads.delete( src )
152
+ @paused_srcs << src
153
+ end
154
+
141
155
  ##
142
156
  # add paused stream
143
157
  #
@@ -161,20 +175,20 @@ module Girl
161
175
  end
162
176
 
163
177
  ##
164
- # add resume src
178
+ # add resume dst
165
179
  #
166
- def add_resume_src( src )
167
- return if @resume_srcs.include?( src )
168
- @resume_srcs << src
180
+ def add_resume_dst( dst )
181
+ return if @resume_dsts.include?( dst )
182
+ @resume_dsts << dst
169
183
  next_tick
170
184
  end
171
185
 
172
186
  ##
173
- # add resume dst
187
+ # add resume src
174
188
  #
175
- def add_resume_dst( dst )
176
- return if @resume_dsts.include?( dst )
177
- @resume_dsts << dst
189
+ def add_resume_src( src )
190
+ return if @resume_srcs.include?( src )
191
+ @resume_srcs << src
178
192
  next_tick
179
193
  end
180
194
 
@@ -187,20 +201,6 @@ module Girl
187
201
  next_tick
188
202
  end
189
203
 
190
- ##
191
- # add dst wbuff
192
- #
193
- def add_dst_wbuff( dst, data )
194
- dst_info = @dst_infos[ dst ]
195
- dst_info[ :wbuff ] << data
196
- add_write( dst )
197
-
198
- if dst_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
199
- puts "p#{ Process.pid } #{ Time.new } pause direct src #{ dst_info[ :domain ] }"
200
- add_paused_src( dst_info[ :src ] )
201
- end
202
- end
203
-
204
204
  ##
205
205
  # add src rbuff
206
206
  #
@@ -241,20 +241,6 @@ module Girl
241
241
  end
242
242
  end
243
243
 
244
- ##
245
- # add stream wbuff
246
- #
247
- def add_stream_wbuff( stream, data )
248
- stream_info = @stream_infos[ stream ]
249
- stream_info[ :wbuff ] << data
250
- add_write( stream )
251
-
252
- if stream_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
253
- puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ stream_info[ :domain ] }"
254
- add_paused_src( stream_info[ :src ] )
255
- end
256
- end
257
-
258
244
  ##
259
245
  # add src wbuff socks5 conn reply
260
246
  #
@@ -270,6 +256,20 @@ module Girl
270
256
  add_src_wbuff( src, data )
271
257
  end
272
258
 
259
+ ##
260
+ # add stream wbuff
261
+ #
262
+ def add_stream_wbuff( stream, data )
263
+ stream_info = @stream_infos[ stream ]
264
+ stream_info[ :wbuff ] << data
265
+ add_write( stream )
266
+
267
+ if stream_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
268
+ puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ stream_info[ :domain ] }"
269
+ add_paused_src( stream_info[ :src ] )
270
+ end
271
+ end
272
+
273
273
  ##
274
274
  # add write
275
275
  #
@@ -280,13 +280,23 @@ module Girl
280
280
  end
281
281
 
282
282
  ##
283
- # close sock
283
+ # close read dst
284
284
  #
285
- def close_sock( sock )
286
- sock.close
287
- @reads.delete( sock )
288
- @writes.delete( sock )
289
- @roles.delete( sock )
285
+ def close_read_dst( dst )
286
+ return if dst.closed?
287
+ # puts "debug1 close read dst"
288
+ dst.close_read
289
+ @reads.delete( dst )
290
+
291
+ if dst.closed? then
292
+ # puts "debug1 delete dst info"
293
+ @roles.delete( dst )
294
+ dst_info = @dst_infos.delete( dst )
295
+ else
296
+ dst_info = @dst_infos[ dst ]
297
+ end
298
+
299
+ dst_info
290
300
  end
291
301
 
292
302
  ##
@@ -309,26 +319,6 @@ module Girl
309
319
  src_info
310
320
  end
311
321
 
312
- ##
313
- # close read dst
314
- #
315
- def close_read_dst( dst )
316
- return if dst.closed?
317
- # puts "debug1 close read dst"
318
- dst.close_read
319
- @reads.delete( dst )
320
-
321
- if dst.closed? then
322
- # puts "debug1 delete dst info"
323
- @roles.delete( dst )
324
- dst_info = @dst_infos.delete( dst )
325
- else
326
- dst_info = @dst_infos[ dst ]
327
- end
328
-
329
- dst_info
330
- end
331
-
332
322
  ##
333
323
  # close read stream
334
324
  #
@@ -349,6 +339,16 @@ module Girl
349
339
  stream_info
350
340
  end
351
341
 
342
+ ##
343
+ # close sock
344
+ #
345
+ def close_sock( sock )
346
+ sock.close
347
+ @reads.delete( sock )
348
+ @writes.delete( sock )
349
+ @roles.delete( sock )
350
+ end
351
+
352
352
  ##
353
353
  # close src
354
354
  #
@@ -360,14 +360,14 @@ module Girl
360
360
  dst = src_info[ :dst ]
361
361
 
362
362
  if dst then
363
- close_read_dst( dst )
364
- set_dst_closing_write( dst )
363
+ close_sock( dst )
364
+ @dst_infos.delete( dst )
365
365
  else
366
366
  stream = src_info[ :stream ]
367
367
 
368
368
  if stream then
369
- close_read_stream( stream )
370
- set_stream_closing_write( stream )
369
+ close_sock( stream )
370
+ @stream_infos.delete( stream )
371
371
  end
372
372
  end
373
373
  end
@@ -382,26 +382,6 @@ module Girl
382
382
  @tun_info[ :srcs ].each{ | _, src | close_src( src ) }
383
383
  end
384
384
 
385
- ##
386
- # close write src
387
- #
388
- def close_write_src( src )
389
- return if src.closed?
390
- # puts "debug1 close write src"
391
- src.close_write
392
- @writes.delete( src )
393
-
394
- if src.closed? then
395
- # puts "debug1 delete src info"
396
- @roles.delete( src )
397
- src_info = del_src_info( src )
398
- else
399
- src_info = @src_infos[ src ]
400
- end
401
-
402
- src_info
403
- end
404
-
405
385
  ##
406
386
  # close write dst
407
387
  #
@@ -422,6 +402,26 @@ module Girl
422
402
  dst_info
423
403
  end
424
404
 
405
+ ##
406
+ # close write src
407
+ #
408
+ def close_write_src( src )
409
+ return if src.closed?
410
+ # puts "debug1 close write src"
411
+ src.close_write
412
+ @writes.delete( src )
413
+
414
+ if src.closed? then
415
+ # puts "debug1 delete src info"
416
+ @roles.delete( src )
417
+ src_info = del_src_info( src )
418
+ else
419
+ src_info = @src_infos[ src ]
420
+ end
421
+
422
+ src_info
423
+ end
424
+
425
425
  ##
426
426
  # close write stream
427
427
  #
@@ -628,6 +628,7 @@ module Girl
628
628
  # connect nonblock 必抛 wait writable
629
629
  rescue Exception => e
630
630
  puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }, close src"
631
+ dst.close
631
632
  add_closing_src( src )
632
633
  return
633
634
  end
@@ -659,6 +660,25 @@ module Girl
659
660
  end
660
661
  end
661
662
 
663
+ ##
664
+ # new a proxy
665
+ #
666
+ def new_a_proxy( proxy_port )
667
+ proxy = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
668
+ proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
669
+
670
+ if RUBY_PLATFORM.include?( 'linux' ) then
671
+ proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
672
+ proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
673
+ end
674
+
675
+ proxy.bind( Socket.sockaddr_in( proxy_port, '0.0.0.0' ) )
676
+ proxy.listen( 127 )
677
+ puts "p#{ Process.pid } #{ Time.new } proxy listen on #{ proxy_port }"
678
+ add_read( proxy, :proxy )
679
+ @proxy_local_address = proxy.local_address
680
+ end
681
+
662
682
  ##
663
683
  # new a stream
664
684
  #
@@ -683,6 +703,7 @@ module Girl
683
703
  rescue IO::WaitWritable
684
704
  rescue Exception => e
685
705
  puts "p#{ Process.pid } #{ Time.new } connect tcpd #{ e.class }"
706
+ stream.close
686
707
  return
687
708
  end
688
709
 
@@ -717,25 +738,6 @@ module Girl
717
738
  end
718
739
  end
719
740
 
720
- ##
721
- # new a proxy
722
- #
723
- def new_a_proxy( proxy_port )
724
- proxy = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
725
- proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
726
-
727
- if RUBY_PLATFORM.include?( 'linux' ) then
728
- proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
729
- proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
730
- end
731
-
732
- proxy.bind( Socket.sockaddr_in( proxy_port, '0.0.0.0' ) )
733
- proxy.listen( 127 )
734
- puts "p#{ Process.pid } #{ Time.new } proxy listen on #{ proxy_port }"
735
- add_read( proxy, :proxy )
736
- @proxy_local_address = proxy.local_address
737
- end
738
-
739
741
  ##
740
742
  # new a tun
741
743
  #
@@ -793,7 +795,7 @@ module Girl
793
795
  #
794
796
  def resolve_domain( src, domain )
795
797
  if @remotes.any? { | remote | ( domain.size >= remote.size ) && ( domain[ ( remote.size * -1 )..-1 ] == remote ) } then
796
- # puts "debug1 #{ domain } hit remotes"
798
+ puts "p#{ Process.pid } #{ Time.new } #{ domain } hit remotes"
797
799
  set_src_proxy_type_tunnel( src )
798
800
  return
799
801
  end
@@ -1012,7 +1014,7 @@ module Girl
1012
1014
  #
1013
1015
  def read_tun( tun )
1014
1016
  return if tun.closed?
1015
-
1017
+
1016
1018
  begin
1017
1019
  data, addrinfo, rflags, *controls = tun.recvmsg_nonblock
1018
1020
  rescue IO::WaitReadable, Errno::EINTR
@@ -262,8 +262,8 @@ module Girl
262
262
  streamd = dst_info[ :streamd ]
263
263
 
264
264
  if streamd then
265
- close_read_streamd( streamd )
266
- set_streamd_closing_write( streamd )
265
+ close_sock( streamd )
266
+ @streamd_infos.delete( streamd )
267
267
  end
268
268
  end
269
269
 
@@ -328,8 +328,8 @@ module Girl
328
328
  dst = streamd_info[ :dst ]
329
329
 
330
330
  if dst then
331
- close_read_dst( dst )
332
- set_dst_closing_write( dst )
331
+ close_sock( dst )
332
+ del_dst_info( dst )
333
333
  end
334
334
  end
335
335
 
@@ -399,6 +399,7 @@ module Girl
399
399
  rescue IO::WaitWritable
400
400
  rescue Exception => e
401
401
  puts "p#{ Process.pid } #{ Time.new } connect destination #{ domain_port } #{ e.class }"
402
+ dst.close
402
403
  return false
403
404
  end
404
405
 
@@ -443,7 +444,7 @@ module Girl
443
444
  tund_info[ :dsts ].delete( dst_info[ :id ] )
444
445
  tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
445
446
  end
446
-
447
+
447
448
  dst_info
448
449
  end
449
450
 
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '0.99.0'.freeze
2
+ VERSION = '1.0.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: 0.99.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-20 00:00:00.000000000 Z
11
+ date: 2020-11-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: escape evil.
14
14
  email:
@@ -27,8 +27,6 @@ files:
27
27
  - lib/girl/proxyd.rb
28
28
  - lib/girl/proxyd_custom.rb
29
29
  - lib/girl/proxyd_worker.rb
30
- - lib/girl/udp.rb
31
- - lib/girl/udpd.rb
32
30
  - lib/girl/version.rb
33
31
  homepage: https://github.com/takafan/girl
34
32
  licenses:
@@ -1,326 +0,0 @@
1
- require 'girl/version'
2
- require 'socket'
3
-
4
- ##
5
- # Girl::Udp - udp透明转发,近端。
6
- #
7
- # usage
8
- # ======
9
- #
10
- # Girl::Udpd.new( 3030 ).looping # 远端
11
- #
12
- # Girl::Udp.new( 'your.server.ip', 3030, 1313 ).looping # 近端
13
- #
14
- # iptables -t nat -A PREROUTING -p udp -d game.server.ip -j REDIRECT --to-ports 1313
15
- #
16
- module Girl
17
- class Udp
18
-
19
- def initialize( udpd_host, udpd_port = 3030, redir_port = 1313 )
20
- @udpd_host = udpd_host
21
- @udpd_addr = Socket.sockaddr_in( udpd_port, udpd_host )
22
- @mutex = Mutex.new
23
- @reads = []
24
- @writes = []
25
- @roles = {} # :dotr / :redir / :tun
26
- @redir_wbuffs = [] # [ src_addr data ] ...
27
- @tuns = {} # [ orig_src_addr dst_addr ]=> tun
28
- @mappings = {} # src_addr => [ orig_src_addr dst_addr ]
29
- @tun_infos = {} # tun => {}
30
- # orig_src_addr: sockaddr
31
- # dst_addr: sockaddr
32
- # src_addr: sockaddr
33
- # tund_addr: sockaddr
34
- # rbuffs: []
35
- # wbuffs: []
36
- # last_traff_at: now
37
- dotr, dotw = IO.pipe
38
- @dotw = dotw
39
- add_read( dotr, :dotr )
40
- new_a_redir( redir_port )
41
- end
42
-
43
- def looping
44
- loop_expire
45
-
46
- loop do
47
- rs, ws = IO.select( @reads, @writes )
48
-
49
- @mutex.synchronize do
50
- rs.each do | sock |
51
- case @roles[ sock ]
52
- when :dotr then
53
- read_dotr( sock )
54
- when :redir then
55
- read_redir( sock )
56
- when :tun then
57
- read_tun( sock )
58
- end
59
- end
60
-
61
- ws.each do | sock |
62
- case @roles[ sock ]
63
- when :redir then
64
- write_redir( sock )
65
- when :tun then
66
- write_tun( sock )
67
- end
68
- end
69
- end
70
- end
71
- end
72
-
73
- def quit!
74
- exit
75
- end
76
-
77
- private
78
-
79
- def loop_expire
80
- Thread.new do
81
- loop do
82
- sleep 30
83
-
84
- @mutex.synchronize do
85
- trigger = false
86
- now = Time.new
87
-
88
- @tun_infos.each do | tun, tun_info |
89
- # net.netfilter.nf_conntrack_udp_timeout_stream
90
- if now - tun_info[ :last_traff_at ] > 180 then
91
- set_is_closing( tun )
92
- trigger = true
93
- end
94
- end
95
-
96
- next_tick if trigger
97
- end
98
- end
99
- end
100
- end
101
-
102
- def new_a_redir( redir_port )
103
- redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
104
- redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
105
- redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
106
- puts "redir bound on #{ redir_port } #{ Time.new }"
107
- @redir = redir
108
- add_read( redir, :redir )
109
- end
110
-
111
- def new_a_tun( orig_src_addr, dst_addr, src_addr )
112
- tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
113
- tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
114
- tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
115
-
116
- @tun_infos[ tun ] = {
117
- orig_src_addr: orig_src_addr,
118
- dst_addr: dst_addr,
119
- src_addr: src_addr,
120
- tund_addr: nil,
121
- rbuffs: [],
122
- wbuffs: [],
123
- last_traff_at: Time.new,
124
- is_closing: false
125
- }
126
-
127
- @tuns[ [ orig_src_addr, dst_addr ].join ] = tun
128
- add_read( tun, :tun )
129
-
130
- tun
131
- end
132
-
133
- def add_redir_wbuff( redir, to_addr, data )
134
- @redir_wbuffs << [ to_addr, data ]
135
- add_write( redir )
136
- end
137
-
138
- def add_tun_wbuff( tun, to_addr, data )
139
- tun_info = @tun_infos[ tun ]
140
-
141
- if to_addr then
142
- tun_info[ :wbuffs ] << [ to_addr, data ]
143
- add_write( tun )
144
- else
145
- tun_info[ :rbuffs ] << data
146
- end
147
- end
148
-
149
- def add_read( sock, role )
150
- unless @reads.include?( sock ) then
151
- @reads << sock
152
- end
153
-
154
- @roles[ sock ] = role
155
- end
156
-
157
- def add_write( sock )
158
- unless @writes.include?( sock ) then
159
- @writes << sock
160
- end
161
- end
162
-
163
- def set_is_closing( tun )
164
- if tun && !tun.closed? then
165
- # puts "debug1 set tun is closing"
166
-
167
- tun_info = @tun_infos[ tun ]
168
- tun_info[ :is_closing ] = true
169
-
170
- @reads.delete( tun )
171
- add_write( tun )
172
- end
173
- end
174
-
175
- def send_data( sock, data, to_addr )
176
- begin
177
- sock.sendmsg( data, 0, to_addr )
178
- rescue IO::WaitWritable, Errno::EINTR
179
- return false
180
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
181
- if @roles[ sock ] == :tun then
182
- puts "#{ Time.new } #{ e.class }, close tun"
183
- close_tun( sock )
184
- return false
185
- end
186
- end
187
-
188
- true
189
- end
190
-
191
- def close_tun( tun )
192
- tun.close
193
- @reads.delete( tun )
194
- @writes.delete( tun )
195
- @roles.delete( tun )
196
- tun_info = @tun_infos.delete( tun )
197
- @tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
198
-
199
- if @mappings.include?( tun_info[ :src_addr ] ) then
200
- orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
201
-
202
- if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ] then
203
- @mappings.delete( tun_info[ :src_addr ] )
204
- end
205
- end
206
- end
207
-
208
- def write_redir( redir )
209
- while @redir_wbuffs.any? do
210
- to_addr, data = @redir_wbuffs.first
211
- return unless send_data( redir, data, to_addr )
212
- @redir_wbuffs.shift
213
- end
214
-
215
- @writes.delete( redir )
216
- end
217
-
218
- def write_tun( tun )
219
- tun_info = @tun_infos[ tun ]
220
-
221
- if tun_info[ :is_closing ] then
222
- close_tun( tun )
223
- return
224
- end
225
-
226
- while tun_info[ :wbuffs ].any? do
227
- to_addr, data = tun_info[ :wbuffs ].first
228
- return unless send_data( tun, data, to_addr )
229
- tun_info[ :wbuffs ].shift
230
- end
231
-
232
- @writes.delete( tun )
233
- end
234
-
235
- def read_dotr( dotr )
236
- dotr.read( 1 )
237
- end
238
-
239
- def read_redir( redir )
240
- data, addrinfo, rflags, *controls = redir.recvmsg
241
- src_addr = addrinfo.to_sockaddr
242
- is_hit_cache = false
243
- now = Time.new
244
- # puts "debug redir recv #{ data.inspect } from #{ addrinfo.inspect }"
245
-
246
- if @mappings.include?( src_addr ) then
247
- orig_src_addr, dst_addr, timeout, read_at = @mappings[ src_addr ]
248
-
249
- if now - read_at < timeout then
250
- # puts "debug hit cache #{ addrinfo.inspect }"
251
- is_hit_cache = true
252
- else
253
- # puts "debug cache timeout #{ addrinfo.inspect }"
254
- @mappings.delete( src_addr )
255
- end
256
- end
257
-
258
- unless is_hit_cache then
259
- # 2 udp 4 timeout 5 src 7 sport 9 [UNREPLIED] 11 dst 13 dport
260
- # 2 udp 4 timeout 5 src 7 sport 10 dst 12 dport
261
- bin = IO.binread( '/proc/net/nf_conntrack' )
262
- rows = bin.split( "\n" ).map { | line | line.split( ' ' ) }
263
- row = rows.find { | _row | _row[ 2 ] == 'udp' && ( ( _row[ 10 ].split( '=' )[ 1 ] == addrinfo.ip_address && _row[ 12 ].split( '=' )[ 1 ].to_i == addrinfo.ip_port ) || ( _row[ 9 ] == '[UNREPLIED]' && _row[ 11 ].split( '=' )[ 1 ] == addrinfo.ip_address && _row[ 13 ].split( '=' )[ 1 ].to_i == addrinfo.ip_port ) ) }
264
-
265
- unless row then
266
- puts "miss conntrack #{ addrinfo.inspect } #{ Time.new }"
267
- IO.binwrite( '/tmp/nf_conntrack', bin )
268
- return
269
- end
270
-
271
- timeout = row[ 4 ].to_i
272
- orig_src_ip = row[ 5 ].split( '=' )[ 1 ]
273
- orig_src_port = row[ 7 ].split( '=' )[ 1 ].to_i
274
- dst_ip = row[ 6 ].split( '=' )[ 1 ]
275
- dst_port = row[ 8 ].split( '=' )[ 1 ].to_i
276
- orig_src_addr = Socket.sockaddr_in( orig_src_port, orig_src_ip )
277
- dst_addr = Socket.sockaddr_in( dst_port, dst_ip )
278
-
279
- if Addrinfo.new( dst_addr ).ipv4_private? then
280
- puts "dst is private? #{ Addrinfo.new( dst_addr ).inspect } #{ Addrinfo.new( src_addr ).inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Time.new }"
281
- add_redir_wbuff( redir, dst_addr, data )
282
- return
283
- end
284
-
285
- # puts "debug save cache #{ addrinfo.inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect } #{ timeout } #{ now }"
286
- @mappings[ src_addr ] = [ orig_src_addr, dst_addr, timeout, now ]
287
- end
288
-
289
- tun = @tuns[ [ orig_src_addr, dst_addr ].join ]
290
-
291
- unless tun then
292
- tun = new_a_tun( orig_src_addr, dst_addr, src_addr )
293
-
294
- # puts "debug tun send to udpd #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect }"
295
- ctlmsg = [ orig_src_addr, dst_addr ].join
296
- add_tun_wbuff( tun, @udpd_addr, ctlmsg )
297
- end
298
-
299
- tun_info = @tun_infos[ tun ]
300
- add_tun_wbuff( tun, tun_info[ :tund_addr ], data )
301
- end
302
-
303
- def read_tun( tun )
304
- data, addrinfo, rflags, *controls = tun.recvmsg
305
- from_addr = addrinfo.to_sockaddr
306
- tun_info = @tun_infos[ tun ]
307
- tun_info[ :last_traff_at ] = Time.new
308
-
309
- if from_addr == @udpd_addr then
310
- tund_port = data[ 0, 2 ].unpack( 'n' ).first
311
- tund_addr = Socket.sockaddr_in( tund_port, @udpd_host )
312
- tun_info[ :tund_addr ] = tund_addr
313
-
314
- if tun_info[ :rbuffs ].any? then
315
- tun_info[ :wbuffs ] += tun_info[ :rbuffs ].map{ | rbuff | [ tund_addr, rbuff ] }
316
- tun_info[ :rbuffs ].clear
317
- add_write( tun )
318
- end
319
-
320
- elsif from_addr == tun_info[ :tund_addr ] then
321
- add_redir_wbuff( @redir, tun_info[ :src_addr ], data )
322
- end
323
- end
324
-
325
- end
326
- end
@@ -1,316 +0,0 @@
1
- require 'girl/version'
2
- require 'socket'
3
-
4
- ##
5
- # Girl::Udpd - udp透明转发,远端。
6
- #
7
- module Girl
8
- class Udpd
9
-
10
- def initialize( port = 3030 )
11
- @mutex = Mutex.new
12
- @reads = []
13
- @writes = []
14
- @roles = {} # :dotr / :udpd / :tund
15
- @udpd_wbuffs = [] # [ tun_addr ctlmsg ] ...
16
- @tunds = {} # [ tun_ip_addr orig_src_addr ] => tund
17
- @tund_infos = {} # tund => {}
18
- # port: port
19
- # tun_ip_addr: sockaddr
20
- # orig_src_addr: sockaddr
21
- # wbuffs: [] # [ to_addr, data ] ...
22
- # dst_addrs: { tun_addr => dst_addr }
23
- # tun_addrs: { dst_addr => tun_addr }
24
- # is_tunneleds: { [ tun_addr dst_addr ] => false }
25
- # unpaired_dst_rbuffs: { dst_addr => [] }
26
- # last_traff_at: now
27
- dotr, dotw = IO.pipe
28
- @dotw = dotw
29
- add_read( dotr, :dotr )
30
- new_a_udpd( port )
31
- end
32
-
33
- def looping
34
- loop_expire
35
-
36
- loop do
37
- rs, ws = IO.select( @reads, @writes )
38
-
39
- @mutex.synchronize do
40
- ws.each do | sock |
41
- case @roles[ sock ]
42
- when :udpd then
43
- write_udpd( sock )
44
- when :tund then
45
- write_tund( sock )
46
- end
47
- end
48
-
49
- rs.each do | sock |
50
- case @roles[ sock ]
51
- when :dotr then
52
- read_dotr( sock )
53
- when :udpd then
54
- read_udpd( sock )
55
- when :tund then
56
- read_tund( sock )
57
- end
58
- end
59
- end
60
- end
61
- end
62
-
63
- def quit!
64
- exit
65
- end
66
-
67
- private
68
-
69
- def loop_expire
70
- Thread.new do
71
- loop do
72
- sleep 30
73
-
74
- @mutex.synchronize do
75
- trigger = false
76
- now = Time.new
77
-
78
- @tund_infos.each do | tund, tund_info |
79
- # net.netfilter.nf_conntrack_udp_timeout_stream
80
- if now - tund_info[ :last_traff_at ] > 180 then
81
- set_is_closing( tund )
82
- trigger = true
83
- end
84
- end
85
-
86
- next_tick if trigger
87
- end
88
- end
89
- end
90
- end
91
-
92
- def new_a_udpd( port )
93
- udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
94
- udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
95
- udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
96
- puts "udpd bound on #{ port } #{ Time.new }"
97
- @udpd = udpd
98
- add_read( udpd, :udpd )
99
- end
100
-
101
- def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
102
- from_addr = [ tun_ip_addr, orig_src_addr ].join
103
- td_addr = [ tun_addr, dst_addr ].join
104
- tund = @tunds[ from_addr ]
105
-
106
- if tund then
107
- tund_info = @tund_infos[ tund ]
108
- tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
109
- tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
110
- tund_info[ :is_tunneleds ][ td_addr ] = false
111
- else
112
- tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
113
- tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
114
- tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
115
- tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
116
- tund_port = tund.local_address.ip_unpack.last
117
-
118
- @tund_infos[ tund ] = {
119
- port: tund_port,
120
- tun_ip_addr: tun_ip_addr,
121
- orig_src_addr: orig_src_addr,
122
- wbuffs: [],
123
- dst_addrs: { tun_addr => dst_addr },
124
- tun_addrs: { dst_addr => tun_addr },
125
- is_tunneleds: { td_addr => false },
126
- unpaired_dst_rbuffs: {},
127
- last_traff_at: Time.new,
128
- is_closing: false
129
- }
130
-
131
- @tunds[ from_addr ] = tund
132
- add_read( tund, :tund )
133
- end
134
-
135
- tund
136
- end
137
-
138
- def add_tund_wbuff( tund, to_addr, data )
139
- tund_info = @tund_infos[ tund ]
140
- tund_info[ :wbuffs ] << [ to_addr, data ]
141
-
142
- add_write( tund )
143
- end
144
-
145
- def add_read( sock, role )
146
- unless @reads.include?( sock ) then
147
- @reads << sock
148
- end
149
-
150
- @roles[ sock ] = role
151
- end
152
-
153
- def add_write( sock )
154
- unless @writes.include?( sock ) then
155
- @writes << sock
156
- end
157
- end
158
-
159
- def set_is_closing( tund )
160
- if tund && !tund.closed? then
161
- # puts "debug1 set tund is closing"
162
-
163
- tund_info = @tund_infos[ tund ]
164
- tund_info[ :is_closing ] = true
165
-
166
- @reads.delete( tund )
167
- add_write( tund )
168
- end
169
- end
170
-
171
- def send_data( sock, data, to_addr )
172
- begin
173
- sock.sendmsg( data, 0, to_addr )
174
- rescue IO::WaitWritable, Errno::EINTR
175
- return false
176
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
177
- if @roles[ sock ] == :tund then
178
- puts "#{ Time.new } #{ e.class }, close tund"
179
- close_tund( sock )
180
- return false
181
- end
182
- end
183
-
184
- true
185
- end
186
-
187
- def close_tund( tund )
188
- tund.close
189
- @reads.delete( tund )
190
- @writes.delete( tund )
191
- @roles.delete( tund )
192
- tund_info = @tund_infos.delete( tund )
193
- @tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
194
- end
195
-
196
- def next_tick
197
- @dotw.write( '.' )
198
- end
199
-
200
- def write_udpd( udpd )
201
- while @udpd_wbuffs.any? do
202
- to_addr, data = @udpd_wbuffs.first
203
- return unless send_data( udpd, data, to_addr )
204
- @udpd_wbuffs.shift
205
- end
206
-
207
- @writes.delete( udpd )
208
- end
209
-
210
- def write_tund( tund )
211
- tund_info = @tund_infos[ tund ]
212
-
213
- if tund_info[ :is_closing ] then
214
- close_tund( tund )
215
- return
216
- end
217
-
218
- while tund_info[ :wbuffs ].any? do
219
- to_addr, data = tund_info[ :wbuffs ].first
220
- return unless send_data( tund, data, to_addr )
221
- tund_info[ :wbuffs ].shift
222
- end
223
-
224
- @writes.delete( tund )
225
- end
226
-
227
- def read_dotr( dotr )
228
- dotr.read( 1 )
229
- end
230
-
231
- def read_udpd( udpd )
232
- data, addrinfo, rflags, *controls = udpd.recvmsg
233
- # puts "debug udpd recv #{ data.inspect } from #{ addrinfo.inspect }"
234
- orig_src_addr = data[ 0, 16 ]
235
- dst_addr = data[ 16, 16 ]
236
- tun_addr = addrinfo.to_sockaddr
237
- tun_ip_addr = Addrinfo.ip( addrinfo.ip_address ).to_sockaddr
238
-
239
- return unless Addrinfo.new( orig_src_addr ).ipv4?
240
-
241
- dst_addrinfo = Addrinfo.new( dst_addr )
242
- return unless dst_addrinfo.ipv4?
243
- return if dst_addrinfo.ipv4_private?
244
-
245
- tund = pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
246
- tund_info = @tund_infos[ tund ]
247
- tund_port = tund_info[ :port ]
248
-
249
- # puts "debug udpd send to tun #{ tund_port } #{ addrinfo.inspect }"
250
- ctlmsg = [ tund_port ].pack( 'n' )
251
- @udpd_wbuffs << [ tun_addr, ctlmsg ]
252
- add_write( udpd )
253
- end
254
-
255
- def read_tund( tund )
256
- data, addrinfo, rflags, *controls = tund.recvmsg
257
- from_addr = addrinfo.to_sockaddr
258
- tund_info = @tund_infos[ tund ]
259
- tund_info[ :last_traff_at ] = Time.new
260
- to_addr = tund_info[ :dst_addrs ][ from_addr ]
261
-
262
- if to_addr then
263
- # 来自tun,发给dst。
264
- td_addr = [ from_addr, to_addr ].join
265
- is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
266
-
267
- unless is_tunneled then
268
- # puts "debug first traffic from tun #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
269
- # 发暂存
270
- if tund_info[ :unpaired_dst_rbuffs ].include?( to_addr ) then
271
- rbuffs = tund_info[ :unpaired_dst_rbuffs ].delete( to_addr )
272
- # puts "debug move tund.dst.rbuffs to tund.wbuffs #{ rbuffs.inspect }"
273
- tund_info[ :wbuffs ] += rbuffs.map{ | rbuff | [ from_addr, rbuff ] }
274
- end
275
-
276
- tund_info[ :is_tunneleds ][ td_addr ] = true
277
- end
278
-
279
- # 如果对面没来过流量,且在nat里,nat规则是只对去过的目的地做接收,那么,先过去的流量会撞死。
280
- # 没关系,撞死的流量通常是打洞数据,在应用计算之内,打洞数据通常是连发的。
281
- # puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
282
- add_tund_wbuff( tund, to_addr, data )
283
- return
284
- end
285
-
286
- to_addr = tund_info[ :tun_addrs ][ from_addr ]
287
-
288
- if to_addr then
289
- # 来自dst,发给tun。
290
- # puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
291
-
292
- td_addr = [ to_addr, from_addr ].join
293
- is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
294
-
295
- if is_tunneled then
296
- add_tund_wbuff( tund, to_addr, data )
297
- return
298
- end
299
-
300
- # puts "debug #{ Addrinfo.new( to_addr ).inspect } #{ addrinfo.inspect } not tunneled"
301
- end
302
-
303
- # 来自未知的地方,或者对应的tun还没来流量,记暂存
304
- unless tund_info[ :unpaired_dst_rbuffs ][ from_addr ] then
305
- tund_info[ :unpaired_dst_rbuffs ][ from_addr ] = []
306
- end
307
-
308
- # 暂存5条(连发打洞数据,不需要存多)。
309
- if tund_info[ :unpaired_dst_rbuffs ][ from_addr ].size < 5 then
310
- # puts "debug save other dst rbuff #{ addrinfo.inspect } #{ data.inspect }"
311
- tund_info[ :unpaired_dst_rbuffs ][ from_addr ] << data
312
- end
313
- end
314
-
315
- end
316
- end