girl 4.2.0 → 4.7.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: 3e6e47afe34c123e702c013b4b2f71c3ef836902edd8ab7508b9fe666c2052c7
4
- data.tar.gz: 673a5b27d4863a9c1daa34abc94536e7c7d68549363071e73d9f57a1db4056bc
3
+ metadata.gz: e06e25ddc6594959cceb39bd5d4ad420941dfaeec6866a86d7817e974cf9bc2f
4
+ data.tar.gz: 6d8016cd3a42b0cf611bad16759e34f130f193bb9e68a88f5f8b80597bd62dc9
5
5
  SHA512:
6
- metadata.gz: 1c105f47f7cfd38572adef3c40be156e88fe1b767d6144cd923154e57c19a5508fbaaaff325e2c252f8371ca97c621a8a6b5ce020381c8738b2529bade9840b9
7
- data.tar.gz: 3b13786e8062bad65c975e48340c2b1deae88be8965862543bd644783b3ecbab6b446c2e872a64169a8380fef0679d7c504c6fdbfbe08995d5ae2662b67319b8
6
+ metadata.gz: d1d49eddf9232d1af3cbf4d9426a257cdaf48003fe9a1b08fdca5b1caaba5497eda97b3092b49191c228868026d70843839ac711b1a70201832901062caeecf8
7
+ data.tar.gz: aa1f7dc236106913f5ea2c061fd5b54c7675da04e0db71fc2d200f1665213c8c33b5ed78a4959111453b19189562d0ba233cbf3cc71e32fb3575e7199050b77f
data/lib/girl/head.rb CHANGED
@@ -1,13 +1,15 @@
1
1
  module Girl
2
- READ_SIZE = 1024 * 1024 # atun, btun一次读多少
2
+ READ_SIZE = 1024 * 1024 # 一次读多少
3
3
  WBUFF_LIMIT = 50 * 1024 * 1024 # 写前上限,超过上限暂停读
4
4
  RESUME_BELOW = WBUFF_LIMIT / 2 # 降到多少以下恢复读
5
+ CHUNK_SIZE = 65535 # 按块加解密,块尺寸上限,不超过65535
5
6
  EXPIRE_NEW = 5 # 多久没有建立通道,过期
6
- EXPIRE_AFTER = 300 # 多久没有新流量,过期
7
+ EXPIRE_CONNECTING = 2 # 连接中,多久没连上过期
8
+ EXPIRE_AFTER = 86400 # 多久没有新流量,过期
7
9
  EXPIRE_CTL = 86400 # 多久没有ctlmsg来,过期
8
10
  RESET_TRAFF_DAY = 1 # 流量计数重置日,0为不重置
9
11
  CHECK_TRAFF_INTERVAL = 86400 # 检查今天是否是流量计数重置日间隔
10
- CHECK_EXPIRE_INTERVAL = 5 # 检查过期间隔
12
+ CHECK_EXPIRE_INTERVAL = 1 # 检查过期间隔
11
13
  CHECK_RESUME_INTERVAL = 1 # 检查恢复读间隔
12
14
  RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
13
15
  RESEND_LIMIT = 5 # ctlmsg重传次数
@@ -52,7 +54,9 @@ EOF
52
54
  READ_SIZE
53
55
  WBUFF_LIMIT
54
56
  RESUME_BELOW
57
+ CHUNK_SIZE
55
58
  EXPIRE_NEW
59
+ EXPIRE_CONNECTING
56
60
  EXPIRE_AFTER
57
61
  EXPIRE_CTL
58
62
  RESET_TRAFF_DAY
@@ -7,7 +7,6 @@ module Girl
7
7
  def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
8
8
  @proxyd_host = proxyd_host
9
9
  @proxyd_port = proxyd_port
10
- @proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
11
10
  @directs = directs
12
11
  @remotes = remotes
13
12
  @custom = Girl::ProxyCustom.new( im )
@@ -431,8 +430,7 @@ module Girl
431
430
  return if src.closed?
432
431
  src_info = @src_infos[ src ]
433
432
 
434
- if ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) \
435
- || ( ( ip_info.ip_address == @proxyd_host ) && ( src_info[ :destination_port ] == @proxyd_port ) ) then
433
+ if ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) then
436
434
  puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
437
435
  add_closing_src( src )
438
436
  return
@@ -507,19 +505,33 @@ module Girl
507
505
  if @ctl && !@ctl.closed? then
508
506
  last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
509
507
 
510
- if now - last_recv_at >= EXPIRE_AFTER then
511
- puts "p#{ Process.pid } #{ Time.new } expire ctl"
512
- @ctl_info[ :closing ] = true
513
- next_tick
508
+ if now - last_recv_at >= EXPIRE_CTL then
509
+ puts "p#{ Process.pid } #{ Time.new } expire ctl #{ EXPIRE_CTL }"
510
+ set_ctl_closing
514
511
  end
515
512
  end
516
513
 
517
514
  @src_infos.each do | src, src_info |
518
515
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
519
516
  last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
520
- expire_after = ( src_info[ :dst ] || src_info[ :atun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
521
517
 
522
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
518
+ if src_info[ :dst ] then
519
+ if src_info[ :dst_connected ] then
520
+ expire_after = EXPIRE_AFTER
521
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
522
+ else
523
+ expire_after = EXPIRE_CONNECTING
524
+ is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
525
+ end
526
+ elsif src_info[ :atun ] then
527
+ expire_after = EXPIRE_AFTER
528
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
529
+ else
530
+ expire_after = EXPIRE_NEW
531
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
532
+ end
533
+
534
+ if is_expire then
523
535
  puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
524
536
  add_closing_src( src )
525
537
 
@@ -548,7 +560,7 @@ module Girl
548
560
  if !dst.closed? then
549
561
  dst_info = @dst_infos[ dst ]
550
562
 
551
- if dst_info[ :wbuff ].size < RESUME_BELOW then
563
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
552
564
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
553
565
  add_resume_src( src )
554
566
  end
@@ -559,7 +571,7 @@ module Girl
559
571
  if atun && !atun.closed? then
560
572
  atun_info = @atun_infos[ atun ]
561
573
 
562
- if atun_info[ :wbuff ].size < RESUME_BELOW then
574
+ if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
563
575
  puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
564
576
  add_resume_src( src )
565
577
  end
@@ -574,7 +586,7 @@ module Girl
574
586
  if src && !src.closed? then
575
587
  src_info = @src_infos[ src ]
576
588
 
577
- if src_info[ :wbuff ].size < RESUME_BELOW then
589
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
578
590
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
579
591
  add_resume_dst( dst )
580
592
  end
@@ -588,7 +600,7 @@ module Girl
588
600
  if src && !src.closed? then
589
601
  src_info = @src_infos[ src ]
590
602
 
591
- if src_info[ :wbuff ].size < RESUME_BELOW then
603
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
592
604
  puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
593
605
  add_resume_btun( btun )
594
606
  end
@@ -615,6 +627,7 @@ module Girl
615
627
 
616
628
  if resend >= RESEND_LIMIT then
617
629
  @ctl_info[ :resends ].delete( key )
630
+ set_ctl_closing
618
631
  break
619
632
  end
620
633
 
@@ -632,13 +645,14 @@ module Girl
632
645
  domain = src_info[ :destination_domain ]
633
646
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
634
647
  dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
648
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
635
649
 
636
650
  begin
637
651
  dst.connect_nonblock( destination_addr )
638
652
  rescue IO::WaitWritable
639
653
  # connect nonblock 必抛 wait writable
640
654
  rescue Exception => e
641
- puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }, close src"
655
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
642
656
  dst.close
643
657
  add_closing_src( src )
644
658
  return
@@ -653,9 +667,9 @@ module Girl
653
667
  }
654
668
 
655
669
  @dst_infos[ dst ] = dst_info
656
- add_read( dst, :dst )
657
670
  src_info[ :proxy_type ] = :direct
658
671
  src_info[ :dst ] = dst
672
+ src_info[ :dst_created_at ] = Time.new
659
673
 
660
674
  if src_info[ :proxy_proto ] == :http then
661
675
  if src_info[ :is_connect ] then
@@ -664,11 +678,13 @@ module Girl
664
678
  elsif src_info[ :rbuff ] then
665
679
  # puts "debug move src.rbuff to dst.wbuff"
666
680
  dst_info[ :wbuff ] << src_info[ :rbuff ]
667
- add_write( dst )
668
681
  end
669
682
  elsif src_info[ :proxy_proto ] == :socks5 then
670
683
  add_socks5_conn_reply( src )
671
684
  end
685
+
686
+ add_read( dst, :dst )
687
+ add_write( dst )
672
688
  end
673
689
 
674
690
  ##
@@ -684,7 +700,10 @@ module Girl
684
700
  @ctl = ctl
685
701
  add_read( ctl, :ctl )
686
702
 
703
+ ctld_port = @proxyd_port + 5.times.to_a.sample
704
+ ctld_addr = Socket.sockaddr_in( ctld_port, @proxyd_host )
687
705
  @ctl_info = {
706
+ ctld_addr: ctld_addr, # ctld地址
688
707
  resends: ConcurrentHash.new, # key => count
689
708
  atund_addr: nil, # atund地址,src->dst
690
709
  btund_addr: nil, # btund地址,dst->src
@@ -694,7 +713,7 @@ module Girl
694
713
  }
695
714
 
696
715
  hello = @custom.hello
697
- puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect }"
716
+ puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect } #{ ctld_port }"
698
717
  key = [ HELLO ].pack( 'C' )
699
718
  add_ctlmsg( key, hello )
700
719
  end
@@ -704,6 +723,7 @@ module Girl
704
723
  #
705
724
  def new_a_redir( redir_port )
706
725
  redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
726
+ redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
707
727
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
708
728
 
709
729
  if RUBY_PLATFORM.include?( 'linux' ) then
@@ -730,23 +750,25 @@ module Girl
730
750
 
731
751
  # puts "debug new atun and btun"
732
752
  atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
753
+ atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
733
754
 
734
755
  begin
735
756
  atun.connect_nonblock( @ctl_info[ :atund_addr ] )
736
757
  rescue IO::WaitWritable
737
758
  rescue Exception => e
738
- puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
759
+ puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
739
760
  atun.close
740
761
  return
741
762
  end
742
763
 
743
764
  btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
765
+ btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
744
766
 
745
767
  begin
746
768
  btun.connect_nonblock( @ctl_info[ :btund_addr ] )
747
769
  rescue IO::WaitWritable
748
770
  rescue Exception => e
749
- puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
771
+ puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
750
772
  btun.close
751
773
  return
752
774
  end
@@ -755,7 +777,7 @@ module Girl
755
777
  atun_wbuff = [ dst_id ].pack( 'n' )
756
778
 
757
779
  until src_info[ :rbuff ].empty? do
758
- data = src_info[ :rbuff ][ 0, 65535 ]
780
+ data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
759
781
  data_size = data.bytesize
760
782
  # puts "debug move src.rbuff #{ data_size } to atun.wbuff"
761
783
  atun_wbuff << pack_a_chunk( data )
@@ -776,7 +798,8 @@ module Girl
776
798
  domain: domain, # 目的地
777
799
  wbuff: btun_wbuff, # 写前
778
800
  rbuff: '', # 暂存当前块没收全的流量
779
- wait_bytes: 0 # 还差多少字节收全当前块
801
+ wait_bytes: 0, # 还差多少字节收全当前块
802
+ lbuff: '' # 流量截断在长度前缀处
780
803
  }
781
804
 
782
805
  src_info[ :dst_id ] = dst_id
@@ -808,7 +831,6 @@ module Girl
808
831
  # pack a chunk
809
832
  #
810
833
  def pack_a_chunk( data )
811
- # puts "debug pack a chunk"
812
834
  data = @custom.encode( data )
813
835
  "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
814
836
  end
@@ -866,7 +888,7 @@ module Girl
866
888
  data = @custom.encode( data )
867
889
 
868
890
  begin
869
- @ctl.sendmsg( data, 0, @proxyd_addr )
891
+ @ctl.sendmsg( data, 0, @ctl_info[ :ctld_addr ] )
870
892
  @ctl_info[ :last_sent_at ] = Time.new
871
893
  rescue Exception => e
872
894
  puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
@@ -886,6 +908,15 @@ module Girl
886
908
  add_write( atun )
887
909
  end
888
910
 
911
+ ##
912
+ # set ctl closing
913
+ #
914
+ def set_ctl_closing
915
+ return if @ctl.closed?
916
+ @ctl_info[ :closing ] = true
917
+ next_tick
918
+ end
919
+
889
920
  ##
890
921
  # set dst closing write
891
922
  #
@@ -929,7 +960,7 @@ module Girl
929
960
  # read dotr
930
961
  #
931
962
  def read_dotr( dotr )
932
- dotr.read_nonblock( 65535 )
963
+ dotr.read_nonblock( READ_SIZE )
933
964
 
934
965
  if @ctl_info && @ctl_info[ :closing ] then
935
966
  send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
@@ -993,6 +1024,8 @@ module Girl
993
1024
  is_connect: true, # 代理协议是http的场合,是否是CONNECT
994
1025
  rbuff: '', # 读到的流量
995
1026
  dst: nil, # :direct的场合,对应的dst
1027
+ dst_created_at: nil, # :direct的场合,对应的dst的创建时间
1028
+ dst_connected: false, # :direct的场合,对应的dst是否已连接
996
1029
  ctl: nil, # :tunnel的场合,对应的ctl
997
1030
  atun: nil, # :tunnel的场合,对应的atun
998
1031
  btun: nil, # :tunnel的场合,对应的btun
@@ -1028,7 +1061,7 @@ module Girl
1028
1061
 
1029
1062
  case ctl_num
1030
1063
  when TUND_PORT then
1031
- return if @ctl_info[ :atund_addr ] || data.size != 5
1064
+ return if @ctl_info[ :atund_addr ] || data.bytesize != 5
1032
1065
  atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
1033
1066
  puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
1034
1067
  @ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
@@ -1042,14 +1075,14 @@ module Girl
1042
1075
  @pending_srcs.clear
1043
1076
  end
1044
1077
  when PAIRED then
1045
- return if data.size != 11
1078
+ return if data.bytesize != 11
1046
1079
  src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
1047
1080
  # puts "debug got paired #{ src_id } #{ dst_id }"
1048
1081
  @ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
1049
1082
  @ctl_info[ :last_recv_at ] = Time.new
1050
1083
  new_tuns( src_id, dst_id )
1051
1084
  when UNKNOWN_CTL_ADDR then
1052
- puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
1085
+ puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
1053
1086
  close_ctl( ctl )
1054
1087
  end
1055
1088
  end
@@ -1066,7 +1099,7 @@ module Girl
1066
1099
  src_info = @src_infos[ src ]
1067
1100
 
1068
1101
  begin
1069
- data = src.read_nonblock( 65535 )
1102
+ data = src.read_nonblock( CHUNK_SIZE )
1070
1103
  rescue IO::WaitReadable
1071
1104
  print 'r'
1072
1105
  return
@@ -1248,7 +1281,7 @@ module Girl
1248
1281
  src = dst_info[ :src ]
1249
1282
 
1250
1283
  begin
1251
- data = dst.read_nonblock( 65535 )
1284
+ data = dst.read_nonblock( CHUNK_SIZE )
1252
1285
  rescue IO::WaitReadable
1253
1286
  print 'r'
1254
1287
  return
@@ -1289,22 +1322,44 @@ module Girl
1289
1322
  end
1290
1323
 
1291
1324
  until data.empty? do
1292
- rbuff = btun_info[ :rbuff ]
1293
1325
  wait_bytes = btun_info[ :wait_bytes ]
1294
1326
 
1295
1327
  if wait_bytes > 0 then
1296
1328
  len = wait_bytes
1297
1329
  # puts "debug wait bytes #{ len }"
1298
1330
  else
1299
- if data.bytesize <= 2 then
1300
- # puts "debug unexpect data length #{ data.bytesize }"
1301
- close_btun( btun )
1302
- return
1303
- end
1331
+ lbuff = btun_info[ :lbuff ]
1332
+
1333
+ if lbuff.empty? then
1334
+ # 长度缓存为空,从读到的流量里取长度
1335
+ # 两个字节以下,记进长度缓存
1336
+ if data.bytesize <= 2 then
1337
+ # puts "debug set btun.lbuff #{ data.inspect }"
1338
+ btun_info[ :lbuff ] = data
1339
+ return
1340
+ end
1341
+
1342
+ len = data[ 0, 2 ].unpack( 'n' ).first
1343
+ data = data[ 2..-1 ]
1344
+ elsif lbuff.bytesize == 1 then
1345
+ # 长度缓存记有一个字节,补一个字节
1346
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
1347
+
1348
+ if data.bytesize == 1 then
1349
+ # puts "debug add btun.lbuff a byte #{ data.inspect }"
1350
+ btun_info[ :lbuff ] = lbuff
1351
+ return
1352
+ end
1304
1353
 
1305
- len = data[ 0, 2 ].unpack( 'n' ).first
1306
- # puts "debug read len #{ len }"
1307
- data = data[ 2..-1 ]
1354
+ # 使用长度缓存
1355
+ len = lbuff.unpack( 'n' ).first
1356
+ btun_info[ :lbuff ].clear
1357
+ data = data[ 1..-1 ]
1358
+ else
1359
+ # 使用长度缓存
1360
+ len = lbuff.unpack( 'n' ).first
1361
+ btun_info[ :lbuff ].clear
1362
+ end
1308
1363
  end
1309
1364
 
1310
1365
  chunk = data[ 0, len ]
@@ -1312,7 +1367,7 @@ module Girl
1312
1367
 
1313
1368
  if chunk_size == len then
1314
1369
  # 取完整了
1315
- chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
1370
+ chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
1316
1371
  # puts "debug decode and add src.wbuff #{ chunk.bytesize }"
1317
1372
  add_src_wbuff( src, chunk )
1318
1373
  btun_info[ :rbuff ].clear
@@ -1391,6 +1446,12 @@ module Girl
1391
1446
 
1392
1447
  dst_info = @dst_infos[ dst ]
1393
1448
  src = dst_info[ :src ]
1449
+ src_info = @src_infos[ src ]
1450
+
1451
+ unless src.closed? then
1452
+ src_info[ :dst_connected ] = true
1453
+ end
1454
+
1394
1455
  data = dst_info[ :wbuff ]
1395
1456
 
1396
1457
  # 写前为空,处理关闭写
@@ -1421,7 +1482,6 @@ module Girl
1421
1482
  dst_info[ :wbuff ] = data
1422
1483
 
1423
1484
  unless src.closed? then
1424
- src_info = @src_infos[ src ]
1425
1485
  src_info[ :last_sent_at ] = Time.new
1426
1486
  end
1427
1487
  end
@@ -28,7 +28,7 @@ module Girl
28
28
  dotr, dotw = IO.pipe
29
29
  @dotw = dotw
30
30
  add_read( dotr, :dotr )
31
- new_a_ctld( proxyd_port )
31
+ new_ctlds( proxyd_port )
32
32
  new_a_infod( infod_port )
33
33
  end
34
34
 
@@ -306,6 +306,7 @@ module Girl
306
306
  #
307
307
  def deal_with_destination_addr( ctl_addr, src_id, destination_addr, domain_port )
308
308
  dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
309
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
309
310
 
310
311
  begin
311
312
  dst.connect_nonblock( destination_addr )
@@ -324,6 +325,7 @@ module Girl
324
325
  ctl_addr: ctl_addr, # 对应ctl
325
326
  im: ctl_info[ :im ], # 标识
326
327
  domain_port: domain_port, # 目的地和端口
328
+ connected: false, # 是否已连接
327
329
  rbuff: '', # 对应的tun没准备好,暂存读到的流量
328
330
  atun: nil, # 对应的atun
329
331
  btun: nil, # 对应的btun
@@ -336,13 +338,14 @@ module Girl
336
338
  }
337
339
 
338
340
  add_read( dst, :dst )
341
+ add_write( dst )
339
342
 
340
343
  ctl_info[ :dst_ids ][ src_id ] = dst_id
341
344
  ctl_info[ :dsts ][ dst_id ] = dst
342
345
 
343
346
  data = [ PAIRED, src_id, dst_id ].pack( 'CQ>n' )
344
347
  # puts "debug add ctlmsg paired #{ src_id } #{ dst_id }"
345
- send_ctlmsg( data, ctl_addr )
348
+ send_ctlmsg( ctl_info[ :ctld ], data, ctl_addr )
346
349
  end
347
350
 
348
351
  ##
@@ -404,11 +407,17 @@ module Girl
404
407
  end
405
408
 
406
409
  @dst_infos.each do | dst, dst_info |
407
- last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
408
- last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
409
- expire_after = dst_info[ :btun ] ? EXPIRE_AFTER : EXPIRE_NEW
410
+ if dst_info[ :connected ] then
411
+ last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
412
+ last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
413
+ expire_after = EXPIRE_AFTER
414
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
415
+ else
416
+ expire_after = EXPIRE_CONNECTING
417
+ is_expire = ( now - dst_info[ :created_at ] >= expire_after )
418
+ end
410
419
 
411
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
420
+ if is_expire then
412
421
  puts "p#{ Process.pid } #{ Time.new } expire dst #{ expire_after } #{ dst_info[ :domain_port ] }"
413
422
 
414
423
  unless @closing_dsts.include?( dst ) then
@@ -436,7 +445,7 @@ module Girl
436
445
  if btun && !btun.closed? then
437
446
  btun_info = @btun_infos[ btun ]
438
447
 
439
- if btun_info[ :wbuff ].size < RESUME_BELOW then
448
+ if btun_info[ :wbuff ].bytesize < RESUME_BELOW then
440
449
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
441
450
  add_resume_dst( dst )
442
451
  end
@@ -450,7 +459,7 @@ module Girl
450
459
  if dst && !dst.closed? then
451
460
  dst_info = @dst_infos[ dst ]
452
461
 
453
- if dst_info[ :wbuff ].size < RESUME_BELOW then
462
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
454
463
  puts "p#{ Process.pid } #{ Time.new } resume atun #{ atun_info[ :domain_port ] }"
455
464
  add_resume_atun( atun )
456
465
  end
@@ -479,18 +488,6 @@ module Girl
479
488
  end
480
489
  end
481
490
 
482
- ##
483
- # new a ctld
484
- #
485
- def new_a_ctld( proxyd_port )
486
- ctld = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
487
- ctld.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
488
- ctld.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
489
- puts "p#{ Process.pid } #{ Time.new } ctld bind on #{ proxyd_port }"
490
- add_read( ctld, :ctld )
491
- @ctld = ctld
492
- end
493
-
494
491
  ##
495
492
  # new a infod
496
493
  #
@@ -507,11 +504,26 @@ module Girl
507
504
  #
508
505
  def new_a_tund
509
506
  tund = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
507
+ tund.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
510
508
  tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
511
509
  tund.listen( 127 )
512
510
  tund
513
511
  end
514
512
 
513
+ ##
514
+ # new ctlds
515
+ #
516
+ def new_ctlds( proxyd_port )
517
+ 5.times do | i |
518
+ ctld_port = proxyd_port + i
519
+ ctld = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
520
+ ctld.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
521
+ ctld.bind( Socket.sockaddr_in( ctld_port, '0.0.0.0' ) )
522
+ puts "p#{ Process.pid } #{ Time.new } ctld bind on #{ ctld_port }"
523
+ add_read( ctld, :ctld )
524
+ end
525
+ end
526
+
515
527
  ##
516
528
  # next tick
517
529
  #
@@ -523,7 +535,6 @@ module Girl
523
535
  # pack a chunk
524
536
  #
525
537
  def pack_a_chunk( data )
526
- # puts "debug pack a chunk"
527
538
  data = @custom.encode( data )
528
539
  "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
529
540
  end
@@ -572,11 +583,11 @@ module Girl
572
583
  ##
573
584
  # send ctlmsg
574
585
  #
575
- def send_ctlmsg( data, to_addr )
586
+ def send_ctlmsg( ctld, data, to_addr )
576
587
  data = @custom.encode( data )
577
588
 
578
589
  begin
579
- @ctld.sendmsg( data, 0, to_addr )
590
+ ctld.sendmsg( data, 0, to_addr )
580
591
  rescue Exception => e
581
592
  puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
582
593
  end
@@ -610,7 +621,7 @@ module Girl
610
621
  # read dotr
611
622
  #
612
623
  def read_dotr( dotr )
613
- dotr.read_nonblock( 65535 )
624
+ dotr.read_nonblock( READ_SIZE )
614
625
 
615
626
  if @deleting_ctl_infos.any? then
616
627
  @deleting_ctl_infos.each { | ctl_addr | del_ctl_info( ctl_addr ) }
@@ -656,7 +667,7 @@ module Girl
656
667
  if ctl_info then
657
668
  atund_port, btund_port = ctl_info[ :atund_port ], ctl_info[ :btund_port ]
658
669
  else
659
- return if data.size <= 1
670
+ return if data.bytesize <= 1
660
671
  im = data[ 1..-1 ]
661
672
  result = @custom.check( im, addrinfo )
662
673
 
@@ -688,6 +699,7 @@ module Girl
688
699
  }
689
700
 
690
701
  @ctl_infos[ ctl_addr ] = {
702
+ ctld: ctld, # 对应的ctld
691
703
  addrinfo: addrinfo, # 地址
692
704
  im: im, # 标识
693
705
  atund: atund, # 对应atund,src->dst
@@ -703,21 +715,21 @@ module Girl
703
715
  end
704
716
 
705
717
  data2 = [ TUND_PORT, atund_port, btund_port ].pack( 'Cnn' )
706
- send_ctlmsg( data2, ctl_addr )
718
+ send_ctlmsg( ctld, data2, ctl_addr )
707
719
  when A_NEW_SOURCE then
708
720
  unless ctl_info then
709
- send_ctlmsg( [ UNKNOWN_CTL_ADDR ].pack( 'C' ), addrinfo )
721
+ send_ctlmsg( ctld, [ UNKNOWN_CTL_ADDR ].pack( 'C' ), addrinfo )
710
722
  return
711
723
  end
712
724
 
713
- return if data.size <= 9
725
+ return if data.bytesize <= 9
714
726
  src_id = data[ 1, 8 ].unpack( 'Q>' ).first
715
727
  dst_id = ctl_info[ :dst_ids ][ src_id ]
716
728
 
717
729
  if dst_id then
718
730
  data2 = [ PAIRED, src_id, dst_id ].pack( 'CQ>n' )
719
731
  # puts "debug dst id exist, send ctlmsg paired #{ src_id } #{ dst_id }"
720
- send_ctlmsg( data2, ctl_addr )
732
+ send_ctlmsg( ctld, data2, ctl_addr )
721
733
  return
722
734
  end
723
735
 
@@ -773,7 +785,7 @@ module Girl
773
785
  btun = dst_info[ :btun ]
774
786
 
775
787
  begin
776
- data = dst.read_nonblock( 65535 )
788
+ data = dst.read_nonblock( CHUNK_SIZE )
777
789
  rescue IO::WaitReadable
778
790
  print 'r'
779
791
  return
@@ -826,7 +838,8 @@ module Girl
826
838
  dst: nil, # 对应dst
827
839
  domain_port: nil, # dst的目的地和端口
828
840
  rbuff: '', # 暂存当前块没收全的流量
829
- wait_bytes: 0 # 还差多少字节收全当前块
841
+ wait_bytes: 0, # 还差多少字节收全当前块
842
+ lbuff: '' # 流量截断在长度前缀处
830
843
  }
831
844
 
832
845
  add_read( atun, :atun )
@@ -922,22 +935,44 @@ module Girl
922
935
  end
923
936
 
924
937
  until data.empty? do
925
- rbuff = atun_info[ :rbuff ]
926
938
  wait_bytes = atun_info[ :wait_bytes ]
927
939
 
928
940
  if wait_bytes > 0 then
929
941
  len = wait_bytes
930
942
  # puts "debug wait bytes #{ len }"
931
943
  else
932
- if data.bytesize <= 2 then
933
- # puts "debug unexpect data length #{ data.bytesize }"
934
- close_atun( atun )
935
- return
936
- end
944
+ lbuff = atun_info[ :lbuff ]
945
+
946
+ if lbuff.empty? then
947
+ # 长度缓存为空,从读到的流量里取长度
948
+ # 两个字节以下,记进长度缓存
949
+ if data.bytesize <= 2 then
950
+ # puts "debug set atun.lbuff #{ data.inspect }"
951
+ atun_info[ :lbuff ] = data
952
+ return
953
+ end
937
954
 
938
- len = data[ 0, 2 ].unpack( 'n' ).first
939
- # puts "debug read len #{ len }"
940
- data = data[ 2..-1 ]
955
+ len = data[ 0, 2 ].unpack( 'n' ).first
956
+ data = data[ 2..-1 ]
957
+ elsif lbuff.bytesize == 1 then
958
+ # 长度缓存记有一个字节,补一个字节
959
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
960
+
961
+ if data.bytesize == 1 then
962
+ # puts "debug add atun.lbuff a byte #{ data.inspect }"
963
+ atun_info[ :lbuff ] = lbuff
964
+ return
965
+ end
966
+
967
+ # 使用长度缓存
968
+ len = lbuff.unpack( 'n' ).first
969
+ atun_info[ :lbuff ].clear
970
+ data = data[ 1..-1 ]
971
+ else
972
+ # 使用长度缓存
973
+ len = lbuff.unpack( 'n' ).first
974
+ atun_info[ :lbuff ].clear
975
+ end
941
976
  end
942
977
 
943
978
  chunk = data[ 0, len ]
@@ -945,7 +980,7 @@ module Girl
945
980
 
946
981
  if chunk_size == len then
947
982
  # 取完整了
948
- chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
983
+ chunk = @custom.decode( "#{ atun_info[ :rbuff ] }#{ chunk }" )
949
984
  # puts "debug decode and add dst.wbuff #{ chunk.bytesize }"
950
985
  add_dst_wbuff( dst, chunk )
951
986
  atun_info[ :rbuff ].clear
@@ -1022,7 +1057,7 @@ module Girl
1022
1057
  data2 = ''
1023
1058
 
1024
1059
  until dst_info[ :rbuff ].empty? do
1025
- _data = dst_info[ :rbuff ][ 0, 65535 ]
1060
+ _data = dst_info[ :rbuff ][ 0, CHUNK_SIZE ]
1026
1061
  data_size = _data.bytesize
1027
1062
  # puts "debug move dst.rbuff to btun.wbuff"
1028
1063
  data2 << pack_a_chunk( _data )
@@ -1045,6 +1080,7 @@ module Girl
1045
1080
  end
1046
1081
 
1047
1082
  dst_info = @dst_infos[ dst ]
1083
+ dst_info[ :connected ] = true
1048
1084
  atun = dst_info[ :atun ]
1049
1085
  data = dst_info[ :wbuff ]
1050
1086
 
data/lib/girl/relay.rb CHANGED
@@ -4,6 +4,7 @@ require 'girl/head'
4
4
  require 'girl/proxy_custom'
5
5
  require 'girl/relay_worker'
6
6
  require 'girl/version'
7
+ require 'ipaddr'
7
8
  require 'json'
8
9
  require 'socket'
9
10
 
@@ -520,8 +520,8 @@ module Girl
520
520
  if @ctl && !@ctl.closed? then
521
521
  last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
522
522
 
523
- if now - last_recv_at >= EXPIRE_AFTER then
524
- puts "p#{ Process.pid } #{ Time.new } expire ctl"
523
+ if now - last_recv_at >= EXPIRE_CTL then
524
+ puts "p#{ Process.pid } #{ Time.new } expire ctl #{ EXPIRE_CTL }"
525
525
  @ctl_info[ :closing ] = true
526
526
  next_tick
527
527
  end
@@ -537,9 +537,24 @@ module Girl
537
537
  @src_infos.each do | src, src_info |
538
538
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
539
539
  last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
540
- expire_after = ( src_info[ :dst ] || src_info[ :tun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
541
540
 
542
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
541
+ if src_info[ :dst ] then
542
+ if src_info[ :dst_connected ] then
543
+ expire_after = EXPIRE_AFTER
544
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
545
+ else
546
+ expire_after = EXPIRE_CONNECTING
547
+ is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
548
+ end
549
+ elsif src_info[ :atun ] then
550
+ expire_after = EXPIRE_AFTER
551
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
552
+ else
553
+ expire_after = EXPIRE_NEW
554
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
555
+ end
556
+
557
+ if is_expire then
543
558
  puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
544
559
  add_closing_src( src )
545
560
 
@@ -568,7 +583,7 @@ module Girl
568
583
  if !dst.closed? then
569
584
  dst_info = @dst_infos[ dst ]
570
585
 
571
- if dst_info[ :wbuff ].size < RESUME_BELOW then
586
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
572
587
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
573
588
  add_resume_src( src )
574
589
  end
@@ -579,7 +594,7 @@ module Girl
579
594
  if atun && !atun.closed? then
580
595
  atun_info = @atun_infos[ atun ]
581
596
 
582
- if atun_info[ :wbuff ].size < RESUME_BELOW then
597
+ if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
583
598
  puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
584
599
  add_resume_src( src )
585
600
  end
@@ -594,7 +609,7 @@ module Girl
594
609
  if src && !src.closed? then
595
610
  src_info = @src_infos[ src ]
596
611
 
597
- if src_info[ :wbuff ].size < RESUME_BELOW then
612
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
598
613
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
599
614
  add_resume_dst( dst )
600
615
  end
@@ -608,7 +623,7 @@ module Girl
608
623
  if src && !src.closed? then
609
624
  src_info = @src_infos[ src ]
610
625
 
611
- if src_info[ :wbuff ].size < RESUME_BELOW then
626
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
612
627
  puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
613
628
  add_resume_btun( btun )
614
629
  end
@@ -652,14 +667,14 @@ module Girl
652
667
  domain = src_info[ :destination_domain ]
653
668
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
654
669
  dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
655
- dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
670
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
656
671
 
657
672
  begin
658
673
  dst.connect_nonblock( destination_addr )
659
674
  rescue IO::WaitWritable
660
675
  # connect nonblock 必抛 wait writable
661
676
  rescue Exception => e
662
- puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }, close src"
677
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
663
678
  dst.close
664
679
  add_closing_src( src )
665
680
  return
@@ -674,15 +689,17 @@ module Girl
674
689
  }
675
690
 
676
691
  @dst_infos[ dst ] = dst_info
677
- add_read( dst, :dst )
678
692
  src_info[ :proxy_type ] = :direct
679
693
  src_info[ :dst ] = dst
694
+ src_info[ :dst_created_at ] = Time.new
680
695
 
681
696
  if src_info[ :rbuff ] then
682
697
  # puts "debug move src.rbuff to dst.wbuff"
683
698
  dst_info[ :wbuff ] << src_info[ :rbuff ]
684
- add_write( dst )
685
699
  end
700
+
701
+ add_read( dst, :dst )
702
+ add_write( dst )
686
703
  end
687
704
 
688
705
  ##
@@ -718,6 +735,7 @@ module Girl
718
735
  #
719
736
  def new_a_redir( redir_port )
720
737
  redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
738
+ redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
721
739
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
722
740
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
723
741
  redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
@@ -756,7 +774,7 @@ module Girl
756
774
  to_addr = @nameserver_addr
757
775
  end
758
776
 
759
- puts "p#{ Process.pid } #{ Time.new } new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
777
+ # puts "debug new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
760
778
 
761
779
  @rsv_infos[ rsv ] = {
762
780
  src_addr: src_addr,
@@ -778,23 +796,25 @@ module Girl
778
796
 
779
797
  # puts "debug new atun and btun"
780
798
  atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
799
+ atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
781
800
 
782
801
  begin
783
802
  atun.connect_nonblock( @ctl_info[ :atund_addr ] )
784
803
  rescue IO::WaitWritable
785
804
  rescue Exception => e
786
- puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
805
+ puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
787
806
  atun.close
788
807
  return
789
808
  end
790
809
 
791
810
  btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
811
+ btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
792
812
 
793
813
  begin
794
814
  btun.connect_nonblock( @ctl_info[ :btund_addr ] )
795
815
  rescue IO::WaitWritable
796
816
  rescue Exception => e
797
- puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
817
+ puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
798
818
  btun.close
799
819
  return
800
820
  end
@@ -803,7 +823,7 @@ module Girl
803
823
  atun_wbuff = [ dst_id ].pack( 'n' )
804
824
 
805
825
  until src_info[ :rbuff ].empty? do
806
- data = src_info[ :rbuff ][ 0, 65535 ]
826
+ data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
807
827
  data_size = data.bytesize
808
828
  # puts "debug move src.rbuff #{ data_size } to atun.wbuff"
809
829
  atun_wbuff << pack_a_chunk( data )
@@ -824,7 +844,8 @@ module Girl
824
844
  domain: domain, # 目的地
825
845
  wbuff: btun_wbuff, # 写前
826
846
  rbuff: '', # 暂存当前块没收全的流量
827
- wait_bytes: 0 # 还差多少字节收全当前块
847
+ wait_bytes: 0, # 还差多少字节收全当前块
848
+ lbuff: '' # 流量截断在长度前缀处
828
849
  }
829
850
 
830
851
  src_info[ :dst_id ] = dst_id
@@ -933,7 +954,7 @@ module Girl
933
954
  # read dotr
934
955
  #
935
956
  def read_dotr( dotr )
936
- dotr.read_nonblock( 65535 )
957
+ dotr.read_nonblock( READ_SIZE )
937
958
 
938
959
  if @ctl_info && @ctl_info[ :closing ] then
939
960
  send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
@@ -1038,6 +1059,8 @@ module Girl
1038
1059
  destination_port: dest_port, # 目的地端口
1039
1060
  rbuff: '', # 读到的流量
1040
1061
  dst: nil, # :direct的场合,对应的dst
1062
+ dst_created_at: nil, # :direct的场合,对应的dst的创建时间
1063
+ dst_connected: false, # :direct的场合,对应的dst是否已连接
1041
1064
  ctl: nil, # :tunnel的场合,对应的ctl
1042
1065
  atun: nil, # :tunnel的场合,对应的atun
1043
1066
  btun: nil, # :tunnel的场合,对应的btun
@@ -1075,7 +1098,7 @@ module Girl
1075
1098
 
1076
1099
  case ctl_num
1077
1100
  when TUND_PORT then
1078
- return if @ctl_info[ :atund_addr ] || data.size != 5
1101
+ return if @ctl_info[ :atund_addr ] || data.bytesize != 5
1079
1102
  atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
1080
1103
  puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
1081
1104
  @ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
@@ -1089,14 +1112,14 @@ module Girl
1089
1112
  @pending_srcs.clear
1090
1113
  end
1091
1114
  when PAIRED then
1092
- return if data.size != 11
1115
+ return if data.bytesize != 11
1093
1116
  src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
1094
1117
  # puts "debug got paired #{ src_id } #{ dst_id }"
1095
1118
  @ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
1096
1119
  @ctl_info[ :last_recv_at ] = Time.new
1097
1120
  new_tuns( src_id, dst_id )
1098
1121
  when UNKNOWN_CTL_ADDR then
1099
- puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
1122
+ puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
1100
1123
  close_ctl( ctl )
1101
1124
  end
1102
1125
  end
@@ -1113,7 +1136,7 @@ module Girl
1113
1136
  src_info = @src_infos[ src ]
1114
1137
 
1115
1138
  begin
1116
- data = src.read_nonblock( 65535 )
1139
+ data = src.read_nonblock( CHUNK_SIZE )
1117
1140
  rescue IO::WaitReadable
1118
1141
  print 'r'
1119
1142
  return
@@ -1175,7 +1198,7 @@ module Girl
1175
1198
  src = dst_info[ :src ]
1176
1199
 
1177
1200
  begin
1178
- data = dst.read_nonblock( 65535 )
1201
+ data = dst.read_nonblock( CHUNK_SIZE )
1179
1202
  rescue IO::WaitReadable
1180
1203
  print 'r'
1181
1204
  return
@@ -1216,22 +1239,44 @@ module Girl
1216
1239
  end
1217
1240
 
1218
1241
  until data.empty? do
1219
- rbuff = btun_info[ :rbuff ]
1220
1242
  wait_bytes = btun_info[ :wait_bytes ]
1221
1243
 
1222
1244
  if wait_bytes > 0 then
1223
1245
  len = wait_bytes
1224
1246
  # puts "debug wait bytes #{ len }"
1225
1247
  else
1226
- if data.bytesize <= 2 then
1227
- # puts "debug unexpect data length #{ data.bytesize }"
1228
- close_btun( btun )
1229
- return
1230
- end
1248
+ lbuff = btun_info[ :lbuff ]
1249
+
1250
+ if lbuff.empty? then
1251
+ # 长度缓存为空,从读到的流量里取长度
1252
+ # 两个字节以下,记进长度缓存
1253
+ if data.bytesize <= 2 then
1254
+ # puts "debug set btun.lbuff #{ data.inspect }"
1255
+ btun_info[ :lbuff ] = data
1256
+ return
1257
+ end
1231
1258
 
1232
- len = data[ 0, 2 ].unpack( 'n' ).first
1233
- # puts "debug read len #{ len }"
1234
- data = data[ 2..-1 ]
1259
+ len = data[ 0, 2 ].unpack( 'n' ).first
1260
+ data = data[ 2..-1 ]
1261
+ elsif lbuff.bytesize == 1 then
1262
+ # 长度缓存记有一个字节,补一个字节
1263
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
1264
+
1265
+ if data.bytesize == 1 then
1266
+ # puts "debug add btun.lbuff a byte #{ data.inspect }"
1267
+ btun_info[ :lbuff ] = lbuff
1268
+ return
1269
+ end
1270
+
1271
+ # 使用长度缓存
1272
+ len = lbuff.unpack( 'n' ).first
1273
+ btun_info[ :lbuff ].clear
1274
+ data = data[ 1..-1 ]
1275
+ else
1276
+ # 使用长度缓存
1277
+ len = lbuff.unpack( 'n' ).first
1278
+ btun_info[ :lbuff ].clear
1279
+ end
1235
1280
  end
1236
1281
 
1237
1282
  chunk = data[ 0, len ]
@@ -1239,7 +1284,7 @@ module Girl
1239
1284
 
1240
1285
  if chunk_size == len then
1241
1286
  # 取完整了
1242
- chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
1287
+ chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
1243
1288
  # puts "debug read btun decoded #{ chunk.bytesize }"
1244
1289
  add_src_wbuff( src, chunk )
1245
1290
  btun_info[ :rbuff ] = ''
@@ -1318,6 +1363,12 @@ module Girl
1318
1363
 
1319
1364
  dst_info = @dst_infos[ dst ]
1320
1365
  src = dst_info[ :src ]
1366
+ src_info = @src_infos[ src ]
1367
+
1368
+ unless src.closed? then
1369
+ src_info[ :dst_connected ] = true
1370
+ end
1371
+
1321
1372
  data = dst_info[ :wbuff ]
1322
1373
 
1323
1374
  # 写前为空,处理关闭写
@@ -1348,7 +1399,6 @@ module Girl
1348
1399
  dst_info[ :wbuff ] = data
1349
1400
 
1350
1401
  unless src.closed? then
1351
- src_info = @src_infos[ src ]
1352
1402
  src_info[ :last_sent_at ] = Time.new
1353
1403
  end
1354
1404
  end
@@ -162,7 +162,7 @@ module Girl
162
162
  # read dotr
163
163
  #
164
164
  def read_dotr( dotr )
165
- dotr.read_nonblock( 65535 )
165
+ dotr.read_nonblock( READ_SIZE )
166
166
 
167
167
  if @closing_dsts.any? then
168
168
  @closing_dsts.each { | dst | close_dst( dst ) }
@@ -244,7 +244,7 @@ module Girl
244
244
  redir.close
245
245
  @roles.delete( redir )
246
246
  @reads.delete( redir )
247
- @src_infos.each { | src, _ | close_src( src ) }
247
+ @src_infos.keys.each { | src | close_src( src ) }
248
248
  end
249
249
 
250
250
  ##
@@ -340,9 +340,21 @@ module Girl
340
340
  @src_infos.each do | src, src_info |
341
341
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
342
342
  last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
343
- expire_after = src_info[ :dst ] ? EXPIRE_AFTER : EXPIRE_NEW
344
343
 
345
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
344
+ if src_info[ :dst ] then
345
+ if src_info[ :dst_connected ] then
346
+ expire_after = EXPIRE_AFTER
347
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
348
+ else
349
+ expire_after = EXPIRE_CONNECTING
350
+ is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
351
+ end
352
+ else
353
+ expire_after = EXPIRE_NEW
354
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
355
+ end
356
+
357
+ if is_expire then
346
358
  puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
347
359
  add_closing_src( src )
348
360
 
@@ -370,7 +382,7 @@ module Girl
370
382
  if dst && !dst.closed? then
371
383
  dst_info = @dst_infos[ dst ]
372
384
 
373
- if dst_info[ :wbuff ].size < RESUME_BELOW then
385
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
374
386
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
375
387
  add_resume_src( src )
376
388
  end
@@ -384,7 +396,7 @@ module Girl
384
396
  if src && !src.closed? then
385
397
  src_info = @src_infos[ src ]
386
398
 
387
- if src_info[ :wbuff ].size < RESUME_BELOW then
399
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
388
400
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
389
401
  add_resume_dst( dst )
390
402
  end
@@ -403,13 +415,14 @@ module Girl
403
415
  domain = src_info[ :destination_domain ]
404
416
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
405
417
  dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
418
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
406
419
 
407
420
  begin
408
421
  dst.connect_nonblock( destination_addr )
409
422
  rescue IO::WaitWritable
410
423
  # connect nonblock 必抛 wait writable
411
424
  rescue Exception => e
412
- puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }, close src"
425
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
413
426
  dst.close
414
427
  add_closing_src( src )
415
428
  return
@@ -424,10 +437,12 @@ module Girl
424
437
  }
425
438
 
426
439
  @dst_infos[ dst ] = dst_info
427
- add_read( dst, :dst )
428
440
  src_info[ :proxy_type ] = :direct
429
441
  src_info[ :dst ] = dst
442
+ src_info[ :dst_created_at ] = Time.new
430
443
  add_socks5_conn_reply( src )
444
+ add_read( dst, :dst )
445
+ add_write( dst )
431
446
  end
432
447
 
433
448
  ##
@@ -435,6 +450,7 @@ module Girl
435
450
  #
436
451
  def new_a_redir
437
452
  pre = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
453
+ pre.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
438
454
  pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
439
455
  pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
440
456
  pre.bind( Socket.sockaddr_in( @redir_port, '0.0.0.0' ) )
@@ -534,7 +550,7 @@ module Girl
534
550
  # read dotr
535
551
  #
536
552
  def read_dotr( dotr )
537
- dotr.read_nonblock( 65535 )
553
+ dotr.read_nonblock( READ_SIZE )
538
554
 
539
555
  if @closing_srcs.any? then
540
556
  @closing_srcs.each { | src | close_src( src ) }
@@ -599,6 +615,8 @@ module Girl
599
615
  is_connect: true, # 代理协议是http的场合,是否是CONNECT
600
616
  rbuff: '', # 读到的流量
601
617
  dst: nil, # 对应的dst
618
+ dst_created_at: nil, # 对应的dst的创建时间
619
+ dst_connected: false, # 对应的dst是否已连接
602
620
  wbuff: '', # 从dst读到的流量
603
621
  created_at: Time.new, # 创建时间
604
622
  last_recv_at: nil, # 上一次收到新流量(由dst收到)的时间
@@ -623,7 +641,7 @@ module Girl
623
641
  src_info = @src_infos[ src ]
624
642
 
625
643
  begin
626
- data = src.read_nonblock( 65535 )
644
+ data = src.read_nonblock( READ_SIZE )
627
645
  rescue IO::WaitReadable
628
646
  return
629
647
  rescue Errno::EINTR => e
@@ -741,7 +759,7 @@ module Girl
741
759
  src = dst_info[ :src ]
742
760
 
743
761
  begin
744
- data = dst.read_nonblock( 65535 )
762
+ data = dst.read_nonblock( READ_SIZE )
745
763
  rescue IO::WaitReadable, Errno::EINTR
746
764
  print 'r'
747
765
  return
@@ -812,6 +830,12 @@ module Girl
812
830
 
813
831
  dst_info = @dst_infos[ dst ]
814
832
  src = dst_info[ :src ]
833
+ src_info = @src_infos[ src ]
834
+
835
+ unless src.closed? then
836
+ src_info[ :dst_connected ] = true
837
+ end
838
+
815
839
  data = dst_info[ :wbuff ]
816
840
 
817
841
  # 写前为空,处理关闭写
@@ -842,7 +866,6 @@ module Girl
842
866
  dst_info[ :wbuff ] = data
843
867
 
844
868
  unless src.closed? then
845
- src_info = @src_infos[ src ]
846
869
  src_info[ :last_sent_at ] = Time.new
847
870
  end
848
871
  end
data/lib/girl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '4.2.0'.freeze
2
+ VERSION = '4.7.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: girl
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-13 00:00:00.000000000 Z
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: escape evil.
14
14
  email:
@@ -55,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  requirements: []
58
- rubygems_version: 3.2.15
58
+ rubygems_version: 3.2.3
59
59
  signing_key:
60
60
  specification_version: 4
61
61
  summary: 妹子