girl 0.64.1 → 0.69.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: 5f4e1bba2efaa28dcf93f09ed4e913b449165cdd55febb11d5b59d88f374e49f
4
- data.tar.gz: e23ceb94f65c8edf04b53fb8fd369b47d1aecd602bbdd4057f0498fda63bfeb8
3
+ metadata.gz: b16f67f52bf05cd498b16e480ee9d29577217ef93fd8964c0256e3816eb837e6
4
+ data.tar.gz: 38a5178d59930baa536a2ea882b8e17d86bb5e194386bcf9fc5ef7615d8e120e
5
5
  SHA512:
6
- metadata.gz: d8f9d02746902687b25c2c17346cae8bda8e493c4b7325afa0c64a6417769dd3c39941cf2668b41041ce5f74205399cdc3ce990808602ff6e748012b5462a284
7
- data.tar.gz: b4b52b30693c3d6afca6bd9fee85ac7782afba4b58f475aa73961d3fc8fb3ba21299c745f827631e732dc9e63b2faca5e506dd9f5201e134edd52d38f5fc6097
6
+ metadata.gz: 139f1ea8a12a8e58d236e873ef1b3cb2944768ac1f2940fc986afb3ed5095e82550235f89fa1a81981b1981d6422f5bebd7918874a8cfe2fef7ab586af1d22fa
7
+ data.tar.gz: 0554a3541237a4f62d838309b3ff703b18480218646bf6f3920e218d477aed0d41e21ef1cd944e4f042539c0d0d17a73a15f0fedcd4d8356d350b7052c1071a5
@@ -1,16 +1,14 @@
1
1
  module Girl
2
- PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(source/dest id) - 8(pack id) = 1328
2
+ PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
3
  CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
- PROXY_PACK_SIZE = 1320 # 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 16(src_addr) = 1320
5
- PROXY_CHUNK_SIZE = PROXY_PACK_SIZE * 1000 # proxy块大小
6
4
  WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
7
5
  WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
8
6
  RESUME_BELOW = 50_000 # 降到多少以下恢复写
9
7
  EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
10
- EXPIRE_AFTER = 3600 # 多久没有新流量进来,过期
8
+ EXPIRE_AFTER = 300 # 多久没有新流量,过期
11
9
  CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
12
10
  HEARTBEAT_INTERVAL = 30 # 心跳间隔
13
- STATUS_INTERVAL = 0.3 # 发送状态间隔
11
+ STATUS_INTERVAL = 0.5 # 发送状态间隔
14
12
  SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
15
13
  BREAK_SEND_MISS = 10_000 # miss包个数上限,达到上限忽略要后面的段,可控碎片缓存
16
14
  CONFUSE_UNTIL = 5 # 混淆前几个包
@@ -24,19 +24,19 @@ require 'socket'
24
24
  # tun-tund:
25
25
  #
26
26
  # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
- # 3 a new src -> src_addr -> encoded destination address
28
- # 4 paired -> src_addr -> n: dst_port
27
+ # 3 a new src -> Q>: src_id -> encoded destination address
28
+ # 4 paired -> Q>: src_id -> n: dst_port
29
29
  # 5 dst status -> n: dst_port -> Q>Q>: biggest_dst_pack_id continue_src_pack_id
30
- # 6 src status -> src_addr -> Q>Q>: biggest_src_pack_id continue_dst_pack_id
31
- # 7 miss -> src_addr/n: dst_port -> Q>Q>: pack_id_begin pack_id_end
32
- # 8 fin1 -> src_addr/n: dst_port -> Q>Q>: biggest_src_pack_id continue_dst_pack_id / biggest_dst_pack_id continue_src_pack_id
30
+ # 6 src status -> Q>: src_id -> Q>Q>: biggest_src_pack_id continue_dst_pack_id
31
+ # 7 miss -> Q>: src_id/n: dst_port -> Q>Q>: pack_id_begin pack_id_end
32
+ # 8 fin1 -> Q>: src_id/n: dst_port -> Q>Q>: biggest_src_pack_id continue_dst_pack_id / biggest_dst_pack_id continue_src_pack_id
33
33
  # 9 not use
34
- # 10 fin2 -> src_addr/n: dst_port
34
+ # 10 fin2 -> Q>: src_id/n: dst_port
35
35
  # 11 not use
36
36
  # 12 tund fin
37
37
  # 13 tun fin
38
38
  #
39
- # Q>: 1+ pack_id -> src_addr/n: dst_port -> traffic
39
+ # Q>: 1+ pack_id -> Q>: src_id/n: dst_port -> traffic
40
40
  #
41
41
  # close logic
42
42
  # ===========
@@ -102,19 +102,20 @@ module Girl
102
102
  now = Time.new
103
103
 
104
104
  if @tun && !@tun.closed?
105
- is_expired = @tun_info[ :last_recv_at ].nil? && ( now - @tun_info[ :created_at ] > EXPIRE_NEW )
105
+ is_expired = @tun_info[ :last_recv_at ] ? ( now - @tun_info[ :last_recv_at ] > EXPIRE_AFTER ) : ( now - @tun_info[ :created_at ] > EXPIRE_NEW )
106
106
 
107
107
  if is_expired
108
108
  puts "p#{ Process.pid } #{ Time.new } expire tun"
109
109
  set_is_closing( @tun )
110
110
  else
111
111
  data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
