girl 0.78.0 → 0.83.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: cb6d635f9fb525291d4b0c32b749245255a52234ff9b850add473b430aa5e732
4
- data.tar.gz: c336934bd1fd8825f72e65fdcc9dd708788f53bec7a175a37228ec724b970869
3
+ metadata.gz: 28c02739bfb0608617fa46ef36d80d7ba9c84753eb3c34410eb98f05cab430f1
4
+ data.tar.gz: 94a70957768e52b1e40782c0df53451e1caebcac096829648009c6977219dd8b
5
5
  SHA512:
6
- metadata.gz: 81f96a6e78ddf2cf00ff331002b145871eca5b72653bf822d42943858f887be4e996fa47a98e18313800d2a461899280fa6db6eff3781daa3d714b5e54a489dd
7
- data.tar.gz: 29aaac2d5eae5d9889dcc033048929ff8fffac95c422b5322467ba8859df664097a600e14e9c26ac30e2babadc79463b05d32969565b176f990a52c708dbda80
6
+ metadata.gz: d0e12984275ddf891c11b75ce86d13830798d2538b9b4b15962720ac268f61dc721d1fd355f99282f6274217879e1053d698dbcdaf59de30533fe59c53596173
7
+ data.tar.gz: dc98d8959fd53fc51f8e0e2851ce46afe78a7ddedf293a595148b885a8ed2055a7e1fa92e88b22826528e0a6399ff5c16700c689bf4a766a6d7ca809567e0a1d
@@ -25,6 +25,7 @@ module Girl
25
25
  GOT_FIN2 = 11
26
26
  TUND_FIN = 12
27
27
  TUN_FIN = 13
28
+ IP_CHANGED = 14
28
29
  HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
29
30
  # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
30
31
  RESERVED_ROUTE = <<EOF
@@ -35,6 +35,7 @@ require 'socket'
35
35
  # 11 not use
36
36
  # 12 tund fin
37
37
  # 13 tun fin
38
+ # 14 tun ip changed
38
39
  #
39
40
  # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
40
41
  #
@@ -107,7 +108,7 @@ module Girl
107
108
  raise "not found direct file #{ direct_path }"
108
109
  end
109
110
 
110
- directs = ( [ Addrinfo.ip( proxyd_host ).ip_address ] + RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map { | line | IPAddr.new( line.strip ) }
111
+ directs = ( RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map { | line | IPAddr.new( line.strip ) }
111
112
  end
112
113
 
113
114
  remotes = []
@@ -264,8 +264,10 @@ module Girl
264
264
  # deal with destination ip
265
265
  #
266
266
  def deal_with_destination_ip( src, ip_info )
267
- if @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
268
- # ip命中直连列表,直连
267
+ src_info = @src_infos[ src ]
268
+
269
+ if ( @directs.any? { | direct | direct.include?( ip_info.ip_address ) } ) || ( ( src_info[ :destination_domain ] == @proxyd_host ) && ![ 80, 443 ].include?( src_info[ :destination_port ] ) )
270
+ # ip命中直连列表,或者访问远端非80/443端口,直连
269
271
  # puts "debug1 #{ ip_info.inspect } hit directs"
270
272
  new_a_dst( src, ip_info )
271
273
  else
@@ -741,15 +743,14 @@ module Girl
741
743
  #
742
744
  def write_src( src )
743
745
  src_info = @src_infos[ src ]
744
- data = src_info[ :cache ]
745
- from = :cache
746
+ from, data = :cache, src_info[ :cache ]
746
747
 
747
748
  if data.empty?
748
749
  if src_info[ :chunks ].any?
749
750
  path = File.join( @src_chunk_dir, src_info[ :chunks ].shift )
750
751
 
751
752
  begin
752
- src_info[ :cache ] = data = IO.binread( path )
753
+ data = src_info[ :cache ] = IO.binread( path )
753
754
  File.delete( path )
754
755
  rescue Errno::ENOENT => e
755
756
  puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
@@ -757,8 +758,7 @@ module Girl
757
758
  return
758
759
  end
759
760
  else
760
- data = src_info[ :wbuff ]
761
- from = :wbuff
761
+ from, data = :wbuff, src_info[ :wbuff ]
762
762
  end
763
763
  end
764
764
 
@@ -792,15 +792,14 @@ module Girl
792
792
  #
793
793
  def write_dst( dst )
794
794
  dst_info = @dst_infos[ dst ]
795
- data = dst_info[ :cache ]
796
- from = :cache
795
+ from, data = :cache, dst_info[ :cache ]
797
796
 
798
797
  if data.empty?
799
798
  if dst_info[ :chunks ].any?
800
799
  path = File.join( @dst_chunk_dir, dst_info[ :chunks ].shift )
801
800
 
802
801
  begin
803
- dst_info[ :cache ] = data = IO.binread( path )
802
+ data = dst_info[ :cache ] = IO.binread( path )
804
803
  File.delete( path )
805
804
  rescue Errno::ENOENT => e
806
805
  puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
@@ -808,8 +807,7 @@ module Girl
808
807
  return
809
808
  end
810
809
  else
811
- data = dst_info[ :wbuff ]
812
- from = :wbuff
810
+ from, data = :wbuff, dst_info[ :wbuff ]
813
811
  end
814
812
  end
815
813
 
@@ -879,7 +877,6 @@ module Girl
879
877
  end
880
878
 
881
879
  @tun_info[ :resendings ].shift
882
- return
883
880
  end
884
881
 
885
882
  # 若写后达到上限,暂停取写前
@@ -895,8 +892,7 @@ module Girl
895
892
 
896
893
  # 取写前
897
894
  if @tun_info[ :caches ].any?
898
- src_id, pack_id, data = @tun_info[ :caches ].first
899
- from = :caches
895
+ datas = @tun_info[ :caches ]
900
896
  elsif @tun_info[ :chunks ].any?
901
897
  path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
902
898
 
@@ -917,39 +913,39 @@ module Girl
917
913
  data = data[ ( 18 + pack_size )..-1 ]
918
914
  end
919
915
 
920
- @tun_info[ :caches ] = caches
921
- src_id, pack_id, data = caches.first
922
- from = :caches
916
+ datas = @tun_info[ :caches ] = caches
923
917
  elsif @tun_info[ :wbuffs ].any?
924
- src_id, pack_id, data = @tun_info[ :wbuffs ].first
925
- from = :wbuffs
918
+ datas = @tun_info[ :wbuffs ]
926
919
  else
927
920
  @writes.delete( tun )
928
921
  return
929
922
  end
930
923
 
931
- src_ext = @tun_info[ :src_exts ][ src_id ]
924
+ while datas.any?
925
+ src_id, pack_id, data = datas.first
926
+ src_ext = @tun_info[ :src_exts ][ src_id ]
932
927
 
933
- if src_ext
934
- if pack_id <= CONFUSE_UNTIL
935
- data = @custom.encode( data )
936
- # puts "debug1 encoded pack #{ pack_id }"
937
- end
928
+ if src_ext
929
+ if pack_id <= CONFUSE_UNTIL
930
+ data = @custom.encode( data )
931
+ # puts "debug1 encoded pack #{ pack_id }"
932
+ end
938
933
 
939
- data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
934
+ data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
940
935
 
941
- unless send_data( tun, data, @tun_info[ :tund_addr ] )
942
- return
936
+ unless send_data( tun, data, @tun_info[ :tund_addr ] )
937
+ return
938
+ end
939
+
940
+ # puts "debug2 written pack #{ pack_id }"
941
+ src_ext[ :relay_pack_id ] = pack_id
942
+ src_ext[ :wmems ][ pack_id ] = data
943
+ src_ext[ :send_ats ][ pack_id ] = now
944
+ src_ext[ :last_continue_at ] = now
943
945
  end
944
946
 
945
- # puts "debug2 written pack #{ pack_id }"
946
- src_ext[ :relay_pack_id ] = pack_id
947
- src_ext[ :wmems ][ pack_id ] = data
948
- src_ext[ :send_ats ][ pack_id ] = now
949
- src_ext[ :last_continue_at ] = now
947
+ datas.shift
950
948
  end
951
-
952
- @tun_info[ from ].shift
953
949
  end
954
950
 
955
951
  ##
@@ -1376,6 +1372,11 @@ module Girl
1376
1372
 
1377
1373
  puts "p#{ Process.pid } #{ Time.new } recv tund fin"
1378
1374
  set_is_closing( tun )
1375
+ when IP_CHANGED
1376
+ return if from_addr != @tun_info[ :tund_addr ]
1377
+
1378
+ puts "p#{ Process.pid } #{ Time.new } recv ip changed"
1379
+ set_is_closing( tun )
1379
1380
  end
1380
1381
 
1381
1382
  return
@@ -418,15 +418,17 @@ module Girl
418
418
  ##
419
419
  # send data
420
420
  #
421
- def send_data( tund, data, to_addr )
421
+ def send_data( sock, data, to_addr )
422
422
  begin
423
- tund.sendmsg( data, 0, to_addr )
423
+ sock.sendmsg( data, 0, to_addr )
424
424
  rescue IO::WaitWritable, Errno::EINTR
425
425
  return false
426
426
  rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
427
- puts "#{ Time.new } #{ e.class }, close tund"
428
- close_tund( tund )
429
- return false
427
+ if @roles[ sock ] == :tund
428
+ puts "#{ Time.new } #{ e.class }, close tund"
429
+ close_tund( sock )
430
+ return false
431
+ end
430
432
  end
431
433
 
432
434
  true
@@ -541,9 +543,7 @@ module Girl
541
543
  while @proxyd_ctlmsgs.any?
542
544
  to_addr, data = @proxyd_ctlmsgs.first
543
545
 
544
- begin
545
- proxyd.sendmsg( data, 0, to_addr )
546
- rescue IO::WaitWritable, Errno::EINTR
546
+ unless send_data( proxyd, data, to_addr )
547
547
  return
548
548
  end
549
549
 
@@ -558,15 +558,14 @@ module Girl
558
558
  #
559
559
  def write_dst( dst )
560
560
  dst_info = @dst_infos[ dst ]
561
- data = dst_info[ :cache ]
562
- from = :cache
561
+ from, data = :cache, dst_info[ :cache ]
563
562
 
564
563
  if data.empty?
565
564
  if dst_info[ :chunks ].any?
566
565
  path = File.join( @dst_chunk_dir, dst_info[ :chunks ].shift )
567
566
 
568
567
  begin
569
- dst_info[ :cache ] = data = IO.binread( path )
568
+ data = dst_info[ :cache ] = IO.binread( path )
570
569
  File.delete( path )
571
570
  rescue Errno::ENOENT => e
572
571
  puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
@@ -574,8 +573,7 @@ module Girl
574
573
  return
575
574
  end
576
575
  else
577
- data = dst_info[ :wbuff ]
578
- from = :wbuff
576
+ from, data = :wbuff, dst_info[ :wbuff ]
579
577
  end
580
578
  end
581
579
 
@@ -613,6 +611,11 @@ module Girl
613
611
  tund_info = @tund_infos[ tund ]
614
612
 
615
613
  if tund_info[ :is_closing ]
614
+ if tund_info[ :changed_tun_addr ]
615
+ data = [ 0, IP_CHANGED ].pack( 'Q>C' )
616
+ send_data( tund, data, tund_info[ :changed_tun_addr ] )
617
+ end
618
+
616
619
  close_tund( tund )
617
620
  return
618
621
  end
@@ -646,7 +649,6 @@ module Girl
646
649
  end
647
650
 
648
651
  tund_info[ :resendings ].shift
649
- return
650
652
  end
651
653
 
652
654
  # 若写后达到上限,暂停取写前
@@ -662,8 +664,7 @@ module Girl
662
664
 
663
665
  # 取写前
664
666
  if tund_info[ :caches ].any?
665
- dst_local_port, pack_id, data = tund_info[ :caches ].first
666
- from = :caches
667
+ datas = tund_info[ :caches ]
667
668
  elsif tund_info[ :chunks ].any?
668
669
  path = File.join( @tund_chunk_dir, tund_info[ :chunks ].shift )
669
670
 
@@ -684,39 +685,39 @@ module Girl
684
685
  data = data[ ( 12 + pack_size )..-1 ]
685
686
  end
686
687
 
687
- tund_info[ :caches ] = caches
688
- dst_local_port, pack_id, data = caches.first
689
- from = :caches
688
+ datas = tund_info[ :caches ] = caches
690
689
  elsif tund_info[ :wbuffs ].any?
691
- dst_local_port, pack_id, data = tund_info[ :wbuffs ].first
692
- from = :wbuffs
690
+ datas = tund_info[ :wbuffs ]
693
691
  else
694
692
  @writes.delete( tund )
695
693
  return
696
694
  end
697
695
 
698
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
696
+ while datas.any?
697
+ dst_local_port, pack_id, data = datas.first
698
+ dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
699
699
 
700
- if dst_ext
701
- if pack_id <= CONFUSE_UNTIL
702
- data = @custom.encode( data )
703
- # puts "debug1 encoded pack #{ pack_id }"
704
- end
700
+ if dst_ext
701
+ if pack_id <= CONFUSE_UNTIL
702
+ data = @custom.encode( data )
703
+ # puts "debug1 encoded pack #{ pack_id }"
704
+ end
705
705
 
706
- data = [ [ pack_id, dst_local_port ].pack( 'Q>n' ), data ].join
706
+ data = [ [ pack_id, dst_local_port ].pack( 'Q>n' ), data ].join
707
707
 
708
- unless send_data( tund, data, tund_info[ :tun_addr ] )
709
- return
708
+ unless send_data( tund, data, tund_info[ :tun_addr ] )
709
+ return
710
+ end
711
+
712
+ # puts "debug2 written pack #{ pack_id }"
713
+ dst_ext[ :relay_pack_id ] = pack_id
714
+ dst_ext[ :wmems ][ pack_id ] = data
715
+ dst_ext[ :send_ats ][ pack_id ] = now
716
+ dst_ext[ :last_continue_at ] = now
710
717
  end
711
718
 
712
- # puts "debug2 written pack #{ pack_id }"
713
- dst_ext[ :relay_pack_id ] = pack_id
714
- dst_ext[ :wmems ][ pack_id ] = data
715
- dst_ext[ :send_ats ][ pack_id ] = now
716
- dst_ext[ :last_continue_at ] = now
719
+ datas.shift
717
720
  end
718
-
719
- tund_info[ from ].shift
720
721
  end
721
722
 
722
723
  ##
@@ -762,7 +763,8 @@ module Girl
762
763
  resendings: [], # 重传队列 [ dst_local_port, pack_id ]
763
764
  created_at: Time.new, # 创建时间
764
765
  last_recv_at: nil, # 上一次收到流量的时间,过期关闭
765
- is_closing: false # 是否准备关闭
766
+ is_closing: false, # 是否准备关闭
767
+ changed_tun_addr: nil # 记录到和tun addr不符的来源地址
766
768
  }
767
769
 
768
770
  add_read( tund, :tund )
@@ -812,13 +814,11 @@ module Girl
812
814
  tund_info = @tund_infos[ tund ]
813
815
 
814
816
  if from_addr != tund_info[ :tun_addr ]
815
- if addrinfo.ip_port == Addrinfo.new( tund_info[ :tun_addr ] ).ip_port
816
- puts "p#{ Process.pid } #{ Time.new } tun ip changed #{ addrinfo.inspect }"
817
- tund_info[ :tun_addr ] = from_addr
818
- else
819
- puts "p#{ Process.pid } #{ Time.new } #{ addrinfo.inspect } not match #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
820
- return
821
- end
817
+ # 通常是光猫刷新ip(端口也会变),但万一不是,为了避免脏数据注入,关闭tund
818
+ puts "p#{ Process.pid } #{ Time.new } from #{ addrinfo.inspect } not match tun addr #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
819
+ tund_info[ :changed_tun_addr ] = from_addr
820
+ set_is_closing( tund )
821
+ return
822
822
  end
823
823
 
824
824
  tund_info[ :last_recv_at ] = now
@@ -17,25 +17,12 @@ module Girl
17
17
  class Udp
18
18
 
19
19
  def initialize( udpd_host, udpd_port = 3030, redir_port = 1313 )
20
- ctlr, ctlw = IO.pipe
21
-
22
- redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
23
- redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
24
- redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
25
- puts "redir bound on #{ redir_port } #{ Time.new }"
26
-
27
- @mutex = Mutex.new
28
20
  @udpd_host = udpd_host
29
21
  @udpd_addr = Socket.sockaddr_in( udpd_port, udpd_host )
30
- @ctlw = ctlw
31
- @redir = redir
32
- @reads = [ ctlr, redir ]
22
+ @mutex = Mutex.new
23
+ @reads = []
33
24
  @writes = []
34
- @closings = []
35
- @roles = {
36
- ctlr => :ctlr, # :ctlr / :redir / :tun
37
- redir => :redir
38
- }
25
+ @roles = {} # :dotr / :redir / :tun
39
26
  @redir_wbuffs = [] # [ src_addr data ] ...
40
27
  @tuns = {} # [ orig_src_addr dst_addr ]=> tun
41
28
  @mappings = {} # src_addr => [ orig_src_addr dst_addr ]
@@ -47,6 +34,10 @@ module Girl
47
34
  # rbuffs: []
48
35
  # wbuffs: []
49
36
  # last_traff_at: now
37
+ dotr, dotw = IO.pipe
38
+ @dotw = dotw
39
+ add_read( dotr, :dotr )
40
+ new_a_redir( redir_port )
50
41
  end
51
42
 
52
43
  def looping
@@ -56,23 +47,23 @@ module Girl
56
47
  rs, ws = IO.select( @reads, @writes )
57
48
 
58
49
  @mutex.synchronize do
59
- rs.each do | sock |
50
+ ws.each do | sock |
60
51
  case @roles[ sock ]
61
- when :ctlr
62
- read_ctlr( sock )
63
52
  when :redir
64
- read_redir( sock )
53
+ write_redir( sock )
65
54
  when :tun
66
- read_tun( sock )
55
+ write_tun( sock )
67
56
  end
68
57
  end
69
58
 
70
- ws.each do | sock |
59
+ rs.each do | sock |
71
60
  case @roles[ sock ]
61
+ when :dotr
62
+ read_dotr( sock )
72
63
  when :redir
73
- write_redir( sock )
64
+ read_redir( sock )
74
65
  when :tun
75
- write_tun( sock )
66
+ read_tun( sock )
76
67
  end
77
68
  end
78
69
  end
@@ -85,15 +76,176 @@ module Girl
85
76
 
86
77
  private
87
78
 
88
- def read_ctlr( ctlr )
89
- od_addr = ctlr.read( 32 )
90
- tun = @tuns[ od_addr ]
79
+ def loop_expire
80
+ Thread.new do
81
+ loop do
82
+ sleep 30
91
83
 
92
- if tun
93
- add_closing( tun )
84
+ @mutex.synchronize do
85
+ need_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
91
+ set_is_closing( tun )
92
+ need_trigger = true
93
+ end
94
+ end
95
+
96
+ if need_trigger
97
+ next_tick
98
+ end
99
+ end
100
+ end
94
101
  end
95
102
  end
96
103
 
104
+ def new_a_redir( redir_port )
105
+ redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
106
+ redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
107
+ redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
108
+ puts "redir bound on #{ redir_port } #{ Time.new }"
109
+ @redir = redir
110
+ add_read( redir, :redir )
111
+ end
112
+
113
+ def new_a_tun( orig_src_addr, dst_addr, src_addr )
114
+ tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
115
+ tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
116
+ tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
117
+
118
+ @tun_infos[ tun ] = {
119
+ orig_src_addr: orig_src_addr,
120
+ dst_addr: dst_addr,
121
+ src_addr: src_addr,
122
+ tund_addr: nil,
123
+ rbuffs: [],
124
+ wbuffs: [],
125
+ last_traff_at: Time.new,
126
+ is_closing: false
127
+ }
128
+
129
+ @tuns[ [ orig_src_addr, dst_addr ].join ] = tun
130
+ add_read( tun, :tun )
131
+
132
+ tun
133
+ end
134
+
135
+ def add_redir_wbuff( redir, to_addr, data )
136
+ @redir_wbuffs << [ to_addr, data ]
137
+ add_write( redir )
138
+ end
139
+
140
+ def add_tun_wbuff( tun, to_addr, data )
141
+ tun_info = @tun_infos[ tun ]
142
+
143
+ if to_addr
144
+ tun_info[ :wbuffs ] << [ to_addr, data ]
145
+ add_write( tun )
146
+ else
147
+ tun_info[ :rbuffs ] << data
148
+ end
149
+ end
150
+
151
+ def add_read( sock, role )
152
+ unless @reads.include?( sock )
153
+ @reads << sock
154
+ end
155
+
156
+ @roles[ sock ] = role
157
+ end
158
+
159
+ def add_write( sock )
160
+ unless @writes.include?( sock )
161
+ @writes << sock
162
+ end
163
+ end
164
+
165
+ def set_is_closing( tun )
166
+ if tun && !tun.closed?
167
+ # puts "debug1 set tun is closing"
168
+
169
+ tun_info = @tun_infos[ tun ]
170
+ tun_info[ :is_closing ] = true
171
+
172
+ @reads.delete( tun )
173
+ add_write( tun )
174
+ end
175
+ end
176
+
177
+ def send_data( sock, data, to_addr )
178
+ begin
179
+ sock.sendmsg( data, 0, to_addr )
180
+ rescue IO::WaitWritable, Errno::EINTR
181
+ return false
182
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
183
+ if @roles[ sock ] == :tun
184
+ puts "#{ Time.new } #{ e.class }, close tun"
185
+ close_tun( sock )
186
+ return false
187
+ end
188
+ end
189
+
190
+ true
191
+ end
192
+
193
+ def close_tun( tun )
194
+ tun.close
195
+ @reads.delete( tun )
196
+ @writes.delete( tun )
197
+ @roles.delete( tun )
198
+ tun_info = @tun_infos.delete( tun )
199
+ @tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
200
+
201
+ if @mappings.include?( tun_info[ :src_addr ] )
202
+ orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
203
+
204
+ if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ]
205
+ @mappings.delete( tun_info[ :src_addr ] )
206
+ end
207
+ end
208
+ end
209
+
210
+ def write_redir( redir )
211
+ while @redir_wbuffs.any?
212
+ to_addr, data = @redir_wbuffs.first
213
+
214
+ unless send_data( redir, data, to_addr )
215
+ return
216
+ end
217
+
218
+ @redir_wbuffs.shift
219
+ end
220
+
221
+ @writes.delete( redir )
222
+ end
223
+
224
+ def write_tun( tun )
225
+ tun_info = @tun_infos[ tun ]
226
+
227
+ if tun_info[ :is_closing ]
228
+ close_tun( tun )
229
+ return
230
+ end
231
+
232
+ while tun_info[ :wbuffs ].any?
233
+ to_addr, data = tun_info[ :wbuffs ].first
234
+
235
+ unless send_data( tun, data, to_addr )
236
+ return
237
+ end
238
+
239
+ tun_info[ :wbuffs ].shift
240
+ end
241
+
242
+ @writes.delete( tun )
243
+ end
244
+
245
+ def read_dotr( dotr )
246
+ dotr.read( 1 )
247
+ end
248
+
97
249
  def read_redir( redir )
98
250
  data, addrinfo, rflags, *controls = redir.recvmsg
99
251
  src_addr = addrinfo.to_sockaddr
@@ -180,121 +332,5 @@ module Girl
180
332
  end
181
333
  end
182
334
 
183
- def write_redir( redir )
184
- if @redir_wbuffs.empty?
185
- @writes.delete( redir )
186
- return
187
- end
188
-
189
- src_addr, data = @redir_wbuffs.shift
190
- redir.sendmsg( data, 0, src_addr )
191
- end
192
-
193
- def write_tun( tun )
194
- if @closings.include?( tun )
195
- close_tun( tun )
196
- return
197
- end
198
-
199
- tun_info = @tun_infos[ tun ]
200
-
201
- if tun_info[ :wbuffs ].empty?
202
- @writes.delete( tun )
203
- return
204
- end
205
-
206
- to_addr, data = tun_info[ :wbuffs ].shift
207
- tun.sendmsg( data, 0, to_addr )
208
- end
209
-
210
- def add_redir_wbuff( redir, to_addr, data )
211
- @redir_wbuffs << [ to_addr, data ]
212
- add_write( redir )
213
- end
214
-
215
- def add_tun_wbuff( tun, to_addr, data )
216
- tun_info = @tun_infos[ tun ]
217
-
218
- if to_addr
219
- tun_info[ :wbuffs ] << [ to_addr, data ]
220
- add_write( tun )
221
- else
222
- tun_info[ :rbuffs ] << data
223
- end
224
- end
225
-
226
- def add_write( sock )
227
- unless @writes.include?( sock )
228
- @writes << sock
229
- end
230
- end
231
-
232
- def add_closing( tun )
233
- unless @closings.include?( tun )
234
- @closings << tun
235
- end
236
-
237
- add_write( tun )
238
- end
239
-
240
- def close_tun( tun )
241
- tun.close
242
- @reads.delete( tun )
243
- @writes.delete( tun )
244
- @closings.delete( tun )
245
- @roles.delete( tun )
246
- tun_info = @tun_infos.delete( tun )
247
- @tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
248
-
249
- if @mappings.include?( tun_info[ :src_addr ] )
250
- orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
251
-
252
- if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ]
253
- @mappings.delete( tun_info[ :src_addr ] )
254
- end
255
- end
256
- end
257
-
258
- def new_a_tun( orig_src_addr, dst_addr, src_addr )
259
- tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
260
- tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
261
- tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
262
-
263
- @tun_infos[ tun ] = {
264
- orig_src_addr: orig_src_addr,
265
- dst_addr: dst_addr,
266
- src_addr: src_addr,
267
- tund_addr: nil,
268
- rbuffs: [],
269
- wbuffs: [],
270
- last_traff_at: Time.new
271
- }
272
-
273
- @tuns[ [ orig_src_addr, dst_addr ].join ] = tun
274
- @roles[ tun ] = :tun
275
- @reads << tun
276
-
277
- tun
278
- end
279
-
280
- def loop_expire
281
- Thread.new do
282
- loop do
283
- sleep 30
284
-
285
- @mutex.synchronize do
286
- now = Time.new
287
-
288
- @tun_infos.values.each do | tun_info |
289
- # net.netfilter.nf_conntrack_udp_timeout_stream
290
- if now - tun_info[ :last_traff_at ] > 180
291
- @ctlw.write( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
292
- end
293
- end
294
- end
295
- end
296
- end
297
- end
298
-
299
335
  end
300
336
  end
@@ -8,23 +8,10 @@ module Girl
8
8
  class Udpd
9
9
 
10
10
  def initialize( port = 3030 )
11
- ctlr, ctlw = IO.pipe
12
-
13
- udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
14
- udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
15
- udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
16
- puts "udpd bound on #{ port } #{ Time.new }"
17
-
18
11
  @mutex = Mutex.new
19
- @ctlw = ctlw
20
- @udpd = udpd
21
- @reads = [ ctlr, udpd ]
12
+ @reads = []
22
13
  @writes = []
23
- @closings = []
24
- @roles = {
25
- ctlr => :ctlr, # :ctlr / :udpd / :tund
26
- udpd => :udpd
27
- }
14
+ @roles = {} # :dotr / :udpd / :tund
28
15
  @udpd_wbuffs = [] # [ tun_addr ctlmsg ] ...
29
16
  @tunds = {} # [ tun_ip_addr orig_src_addr ] => tund
30
17
  @tund_infos = {} # tund => {}
@@ -37,6 +24,10 @@ module Girl
37
24
  # is_tunneleds: { [ tun_addr dst_addr ] => false }
38
25
  # unpaired_dst_rbuffs: { dst_addr => [] }
39
26
  # last_traff_at: now
27
+ dotr, dotw = IO.pipe
28
+ @dotw = dotw
29
+ add_read( dotr, :dotr )
30
+ new_a_udpd( port )
40
31
  end
41
32
 
42
33
  def looping
@@ -46,23 +37,23 @@ module Girl
46
37
  rs, ws = IO.select( @reads, @writes )
47
38
 
48
39
  @mutex.synchronize do
49
- rs.each do | sock |
40
+ ws.each do | sock |
50
41
  case @roles[ sock ]
51
- when :ctlr
52
- read_ctlr( sock )
53
42
  when :udpd
54
- read_udpd( sock )
43
+ write_udpd( sock )
55
44
  when :tund
56
- read_tund( sock )
45
+ write_tund( sock )
57
46
  end
58
47
  end
59
48
 
60
- ws.each do | sock |
49
+ rs.each do | sock |
61
50
  case @roles[ sock ]
51
+ when :dotr
52
+ read_dotr( sock )
62
53
  when :udpd
63
- write_udpd( sock )
54
+ read_udpd( sock )
64
55
  when :tund
65
- write_tund( sock )
56
+ read_tund( sock )
66
57
  end
67
58
  end
68
59
  end
@@ -75,13 +66,176 @@ module Girl
75
66
 
76
67
  private
77
68
 
78
- def read_ctlr( ctlr )
79
- to_addr = ctlr.read( 32 )
80
- tund = @tunds[ to_addr ]
69
+ def loop_expire
70
+ Thread.new do
71
+ loop do
72
+ sleep 30
73
+
74
+ @mutex.synchronize do
75
+ need_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
81
+ set_is_closing( tund )
82
+ need_trigger = true
83
+ end
84
+ end
85
+
86
+ if need_trigger
87
+ next_tick
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def new_a_udpd( port )
95
+ udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
96
+ udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
97
+ udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
98
+ puts "udpd bound on #{ port } #{ Time.new }"
99
+ @udpd = udpd
100
+ add_read( udpd, :udpd )
101
+ end
102
+
103
+ def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
104
+ from_addr = [ tun_ip_addr, orig_src_addr ].join
105
+ td_addr = [ tun_addr, dst_addr ].join
106
+ tund = @tunds[ from_addr ]
81
107
 
82
108
  if tund
83
- add_closing( tund )
109
+ tund_info = @tund_infos[ tund ]
110
+ tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
111
+ tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
112
+ tund_info[ :is_tunneleds ][ td_addr ] = false
113
+ else
114
+ tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
115
+ tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
116
+ tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
117
+ tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
118
+ tund_port = tund.local_address.ip_unpack.last
119
+
120
+ @tund_infos[ tund ] = {
121
+ port: tund_port,
122
+ tun_ip_addr: tun_ip_addr,
123
+ orig_src_addr: orig_src_addr,
124
+ wbuffs: [],
125
+ dst_addrs: { tun_addr => dst_addr },
126
+ tun_addrs: { dst_addr => tun_addr },
127
+ is_tunneleds: { td_addr => false },
128
+ unpaired_dst_rbuffs: {},
129
+ last_traff_at: Time.new,
130
+ is_closing: false
131
+ }
132
+
133
+ @tunds[ from_addr ] = tund
134
+ add_read( tund, :tund )
135
+ end
136
+
137
+ tund
138
+ end
139
+
140
+ def add_tund_wbuff( tund, to_addr, data )
141
+ tund_info = @tund_infos[ tund ]
142
+ tund_info[ :wbuffs ] << [ to_addr, data ]
143
+
144
+ add_write( tund )
145
+ end
146
+
147
+ def add_read( sock, role )
148
+ unless @reads.include?( sock )
149
+ @reads << sock
150
+ end
151
+
152
+ @roles[ sock ] = role
153
+ end
154
+
155
+ def add_write( sock )
156
+ unless @writes.include?( sock )
157
+ @writes << sock
158
+ end
159
+ end
160
+
161
+ def set_is_closing( tund )
162
+ if tund && !tund.closed?
163
+ # puts "debug1 set tund is closing"
164
+
165
+ tund_info = @tund_infos[ tund ]
166
+ tund_info[ :is_closing ] = true
167
+
168
+ @reads.delete( tund )
169
+ add_write( tund )
170
+ end
171
+ end
172
+
173
+ def send_data( sock, data, to_addr )
174
+ begin
175
+ sock.sendmsg( data, 0, to_addr )
176
+ rescue IO::WaitWritable, Errno::EINTR
177
+ return false
178
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
179
+ if @roles[ sock ] == :tund
180
+ puts "#{ Time.new } #{ e.class }, close tund"
181
+ close_tund( sock )
182
+ return false
183
+ end
184
+ end
185
+
186
+ true
187
+ end
188
+
189
+ def close_tund( tund )
190
+ tund.close
191
+ @reads.delete( tund )
192
+ @writes.delete( tund )
193
+ @roles.delete( tund )
194
+ tund_info = @tund_infos.delete( tund )
195
+ @tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
196
+ end
197
+
198
+ def next_tick
199
+ @dotw.write( '.' )
200
+ end
201
+
202
+ def write_udpd( udpd )
203
+ while @udpd_wbuffs.any?
204
+ to_addr, data = @udpd_wbuffs.first
205
+
206
+ unless send_data( udpd, data, to_addr )
207
+ return
208
+ end
209
+
210
+ @udpd_wbuffs.shift
211
+ end
212
+
213
+ @writes.delete( udpd )
214
+ end
215
+
216
+ def write_tund( tund )
217
+ tund_info = @tund_infos[ tund ]
218
+
219
+ if tund_info[ :is_closing ]
220
+ close_tund( tund )
221
+ return
222
+ end
223
+
224
+ while tund_info[ :wbuffs ].any?
225
+ to_addr, data = tund_info[ :wbuffs ].first
226
+
227
+ unless send_data( tund, data, to_addr )
228
+ return
229
+ end
230
+
231
+ tund_info[ :wbuffs ].shift
84
232
  end
233
+
234
+ @writes.delete( tund )
235
+ end
236
+
237
+ def read_dotr( dotr )
238
+ dotr.read( 1 )
85
239
  end
86
240
 
87
241
  def read_udpd( udpd )
@@ -168,119 +322,5 @@ module Girl
168
322
  end
169
323
  end
170
324
 
171
- def write_udpd( udpd )
172
- if @udpd_wbuffs.empty?
173
- @writes.delete( udpd )
174
- return
175
- end
176
-
177
- tun_addr, ctlmsg = @udpd_wbuffs.shift
178
- udpd.sendmsg( ctlmsg, 0, tun_addr )
179
- end
180
-
181
- def write_tund( tund )
182
- if @closings.include?( tund )
183
- close_tund( tund )
184
- return
185
- end
186
-
187
- tund_info = @tund_infos[ tund ]
188
-
189
- if tund_info[ :wbuffs ].empty?
190
- @writes.delete( tund )
191
- return
192
- end
193
-
194
- to_addr, data = tund_info[ :wbuffs ].shift
195
- tund.sendmsg( data, 0, to_addr )
196
- end
197
-
198
- def add_tund_wbuff( tund, to_addr, data )
199
- tund_info = @tund_infos[ tund ]
200
- tund_info[ :wbuffs ] << [ to_addr, data ]
201
-
202
- add_write( tund )
203
- end
204
-
205
- def add_write( sock )
206
- unless @writes.include?( sock )
207
- @writes << sock
208
- end
209
- end
210
-
211
- def add_closing( tund )
212
- unless @closings.include?( tund )
213
- @closings << tund
214
- end
215
-
216
- add_write( tund )
217
- end
218
-
219
- def close_tund( tund )
220
- tund.close
221
- @reads.delete( tund )
222
- @writes.delete( tund )
223
- @closings.delete( tund )
224
- @roles.delete( tund )
225
- tund_info = @tund_infos.delete( tund )
226
- @tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
227
- end
228
-
229
- def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
230
- from_addr = [ tun_ip_addr, orig_src_addr ].join
231
- td_addr = [ tun_addr, dst_addr ].join
232
- tund = @tunds[ from_addr ]
233
-
234
- if tund
235
- tund_info = @tund_infos[ tund ]
236
- tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
237
- tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
238
- tund_info[ :is_tunneleds ][ td_addr ] = false
239
- else
240
- tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
241
- tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
242
- tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
243
- tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
244
- tund_port = tund.local_address.ip_unpack.last
245
-
246
- @tund_infos[ tund ] = {
247
- port: tund_port,
248
- tun_ip_addr: tun_ip_addr,
249
- orig_src_addr: orig_src_addr,
250
- wbuffs: [],
251
- dst_addrs: { tun_addr => dst_addr },
252
- tun_addrs: { dst_addr => tun_addr },
253
- is_tunneleds: { td_addr => false },
254
- unpaired_dst_rbuffs: {},
255
- last_traff_at: Time.new
256
- }
257
-
258
- @roles[ tund ] = :tund
259
- @reads << tund
260
- @tunds[ from_addr ] = tund
261
- end
262
-
263
- tund
264
- end
265
-
266
- def loop_expire
267
- Thread.new do
268
- loop do
269
- sleep 30
270
-
271
- @mutex.synchronize do
272
- now = Time.new
273
-
274
- @tund_infos.values.each do | tund_info |
275
- # net.netfilter.nf_conntrack_udp_timeout_stream
276
- if now - tund_info[ :last_traff_at ] > 180
277
- @ctlw.write( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
278
- end
279
- end
280
- end
281
- end
282
- end
283
- end
284
-
285
325
  end
286
326
  end
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '0.78.0'.freeze
2
+ VERSION = '0.83.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.78.0
4
+ version: 0.83.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-08-21 00:00:00.000000000 Z
11
+ date: 2020-09-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: while internet is evil, here's a girl.
14
14
  email: