girl 0.99.0 → 1.0.0

This diff has not been reviewed by any users.
Sign up to get free protection for your applications and to get access to all the features.
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