112
+ # puts "debug1 #{ Time.new } heartbeat"
112
113
  add_tun_ctlmsg( data )
113
114
 
114
- @tun_info[ :src_exts ].each do | src_addr, src_ext |
115
+ @tun_info[ :src_exts ].each do | src_id, src_ext |
115
116
  if src_ext[ :src ].closed? && ( now - src_ext[ :last_continue_at ] > EXPIRE_AFTER )
116
- puts "p#{ Process.pid } #{ Time.new } expire src ext"
117
- del_src_ext( src_addr )
117
+ puts "p#{ Process.pid } #{ Time.new } expire src ext #{ src_id }"
118
+ del_src_ext( src_id )
118
119
  end
119
120
  end
120
121
  end
@@ -165,10 +166,10 @@ module Girl
165
166
  if @tun_info[ :src_exts ].any?
166
167
  now = Time.new
167
168
 
168
- @tun_info[ :src_exts ].each do | src_addr, src_ext |
169
+ @tun_info[ :src_exts ].each do | src_id, src_ext |
169
170
  if src_ext[ :dst_port ] && ( now - src_ext[ :last_continue_at ] < SEND_STATUS_UNTIL )
170
171
  # puts "debug2 ctl send status biggest #{ src_ext[ :biggest_pack_id ] } continue dst #{ src_ext[ :continue_dst_pack_id ] }"
171
- data = [ [ 0, SOURCE_STATUS ].pack( 'Q>C' ), src_addr, [ src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>Q>' ) ].join
172
+ data = [ 0, SOURCE_STATUS, src_id, src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
172
173
  add_tun_ctlmsg( data )
173
174
  need_trigger = true
174
175
  end
@@ -179,6 +180,11 @@ module Girl
179
180
  puts "p#{ Process.pid } #{ Time.new } resume tun"
180
181
  @tun_info[ :paused ] = false
181
182
  add_write( @tun )
183
+
184
+ @tun_info[ :src_exts ].each do | _, src_ext |
185
+ add_write( src_ext[ :src ] )
186
+ end
187
+
182
188
  need_trigger = true
183
189
  end
184
190
 
@@ -311,20 +317,20 @@ module Girl
311
317
  def new_a_tun
312
318
  tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
313
319
  tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
314
- port = tun.local_address.ip_unpack.last
320
+ port = tun.local_address.ip_port
315
321
  tun_info = {
316
322
  port: port, # 端口
317
323
  ctlmsg_rbuffs: [], # 还没配上tund,暂存的ctlmsg
318
324
  ctlmsgs: [], # [ to_addr, data ]
319
- wbuffs: [], # 写前缓存 [ src_addr, data ]
320
- caches: [], # 块读出缓存 [ src_addr, data ]
325
+ wbuffs: [], # 写前缓存 [ src_id, data ]
326
+ caches: [], # 块读出缓存 [ src_id, data ]
321
327
  chunks: [], # 块队列 filename
322
328
  spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
323
329
  tund_addr: nil, # tund地址
324
- src_exts: {}, # src额外信息 src_addr => {}
325
- src_addrs: {}, # dst_port => src_addr
330
+ src_exts: {}, # src额外信息 src_id => {}
331
+ src_ids: {}, # dst_port => src_id
326
332
  paused: false, # 是否暂停写
327
- resendings: [], # 重传队列 [ src_addr, pack_id ]
333
+ resendings: [], # 重传队列 [ src_id, pack_id ]
328
334
  created_at: Time.new, # 创建时间
329
335
  last_recv_at: nil, # 上一次收到流量的时间,过期关闭
330
336
  is_closing: false # 是否准备关闭
@@ -363,7 +369,7 @@ module Girl
363
369
  end
364
370
 
365
371
  # puts "debug1 a new dst #{ dst.local_address.inspect }"
366
- local_port = dst.local_address.ip_unpack.last
372
+ local_port = dst.local_address.ip_port
367
373
  @dsts[ local_port ] = dst
368
374
  @dst_infos[ dst ] = {
369
375
  local_port: local_port, # 本地端口
@@ -424,14 +430,14 @@ module Girl
424
430
  }
425
431
 
426
432
  src_info = @src_infos[ src ]
427
- src_addr = src_info[ :src_addr ]
428
- @tun_info[ :src_exts ][ src_addr ] = src_ext
433
+ src_id = src_info[ :id ]
434
+ @tun_info[ :src_exts ][ src_id ] = src_ext
429
435
  src_info[ :proxy_type ] = :tunnel
430
436
 
431
437
  destination_port = src_info[ :destination_port ]
432
438
  destination_domain = src_info[ :destination_domain ]
433
439
  destination_domain_port = [ destination_domain, destination_port ].join( ':' )
434
- data = [ [ 0, A_NEW_SOURCE ].pack( 'Q>C' ), src_addr, @custom.encode( destination_domain_port ) ].join
440
+ data = [ [ 0, A_NEW_SOURCE, src_id ].pack( 'Q>CQ>' ), @custom.encode( destination_domain_port ) ].join
435
441
  loop_send_a_new_source( src_ext, data )
436
442
  end
437
443
 
@@ -490,14 +496,14 @@ module Girl
490
496
  ##
491
497
  # add tun wbuff
492
498
  #
493
- def add_tun_wbuff( src_addr, data )
494
- @tun_info[ :wbuffs ] << [ src_addr, data ]
499
+ def add_tun_wbuff( src_id, data )
500
+ @tun_info[ :wbuffs ] << [ src_id, data ]
495
501
 
496
502
  if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
497
503
  spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
498
504
  filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
499
505
  chunk_path = File.join( @tun_chunk_dir, filename )
500
- wbuffs = @tun_info[ :wbuffs ].map{ | _src_addr, _data | [ _src_addr, [ _data.bytesize ].pack( 'n' ), _data ].join }
506
+ wbuffs = @tun_info[ :wbuffs ].map{ | _src_id, _data | [ [ _src_id, _data.bytesize ].pack( 'Q>n' ), _data ].join }
501
507
 
502
508
  begin
503
509
  IO.binwrite( chunk_path, wbuffs.join )
@@ -522,9 +528,9 @@ module Girl
522
528
  src_info = @src_infos[ src ]
523
529
  src_info[ :wbuff ] << data
524
530
 
525
- if src_info[ :wbuff ].bytesize >= PROXY_CHUNK_SIZE
531
+ if src_info[ :wbuff ].bytesize >= CHUNK_SIZE
526
532
  spring = src_info[ :chunks ].size > 0 ? ( src_info[ :spring ] + 1 ) : 0
527
- filename = "#{ Process.pid }-#{ Addrinfo.new( src_info[ :src_addr ] ).ip_unpack.join( '-' ) }.#{ spring }"
533
+ filename = "#{ Process.pid }-#{ src_info[ :id ] }.#{ spring }"
528
534
  chunk_path = File.join( @src_chunk_dir, filename )
529
535
 
530
536
  begin
@@ -550,7 +556,7 @@ module Girl
550
556
  dst_info = @dst_infos[ dst ]
551
557
  dst_info[ :wbuff ] << data
552
558
 
553
- if dst_info[ :wbuff ].bytesize >= PROXY_CHUNK_SIZE
559
+ if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
554
560
  spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
555
561
  filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
556
562
  chunk_path = File.join( @dst_chunk_dir, filename )
@@ -586,7 +592,7 @@ module Girl
586
592
  # add write
587
593
  #
588
594
  def add_write( sock )
589
- unless @writes.include?( sock )
595
+ if sock && !sock.closed? && !@writes.include?( sock )
590
596
  @writes << sock
591
597
  end
592
598
  end
@@ -630,22 +636,22 @@ module Girl
630
636
  end
631
637
  end
632
638
 
633
- src_addr = src_info[ :src_addr ]
639
+ src_id = src_info[ :id ]
634
640
 
635
641
  if src_info[ :proxy_type ] == :tunnel
636
642
  return if @tun.closed?
637
643
 
638
- src_ext = @tun_info[ :src_exts ][ src_addr ]
644
+ src_ext = @tun_info[ :src_exts ][ src_id ]
639
645
  return if src_ext.nil? || src_ext[ :dst_port ].nil?
640
646
 
641
647
  if src_ext[ :is_dst_closed ]
642
648
  # puts "debug1 2-2. after close src -> dst closed ? yes -> del src ext -> send fin2"
643
- del_src_ext( src_addr )
644
- data = [ [ 0, FIN2 ].pack( 'Q>C' ), src_addr ].join
649
+ del_src_ext( src_id )
650
+ data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
645
651
  add_tun_ctlmsg( data )
646
652
  else
647
653
  # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
648
- data = [ [ 0, FIN1 ].pack( 'Q>C' ), src_addr, [ src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>Q>' ) ].join
654
+ data = [ 0, FIN1, src_id, src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
649
655
  add_tun_ctlmsg( data )
650
656
  end
651
657
  elsif src_info[ :proxy_type ] == :direct
@@ -702,11 +708,11 @@ module Girl
702
708
  ##
703
709
  # del src ext
704
710
  #
705
- def del_src_ext( src_addr )
706
- src_ext = @tun_info[ :src_exts ].delete( src_addr )
711
+ def del_src_ext( src_id )
712
+ src_ext = @tun_info[ :src_exts ].delete( src_id )
707
713
 
708
714
  if src_ext
709
- @tun_info[ :src_addrs ].delete( src_ext[ :dst_port ] )
715
+ @tun_info[ :src_ids ].delete( src_ext[ :dst_port ] )
710
716
  end
711
717
  end
712
718
 
@@ -762,7 +768,19 @@ module Girl
762
768
 
763
769
  if data.empty?
764
770
  if src_info[ :is_closing ]
765
- close_src( src )
771
+ if @tun
772
+ if @tun.closed?
773
+ close_src( src )
774
+ elsif @tun_info[ :paused ]
775
+ @writes.delete( src )
776
+ elsif !@writes.include?( @tun )
777
+ # 转发光了,正式关闭
778
+ # puts "debug2 close src after tun empty"
779
+ close_src( src )
780
+ end
781
+ else
782
+ close_src( src )
783
+ end
766
784
  else
767
785
  @writes.delete( src )
768
786
  end
@@ -861,8 +879,8 @@ module Girl
861
879
 
862
880
  # 重传
863
881
  while @tun_info[ :resendings ].any?
864
- src_addr, pack_id = @tun_info[ :resendings ].first
865
- src_ext = @tun_info[ :src_exts ][ src_addr ]
882
+ src_id, pack_id = @tun_info[ :resendings ].first
883
+ src_ext = @tun_info[ :src_exts ][ src_id ]
866
884
 
867
885
  if src_ext
868
886
  data = src_ext[ :wmems ][ pack_id ]
@@ -893,7 +911,7 @@ module Girl
893
911
 
894
912
  # 取写前
895
913
  if @tun_info[ :caches ].any?
896
- src_addr, data = @tun_info[ :caches ].first
914
+ src_id, data = @tun_info[ :caches ].first
897
915
  from = :caches
898
916
  elsif @tun_info[ :chunks ].any?
899
917
  path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
@@ -910,24 +928,23 @@ module Girl
910
928
  caches = []
911
929
 
912
930
  until data.empty?
913
- _src_addr = data[ 0, 16 ]
914
- pack_size = data[ 16, 2 ].unpack( 'n' ).first
915
- caches << [ _src_addr, data[ 18, pack_size ] ]
916
- data = data[ ( 18 + pack_size )..-1 ]
931
+ _src_id, pack_size = data[ 0, 10 ].unpack( 'Q>n' )
932
+ caches << [ _src_id, data[ 10, pack_size ] ]
933
+ data = data[ ( 10 + pack_size )..-1 ]
917
934
  end
918
935
 
919
936
  @tun_info[ :caches ] = caches
920
- src_addr, data = caches.first
937
+ src_id, data = caches.first
921
938
  from = :caches
922
939
  elsif @tun_info[ :wbuffs ].any?
923
- src_addr, data = @tun_info[ :wbuffs ].first
940
+ src_id, data = @tun_info[ :wbuffs ].first
924
941
  from = :wbuffs
925
942
  else
926
943
  @writes.delete( tun )
927
944
  return
928
945
  end
929
946
 
930
- src_ext = @tun_info[ :src_exts ][ src_addr ]
947
+ src_ext = @tun_info[ :src_exts ][ src_id ]
931
948
 
932
949
  if src_ext
933
950
  pack_id = src_ext[ :biggest_pack_id ] + 1
@@ -937,7 +954,7 @@ module Girl
937
954
  # puts "debug1 encoded pack #{ pack_id }"
938
955
  end
939
956
 
940
- data = [ [ pack_id ].pack( 'Q>' ), src_addr, data ].join
957
+ data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
941
958
 
942
959
  begin
943
960
  tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
@@ -972,10 +989,11 @@ module Girl
972
989
  return
973
990
  end
974
991
 
975
- # puts "debug1 accept a src #{ addrinfo.inspect }"
976
- src_addr = addrinfo.to_sockaddr
992
+ id = rand( ( 2 ** 64 ) - 1 ) + 1
993
+ # puts "debug1 accept a src #{ addrinfo.inspect } #{ id }"
994
+
977
995
  @src_infos[ src ] = {
978
- src_addr: src_addr, # src地址
996
+ id: id, # id
979
997
  proxy_proto: :uncheck, # :uncheck / :http / :socks5
980
998
  proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
981
999
  dst: nil, # :direct的场合,对应的dst
@@ -999,7 +1017,7 @@ module Girl
999
1017
  #
1000
1018
  def read_src( src )
1001
1019
  begin
1002
- data = src.read_nonblock( PROXY_PACK_SIZE )
1020
+ data = src.read_nonblock( PACK_SIZE )
1003
1021
  rescue IO::WaitReadable, Errno::EINTR
1004
1022
  return
1005
1023
  rescue Exception => e
@@ -1129,8 +1147,8 @@ module Girl
1129
1147
  puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
1130
1148
  end
1131
1149
  when :tunnel
1132
- src_addr = src_info[ :src_addr ]
1133
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1150
+ src_id = src_info[ :id ]
1151
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1134
1152
 
1135
1153
  unless src_ext
1136
1154
  # puts "debug1 not found src ext"
@@ -1149,7 +1167,7 @@ module Girl
1149
1167
  data, _ = sub_http_request( data )
1150
1168
  end
1151
1169
 
1152
- add_tun_wbuff( src_addr, data )
1170
+ add_tun_wbuff( src_id, data )
1153
1171
  else
1154
1172
  # puts "debug1 remote dst not ready, save data to src rbuff"
1155
1173
  src_info[ :rbuffs ] << data
@@ -1181,7 +1199,7 @@ module Girl
1181
1199
  #
1182
1200
  def read_dst( dst )
1183
1201
  begin
1184
- data = dst.read_nonblock( PROXY_PACK_SIZE )
1202
+ data = dst.read_nonblock( PACK_SIZE )
1185
1203
  rescue IO::WaitReadable, Errno::EINTR
1186
1204
  return
1187
1205
  rescue Exception => e
@@ -1211,6 +1229,7 @@ module Girl
1211
1229
  data, addrinfo, rflags, *controls = tun.recvmsg
1212
1230
  from_addr = addrinfo.to_sockaddr
1213
1231
  now = Time.new
1232
+ @tun_info[ :last_recv_at ] = now
1214
1233
  pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
1215
1234
 
1216
1235
  if pack_id == 0
@@ -1220,7 +1239,6 @@ module Girl
1220
1239
  when TUND_PORT
1221
1240
  return if ( from_addr != @proxyd_addr ) || @tun_info[ :tund_addr ]
1222
1241
 
1223
- @tun_info[ :last_recv_at ] = now
1224
1242
  tund_port = data[ 9, 2 ].unpack( 'n' ).first
1225
1243
 
1226
1244
  # puts "debug1 got tund port #{ tund_port }"
@@ -1236,18 +1254,15 @@ module Girl
1236
1254
  when PAIRED
1237
1255
  return if from_addr != @tun_info[ :tund_addr ]
1238
1256
 
1239
- src_addr = data[ 9, 16 ]
1240
- dst_port = data[ 25, 2 ].unpack( 'n' ).first
1257
+ src_id, dst_port = data[ 9, 10 ].unpack( 'Q>n' )
1241
1258
 
1242
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1259
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1243
1260
  return if src_ext.nil? || src_ext[ :dst_port ]
1244
1261
 
1245
1262
  src = src_ext[ :src ]
1246
1263
  return if src.closed?
1247
1264
 
1248
- @tun_info[ :last_recv_at ] = now
1249
-
1250
- # puts "debug1 got paired #{ Addrinfo.new( src_addr ).inspect } #{ dst_port }"
1265
+ # puts "debug1 got paired #{ src_id } #{ dst_port }"
1251
1266
 
1252
1267
  if dst_port == 0
1253
1268
  set_is_closing( src )
@@ -1255,7 +1270,7 @@ module Girl
1255
1270
  end
1256
1271
 
1257
1272
  src_ext[ :dst_port ] = dst_port
1258
- @tun_info[ :src_addrs ][ dst_port ] = src_addr
1273
+ @tun_info[ :src_ids ][ dst_port ] = src_id
1259
1274
 
1260
1275
  src_info = @src_infos[ src ]
1261
1276
 
@@ -1271,7 +1286,7 @@ module Girl
1271
1286
  # puts "debug1 add src rbuffs to tun wbuffs"
1272
1287
 
1273
1288
  datas.each do | _data |
1274
- add_tun_wbuff( src_addr, _data )
1289
+ add_tun_wbuff( src_id, _data )
1275
1290
  end
1276
1291
  end
1277
1292
  elsif src_info[ :proxy_proto ] == :socks5
@@ -1282,14 +1297,13 @@ module Girl
1282
1297
 
1283
1298
  dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1284
1299
 
1285
- src_addr = @tun_info[ :src_addrs ][ dst_port ]
1286
- return unless src_addr
1300
+ src_id = @tun_info[ :src_ids ][ dst_port ]
1301
+ return unless src_id
1287
1302
 
1288
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1303
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1289
1304
  return unless src_ext
1290
1305
 
1291
1306
  # puts "debug2 got dest status"
1292
- @tun_info[ :last_recv_at ] = now
1293
1307
 
1294
1308
  # 更新对面发到几
1295
1309
  if biggest_dst_pack_id > src_ext[ :biggest_dst_pack_id ]
@@ -1339,20 +1353,17 @@ module Girl
1339
1353
  when MISS
1340
1354
  return if from_addr != @tun_info[ :tund_addr ]
1341
1355
 
1342
- src_addr = data[ 9, 16 ]
1343
- pack_id_begin, pack_id_end = data[ 25, 16 ].unpack( 'Q>Q>' )
1356
+ src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
1344
1357
 
1345
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1358
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1346
1359
  return unless src_ext
1347
1360
 
1348
- @tun_info[ :last_recv_at ] = now
1349
-
1350
1361
  ( pack_id_begin..pack_id_end ).each do | pack_id |
1351
1362
  send_at = src_ext[ :send_ats ][ pack_id ]
1352
1363
 
1353
1364
  if send_at
1354
1365
  break if now - send_at < STATUS_INTERVAL
1355
- @tun_info[ :resendings ] << [ src_addr, pack_id ]
1366
+ @tun_info[ :resendings ] << [ src_id, pack_id ]
1356
1367
  end
1357
1368
  end
1358
1369
 
@@ -1362,14 +1373,12 @@ module Girl
1362
1373
 
1363
1374
  dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1364
1375
 
1365
- src_addr = @tun_info[ :src_addrs ][ dst_port ]
1366
- return unless src_addr
1376
+ src_id = @tun_info[ :src_ids ][ dst_port ]
1377
+ return unless src_id
1367
1378
 
1368
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1379
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1369
1380
  return unless src_ext
1370
1381
 
1371
- @tun_info[ :last_recv_at ] = now
1372
-
1373
1382
  # puts "debug1 got fin1 #{ dst_port } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
1374
1383
  src_ext[ :is_dst_closed ] = true
1375
1384
  src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
@@ -1385,18 +1394,14 @@ module Girl
1385
1394
 
1386
1395
  dst_port = data[ 9, 2 ].unpack( 'n' ).first
1387
1396
 
1388
- src_addr = @tun_info[ :src_addrs ][ dst_port ]
1389
- return unless src_addr
1390
-
1391
- @tun_info[ :last_recv_at ] = now
1397
+ src_id = @tun_info[ :src_ids ][ dst_port ]
1398
+ return unless src_id
1392
1399
 
1393
1400
  # puts "debug1 1-2. recv fin2 -> del src ext"
1394
- del_src_ext( src_addr )
1401
+ del_src_ext( src_id )
1395
1402
  when TUND_FIN
1396
1403
  return if from_addr != @tun_info[ :tund_addr ]
1397
1404
 
1398
- @tun_info[ :last_recv_at ] = now
1399
-
1400
1405
  puts "p#{ Process.pid } #{ Time.new } recv tund fin"
1401
1406
  set_is_closing( tun )
1402
1407
  end
@@ -1408,15 +1413,13 @@ module Girl
1408
1413
 
1409
1414
  dst_port = data[ 8, 2 ].unpack( 'n' ).first
1410
1415
 
1411
- src_addr = @tun_info[ :src_addrs ][ dst_port ]
1412
- return unless src_addr
1416
+ src_id = @tun_info[ :src_ids ][ dst_port ]
1417
+ return unless src_id
1413
1418
 
1414
- src_ext = @tun_info[ :src_exts ][ src_addr ]
1419
+ src_ext = @tun_info[ :src_exts ][ src_id ]
1415
1420
  return if src_ext.nil? || src_ext[ :src ].closed?
1416
1421
  return if ( pack_id <= src_ext[ :continue_dst_pack_id ] ) || src_ext[ :pieces ].include?( pack_id )
1417
1422
 
1418
- @tun_info[ :last_recv_at ] = now
1419
-
1420
1423
  data = data[ 10..-1 ]
1421
1424
  # puts "debug2 got pack #{ pack_id }"
1422
1425
 
@@ -103,18 +103,22 @@ module Girl
103
103
  is_expired = tund_info[ :last_recv_at ] ? ( now - tund_info[ :last_recv_at ] > EXPIRE_AFTER ) : ( now - tund_info[ :created_at ] > EXPIRE_NEW )
104
104
 
105
105
  if is_expired
106
- puts "p#{ Process.pid } #{ Time.new } expire tund"
106
+ puts "p#{ Process.pid } #{ Time.new } expire tund #{ tund_info[ :port ] }"
107
107
  set_is_closing( tund )
108
- need_trigger = true
109
108
  else
109
+ data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
110
+ # puts "debug1 #{ Time.new } #{ tund_info[ :port ] } heartbeat"
111
+ add_tund_ctlmsg( tund, data )
112
+
110
113
  tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
111
114
  if dst_ext[ :dst ].closed? && ( now - dst_ext[ :last_continue_at ] > EXPIRE_AFTER )
112
115
  puts "p#{ Process.pid } #{ Time.new } expire dst ext #{ dst_local_port }"
113
116
  del_dst_ext( tund, dst_local_port )
114
- need_trigger = true
115
117
  end
116
118
  end
117
119
  end
120
+
121
+ need_trigger = true
118
122
  end
119
123
  end
120
124
 
@@ -167,6 +171,11 @@ module Girl
167
171
  puts "p#{ Process.pid } #{ Time.new } resume tund"
168
172
  tund_info[ :paused ] = false
169
173
  add_write( tund )
174
+
175
+ tund_info[ :dst_exts ].each do | _, dst_ext |
176
+ add_write( dst_ext[ :dst ] )
177
+ end
178
+
170
179
  need_trigger = true
171
180
  end
172
181
  end
@@ -183,7 +192,7 @@ module Girl
183
192
  ##
184
193
  # resolve domain
185
194
  #
186
- def resolve_domain( tund, src_addr, destination_domain_port )
195
+ def resolve_domain( tund, src_id, destination_domain_port )
187
196
  resolv_cache = @resolv_caches[ destination_domain_port ]
188
197
 
189
198
  if resolv_cache
@@ -191,7 +200,7 @@ module Girl
191
200
 
192
201
  if Time.new - created_at < RESOLV_CACHE_EXPIRE
193
202
  # puts "debug1 #{ destination_domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
194
- deal_with_destination_addr( tund, src_addr, destination_addr )
203
+ deal_with_destination_addr( tund, src_id, destination_addr )
195
204
  return
196
205
  end
197
206
 
@@ -215,7 +224,7 @@ module Girl
215
224
  @resolv_caches[ destination_domain_port ] = [ destination_addr, Time.new ]
216
225
 
217
226
  unless tund.closed?
218
- if deal_with_destination_addr( tund, src_addr, destination_addr )
227
+ if deal_with_destination_addr( tund, src_id, destination_addr )
219
228
  next_tick
220
229
  end
221
230
  end
@@ -227,7 +236,7 @@ module Girl
227
236
  ##
228
237
  # deal with destination addr
229
238
  #
230
- def deal_with_destination_addr( tund, src_addr, destination_addr )
239
+ def deal_with_destination_addr( tund, src_id, destination_addr )
231
240
  dst = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
232
241
  dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
233
242
 
@@ -239,7 +248,7 @@ module Girl
239
248
  return false
240
249
  end
241
250
 
242
- local_port = dst.local_address.ip_unpack.last
251
+ local_port = dst.local_address.ip_port
243
252
 
244
253
  @dst_infos[ dst ] = {
245
254
  local_port: local_port, # 本地端口
@@ -255,10 +264,10 @@ module Girl
255
264
  add_read( dst, :dst )
256
265
 
257
266
  tund_info = @tund_infos[ tund ]
258
- tund_info[ :dst_local_ports ][ src_addr ] = local_port
267
+ tund_info[ :dst_local_ports ][ src_id ] = local_port
259
268
  tund_info[ :dst_exts ][ local_port ] = {
260
269
  dst: dst, # dst
261
- src_addr: src_addr, # 近端src地址
270
+ src_id: src_id, # 近端src id
262
271
  wmems: {}, # 写后 pack_id => data
263
272
  send_ats: {}, # 上一次发出时间 pack_id => send_at
264
273
  biggest_pack_id: 0, # 发到几
@@ -270,7 +279,7 @@ module Girl
270
279
  last_continue_at: Time.new # 创建,或者上一次收到连续流量,或者发出新包的时间
271
280
  }
272
281
 
273
- data = [ [ 0, PAIRED ].pack( 'Q>C' ), src_addr, [ local_port ].pack( 'n' ) ].join
282
+ data = [ 0, PAIRED, src_id, local_port ].pack( 'Q>CQ>n' )
274
283
  # puts "debug1 add ctlmsg paired #{ data.inspect }"
275
284
  add_tund_ctlmsg( tund, data )
276
285
 
@@ -344,7 +353,7 @@ module Girl
344
353
  dst_info = @dst_infos[ dst ]
345
354
  dst_info[ :wbuff ] << data
346
355
 
347
- if dst_info[ :wbuff ].bytesize >= PROXY_CHUNK_SIZE
356
+ if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
348
357
  spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
349
358
  filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
350
359
  chunk_path = File.join( @dst_chunk_dir, filename )
@@ -380,7 +389,7 @@ module Girl
380
389
  # add write
381
390
  #
382
391
  def add_write( sock )
383
- unless @writes.include?( sock )
392
+ if sock && !sock.closed? && !@writes.include?( sock )
384
393
  @writes << sock
385
394
  end
386
395
  end
@@ -480,7 +489,7 @@ module Girl
480
489
  dst_ext = tund_info[ :dst_exts ].delete( dst_local_port )
481
490
 
482
491
  if dst_ext
483
- tund_info[ :dst_local_ports ].delete( dst_ext[ :src_addr ] )
492
+ tund_info[ :dst_local_ports ].delete( dst_ext[ :src_id ] )
484
493
  end
485
494
  end
486
495
 
@@ -556,7 +565,19 @@ module Girl
556
565
 
557
566
  if data.empty?
558
567
  if dst_info[ :is_closing ]
559
- close_dst( dst )
568
+ if dst_info[ :tund ].closed?
569
+ close_dst( dst )
570
+ else
571
+ tund_info = @tund_infos[ dst_info[ :tund ] ]
572
+
573
+ if tund_info[ :paused ]
574
+ @writes.delete( dst )
575
+ elsif !@writes.include?( dst_info[ :tund ] )
576
+ # 转发光了,正式关闭
577
+ # puts "debug2 close dst after tund empty"
578
+ close_dst( dst )
579
+ end
580
+ end
560
581
  else
561
582
  @writes.delete( dst )
562
583
  end
@@ -724,7 +745,7 @@ module Girl
724
745
 
725
746
  tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
726
747
  tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
727
- port = tund.local_address.ip_unpack.last
748
+ port = tund.local_address.ip_port
728
749
 
729
750
  @tunneling_tunds[ from_addr ] = tund
730
751
  @tunds[ port ] = tund
@@ -736,9 +757,8 @@ module Girl
736
757
  chunks: [], # 块队列 filename
737
758
  spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
738
759
  tun_addr: from_addr, # tun地址
739
- is_tunneled: false, # 是否已和tun打通
740
760
  dst_exts: {}, # dst额外信息 dst_addr => {}
741
- dst_local_ports: {}, # src_addr => dst_local_port
761
+ dst_local_ports: {}, # src_id => dst_local_port
742
762
  paused: false, # 是否暂停写
743
763
  resendings: [], # 重传队列 [ dst_addr, pack_id ]
744
764
  created_at: Time.new, # 创建时间
@@ -758,7 +778,7 @@ module Girl
758
778
  #
759
779
  def read_dst( dst )
760
780
  begin
761
- data = dst.read_nonblock( PROXY_PACK_SIZE )
781
+ data = dst.read_nonblock( PACK_SIZE )
762
782
  rescue IO::WaitReadable, Errno::EINTR
763
783
  return
764
784
  rescue Exception => e
@@ -800,7 +820,7 @@ module Girl
800
820
  end
801
821
  end
802
822
 
803
- tund_info[ :is_tunneled ] = true
823
+ tund_info[ :last_recv_at ] = now
804
824
  pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
805
825
 
806
826
  if pack_id == 0
@@ -808,9 +828,9 @@ module Girl
808
828
 
809
829
  case ctl_num
810
830
  when A_NEW_SOURCE
811
- src_addr = data[ 9, 16 ]
812
- dst_local_port = tund_info[ :dst_local_ports ][ src_addr ]
813
- # puts "debug1 got a new source #{ Addrinfo.new( src_addr ).inspect }"
831
+ src_id = data[ 9, 8 ].unpack( 'Q>' ).first
832
+ dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
833
+ # puts "debug1 got a new source #{ src_id }"
814
834
 
815
835
  if dst_local_port
816
836
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
@@ -821,29 +841,25 @@ module Girl
821
841
  end
822
842
 
823
843
  # puts "debug1 readd ctlmsg paired #{ dst_local_port }"
824
- data2 = [ [ 0, PAIRED ].pack( 'Q>C' ), src_addr, [ dst_local_port ].pack( 'n' ) ].join
844
+ data2 = [ 0, PAIRED, src_id, dst_local_port ].pack( 'Q>CQ>n' )
825
845
  add_tund_ctlmsg( tund, data2 )
826
846
  return
827
847
  end
828
848
 
829
- tund_info[ :last_recv_at ] = now
830
-
831
- data = data[ 25..-1 ]
849
+ data = data[ 17..-1 ]
832
850
  # puts "debug1 #{ data }"
833
851
  destination_domain_port = @custom.decode( data )
834
- resolve_domain( tund, src_addr, destination_domain_port )
852
+ resolve_domain( tund, src_id, destination_domain_port )
835
853
  when SOURCE_STATUS
836
- src_addr = data[ 9, 16 ]
837
- biggest_src_pack_id, continue_dst_pack_id = data[ 25, 16 ].unpack( 'Q>Q>' )
854
+ src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
838
855
 
839
- dst_local_port = tund_info[ :dst_local_ports ][ src_addr ]
856
+ dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
840
857
  return unless dst_local_port
841
858
 
842
859
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
843
860
  return unless dst_ext
844
861
 
845
862
  # puts "debug2 got source status"
846
- tund_info[ :last_recv_at ] = now
847
863
 
848
864
  # 更新对面发到几
849
865
  if biggest_src_pack_id > dst_ext[ :biggest_src_pack_id ]
@@ -885,7 +901,7 @@ module Girl
885
901
  break
886
902
  end
887
903
 
888
- data2 = [ [ 0, MISS ].pack( 'Q>C' ), src_addr, [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) ].join
904
+ data2 = [ 0, MISS, src_id, pack_id_begin, pack_id_end ].pack( 'Q>CQ>Q>Q>' )
889
905
  add_tund_ctlmsg( tund, data2 )
890
906
  pack_count += ( pack_id_end - pack_id_begin + 1 )
891
907
  end
@@ -896,8 +912,6 @@ module Girl
896
912
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
897
913
  return unless dst_ext
898
914
 
899
- tund_info[ :last_recv_at ] = now
900
-
901
915
  ( pack_id_begin..pack_id_end ).each do | pack_id |
902
916
  send_at = dst_ext[ :send_ats ][ pack_id ]
903
917
 
@@ -909,18 +923,15 @@ module Girl
909
923
 
910
924
  add_write( tund )
911
925
  when FIN1
912
- src_addr = data[ 9, 16 ]
913
- biggest_src_pack_id, continue_dst_pack_id = data[ 25, 16 ].unpack( 'Q>Q>' )
926
+ src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
914
927
 
915
- dst_local_port = tund_info[ :dst_local_ports ][ src_addr ]
928
+ dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
916
929
  return unless dst_local_port
917
930
 
918
931
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
919
932
  return unless dst_ext
920
933
 
921
- tund_info[ :last_recv_at ] = now
922
-
923
- # puts "debug1 got fin1 #{ Addrinfo.new( src_addr ).inspect } biggest src pack #{ biggest_src_pack_id } completed dst pack #{ continue_dst_pack_id }"
934
+ # puts "debug1 got fin1 #{ src_id } biggest src pack #{ biggest_src_pack_id } completed dst pack #{ continue_dst_pack_id }"
924
935
  dst_ext[ :is_src_closed ] = true
925
936
  dst_ext[ :biggest_src_pack_id ] = biggest_src_pack_id
926
937
  release_wmems( dst_ext, continue_dst_pack_id )
@@ -931,36 +942,31 @@ module Girl
931
942
  set_is_closing( dst_ext[ :dst ] )
932
943
  end
933
944
  when FIN2
934
- src_addr = data[ 9, 16 ]
945
+ src_id = data[ 9, 8 ].unpack( 'Q>' ).first
935
946
 
936
- dst_local_port = tund_info[ :dst_local_ports ][ src_addr ]
947
+ dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
937
948
  return unless dst_local_port
938
949
 
939
- tund_info[ :last_recv_at ] = now
940
-
941
950
  # puts "debug1 1-2. recv fin2 -> del dst ext"
942
951
  del_dst_ext( tund, dst_local_port )
943
952
  when TUN_FIN
944
953
  puts "p#{ Process.pid } #{ Time.new } recv tun fin"
945
- tund_info[ :last_recv_at ] = now
946
954
  set_is_closing( tund )
947
955
  end
948
956
 
949
957
  return
950
958
  end
951
959
 
952
- src_addr = data[ 8, 16 ]
960
+ src_id = data[ 8, 8 ].unpack( 'Q>' ).first
953
961
 
954
- dst_local_port = tund_info[ :dst_local_ports ][ src_addr ]
962
+ dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
955
963
  return unless dst_local_port
956
964
 
957
965
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
958
966
  return if dst_ext.nil? || dst_ext[ :dst ].closed?
959
967
  return if ( pack_id <= dst_ext[ :continue_src_pack_id ] ) || dst_ext[ :pieces ].include?( pack_id )
960
968
 
961
- tund_info[ :last_recv_at ] = now
962
-
963
- data = data[ 24..-1 ]
969
+ data = data[ 16..-1 ]
964
970
  # puts "debug2 got pack #{ pack_id }"
965
971
 
966
972
  if pack_id <= CONFUSE_UNTIL
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '0.64.1'.freeze
2
+ VERSION = '0.69.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.64.1
4
+ version: 0.69.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-06-22 00:00:00.000000000 Z
11
+ date: 2020-06-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: while internet is evil, here's a girl.
14
14
  email: