girl 4.3.0 → 4.8.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: 43a48060a5cd6624864bceaa00824b736918f484b5a9342f67a7e885b401b276
4
- data.tar.gz: f08b961719f618da8833746996c9bb66698a35e1d43526e63dd2792df2ed53da
3
+ metadata.gz: 944b2055e93c9751113af05107dce4dc040bb40a41602388350c292af2286e0b
4
+ data.tar.gz: 71c9b4cb592f41750a5f21d751afeb4d13be0b2c20da2f10eb0df42a8cfbe2fd
5
5
  SHA512:
6
- metadata.gz: aa1c6709b604a13c80b9b4c66f09ae80f5ceb7714c8d8f3f0d9ee7cd906f1179399e8f75f31e8e8763bef0eb0ea62f4ddc46b646585833d75a4fdc07fc84c0f6
7
- data.tar.gz: 5443ef6598cc196a27dcf50ec0e0f8d39cf65cc01a268092c0f2b9db2d1add65b1ee33eba8bdce17bd1be8b3e256fcc37bf731aecd4a3bee62d35eb198074934
6
+ metadata.gz: 8a01d46a18c169d0d4773168379b0aa1106157872554444d166156dbaf7d55966d8f941561754d5e506c91d098383bf419ad42a8cd59432dc0270e7f879dc355
7
+ data.tar.gz: a9ed3e588404a191c0c7b38abdb1ec3573af2139022258dd9f2ee469ce6ad335b21ab5595002638d73946130535b6f92ac8c7bb429da7cd3c5b005e1dffdb3f8
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 + 10.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 )
@@ -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
@@ -1413,6 +1446,12 @@ module Girl
1413
1446
 
1414
1447
  dst_info = @dst_infos[ dst ]
1415
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
+
1416
1455
  data = dst_info[ :wbuff ]
1417
1456
 
1418
1457
  # 写前为空,处理关闭写
@@ -1443,7 +1482,6 @@ module Girl
1443
1482
  dst_info[ :wbuff ] = data
1444
1483
 
1445
1484
  unless src.closed? then
1446
- src_info = @src_infos[ src ]
1447
1485
  src_info[ :last_sent_at ] = Time.new
1448
1486
  end
1449
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
+ 10.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
  #
@@ -571,11 +583,11 @@ module Girl
571
583
  ##
572
584
  # send ctlmsg
573
585
  #
574
- def send_ctlmsg( data, to_addr )
586
+ def send_ctlmsg( ctld, data, to_addr )
575
587
  data = @custom.encode( data )
576
588
 
577
589
  begin
578
- @ctld.sendmsg( data, 0, to_addr )
590
+ ctld.sendmsg( data, 0, to_addr )
579
591
  rescue Exception => e
580
592
  puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
581
593
  end
@@ -609,7 +621,7 @@ module Girl
609
621
  # read dotr
610
622
  #
611
623
  def read_dotr( dotr )
612
- dotr.read_nonblock( 65535 )
624
+ dotr.read_nonblock( READ_SIZE )
613
625
 
614
626
  if @deleting_ctl_infos.any? then
615
627
  @deleting_ctl_infos.each { | ctl_addr | del_ctl_info( ctl_addr ) }
@@ -655,7 +667,7 @@ module Girl
655
667
  if ctl_info then
656
668
  atund_port, btund_port = ctl_info[ :atund_port ], ctl_info[ :btund_port ]
657
669
  else
658
- return if data.size <= 1
670
+ return if data.bytesize <= 1
659
671
  im = data[ 1..-1 ]
660
672
  result = @custom.check( im, addrinfo )
661
673
 
@@ -687,6 +699,7 @@ module Girl
687
699
  }
688
700
 
689
701
  @ctl_infos[ ctl_addr ] = {
702
+ ctld: ctld, # 对应的ctld
690
703
  addrinfo: addrinfo, # 地址
691
704
  im: im, # 标识
692
705
  atund: atund, # 对应atund,src->dst
@@ -702,21 +715,21 @@ module Girl
702
715
  end
703
716
 
704
717
  data2 = [ TUND_PORT, atund_port, btund_port ].pack( 'Cnn' )
705
- send_ctlmsg( data2, ctl_addr )
718
+ send_ctlmsg( ctld, data2, ctl_addr )
706
719
  when A_NEW_SOURCE then
707
720
  unless ctl_info then
708
- send_ctlmsg( [ UNKNOWN_CTL_ADDR ].pack( 'C' ), addrinfo )
721
+ send_ctlmsg( ctld, [ UNKNOWN_CTL_ADDR ].pack( 'C' ), addrinfo )
709
722
  return
710
723
  end
711
724
 
712
- return if data.size <= 9
725
+ return if data.bytesize <= 9
713
726
  src_id = data[ 1, 8 ].unpack( 'Q>' ).first
714
727
  dst_id = ctl_info[ :dst_ids ][ src_id ]
715
728
 
716
729
  if dst_id then
717
730
  data2 = [ PAIRED, src_id, dst_id ].pack( 'CQ>n' )
718
731
  # puts "debug dst id exist, send ctlmsg paired #{ src_id } #{ dst_id }"
719
- send_ctlmsg( data2, ctl_addr )
732
+ send_ctlmsg( ctld, data2, ctl_addr )
720
733
  return
721
734
  end
722
735
 
@@ -772,7 +785,7 @@ module Girl
772
785
  btun = dst_info[ :btun ]
773
786
 
774
787
  begin
775
- data = dst.read_nonblock( 65535 )
788
+ data = dst.read_nonblock( CHUNK_SIZE )
776
789
  rescue IO::WaitReadable
777
790
  print 'r'
778
791
  return
@@ -1044,7 +1057,7 @@ module Girl
1044
1057
  data2 = ''
1045
1058
 
1046
1059
  until dst_info[ :rbuff ].empty? do
1047
- _data = dst_info[ :rbuff ][ 0, 65535 ]
1060
+ _data = dst_info[ :rbuff ][ 0, CHUNK_SIZE ]
1048
1061
  data_size = _data.bytesize
1049
1062
  # puts "debug move dst.rbuff to btun.wbuff"
1050
1063
  data2 << pack_a_chunk( _data )
@@ -1067,6 +1080,7 @@ module Girl
1067
1080
  end
1068
1081
 
1069
1082
  dst_info = @dst_infos[ dst ]
1083
+ dst_info[ :connected ] = true
1070
1084
  atun = dst_info[ :atun ]
1071
1085
  data = dst_info[ :wbuff ]
1072
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
 
@@ -6,10 +6,10 @@ module Girl
6
6
  #
7
7
  def initialize( resolv_port, nameserver, resolvd_port, redir_port, proxyd_host, proxyd_port, directs, remotes, im )
8
8
  @nameserver_addr = Socket.sockaddr_in( 53, nameserver )
9
- @resolvd_addr = Socket.sockaddr_in( resolvd_port, proxyd_host )
9
+ @resolvd_ports = 10.times.map { | i | resolvd_port + i }
10
10
  @qnames = remotes.map { | dom | dom.split( '.' ).map{ | sub | [ sub.size ].pack( 'C' ) + sub }.join }
11
11
  @proxyd_host = proxyd_host
12
- @proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
12
+ @proxyd_port = proxyd_port
13
13
  @directs = directs
14
14
  @remotes = remotes
15
15
  @custom = Girl::ProxyCustom.new( im )
@@ -444,8 +444,7 @@ module Girl
444
444
  return if src.closed?
445
445
  src_info = @src_infos[ src ]
446
446
 
447
- if ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) \
448
- || ( ( ip_info.ip_address == @proxyd_host ) && ( src_info[ :destination_port ] == @proxyd_port ) ) then
447
+ if ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) then
449
448
  puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
450
449
  add_closing_src( src )
451
450
  return
@@ -520,10 +519,9 @@ module Girl
520
519
  if @ctl && !@ctl.closed? then
521
520
  last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
522
521
 
523
- if now - last_recv_at >= EXPIRE_AFTER then
524
- puts "p#{ Process.pid } #{ Time.new } expire ctl"
525
- @ctl_info[ :closing ] = true
526
- next_tick
522
+ if now - last_recv_at >= EXPIRE_CTL then
523
+ puts "p#{ Process.pid } #{ Time.new } expire ctl #{ EXPIRE_CTL }"
524
+ set_ctl_closing
527
525
  end
528
526
  end
529
527
 
@@ -537,9 +535,24 @@ module Girl
537
535
  @src_infos.each do | src, src_info |
538
536
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
539
537
  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
538
 
542
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
539
+ if src_info[ :dst ] then
540
+ if src_info[ :dst_connected ] then
541
+ expire_after = EXPIRE_AFTER
542
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
543
+ else
544
+ expire_after = EXPIRE_CONNECTING
545
+ is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
546
+ end
547
+ elsif src_info[ :atun ] then
548
+ expire_after = EXPIRE_AFTER
549
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
550
+ else
551
+ expire_after = EXPIRE_NEW
552
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
553
+ end
554
+
555
+ if is_expire then
543
556
  puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
544
557
  add_closing_src( src )
545
558
 
@@ -568,7 +581,7 @@ module Girl
568
581
  if !dst.closed? then
569
582
  dst_info = @dst_infos[ dst ]
570
583
 
571
- if dst_info[ :wbuff ].size < RESUME_BELOW then
584
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
572
585
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
573
586
  add_resume_src( src )
574
587
  end
@@ -579,7 +592,7 @@ module Girl
579
592
  if atun && !atun.closed? then
580
593
  atun_info = @atun_infos[ atun ]
581
594
 
582
- if atun_info[ :wbuff ].size < RESUME_BELOW then
595
+ if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
583
596
  puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
584
597
  add_resume_src( src )
585
598
  end
@@ -594,7 +607,7 @@ module Girl
594
607
  if src && !src.closed? then
595
608
  src_info = @src_infos[ src ]
596
609
 
597
- if src_info[ :wbuff ].size < RESUME_BELOW then
610
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
598
611
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
599
612
  add_resume_dst( dst )
600
613
  end
@@ -608,7 +621,7 @@ module Girl
608
621
  if src && !src.closed? then
609
622
  src_info = @src_infos[ src ]
610
623
 
611
- if src_info[ :wbuff ].size < RESUME_BELOW then
624
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
612
625
  puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
613
626
  add_resume_btun( btun )
614
627
  end
@@ -635,6 +648,7 @@ module Girl
635
648
 
636
649
  if resend >= RESEND_LIMIT then
637
650
  @ctl_info[ :resends ].delete( key )
651
+ set_ctl_closing
638
652
  break
639
653
  end
640
654
 
@@ -652,14 +666,14 @@ module Girl
652
666
  domain = src_info[ :destination_domain ]
653
667
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
654
668
  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 )
669
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
656
670
 
657
671
  begin
658
672
  dst.connect_nonblock( destination_addr )
659
673
  rescue IO::WaitWritable
660
674
  # connect nonblock 必抛 wait writable
661
675
  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"
676
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
663
677
  dst.close
664
678
  add_closing_src( src )
665
679
  return
@@ -674,15 +688,17 @@ module Girl
674
688
  }
675
689
 
676
690
  @dst_infos[ dst ] = dst_info
677
- add_read( dst, :dst )
678
691
  src_info[ :proxy_type ] = :direct
679
692
  src_info[ :dst ] = dst
693
+ src_info[ :dst_created_at ] = Time.new
680
694
 
681
695
  if src_info[ :rbuff ] then
682
696
  # puts "debug move src.rbuff to dst.wbuff"
683
697
  dst_info[ :wbuff ] << src_info[ :rbuff ]
684
- add_write( dst )
685
698
  end
699
+
700
+ add_read( dst, :dst )
701
+ add_write( dst )
686
702
  end
687
703
 
688
704
  ##
@@ -698,7 +714,10 @@ module Girl
698
714
  @ctl = ctl
699
715
  add_read( ctl, :ctl )
700
716
 
717
+ ctld_port = @proxyd_port + 10.times.to_a.sample
718
+ ctld_addr = Socket.sockaddr_in( ctld_port, @proxyd_host )
701
719
  @ctl_info = {
720
+ ctld_addr: ctld_addr, # ctld地址
702
721
  resends: ConcurrentHash.new, # key => count
703
722
  atund_addr: nil, # atund地址,src->dst
704
723
  btund_addr: nil, # btund地址,dst->src
@@ -708,7 +727,7 @@ module Girl
708
727
  }
709
728
 
710
729
  hello = @custom.hello
711
- puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect }"
730
+ puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect } #{ ctld_port }"
712
731
  key = [ HELLO ].pack( 'C' )
713
732
  add_ctlmsg( key, hello )
714
733
  end
@@ -718,6 +737,7 @@ module Girl
718
737
  #
719
738
  def new_a_redir( redir_port )
720
739
  redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
740
+ redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
721
741
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
722
742
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
723
743
  redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
@@ -751,12 +771,12 @@ module Girl
751
771
 
752
772
  if @qnames.any? { | qname | data.include?( qname ) } then
753
773
  data = @custom.encode( data )
754
- to_addr = @resolvd_addr
774
+ to_addr = Socket.sockaddr_in( @resolvd_ports.sample, @proxyd_host )
755
775
  else
756
776
  to_addr = @nameserver_addr
757
777
  end
758
778
 
759
- puts "p#{ Process.pid } #{ Time.new } new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
779
+ # puts "debug new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
760
780
 
761
781
  @rsv_infos[ rsv ] = {
762
782
  src_addr: src_addr,
@@ -778,23 +798,25 @@ module Girl
778
798
 
779
799
  # puts "debug new atun and btun"
780
800
  atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
801
+ atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
781
802
 
782
803
  begin
783
804
  atun.connect_nonblock( @ctl_info[ :atund_addr ] )
784
805
  rescue IO::WaitWritable
785
806
  rescue Exception => e
786
- puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
807
+ puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
787
808
  atun.close
788
809
  return
789
810
  end
790
811
 
791
812
  btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
813
+ btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
792
814
 
793
815
  begin
794
816
  btun.connect_nonblock( @ctl_info[ :btund_addr ] )
795
817
  rescue IO::WaitWritable
796
818
  rescue Exception => e
797
- puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
819
+ puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
798
820
  btun.close
799
821
  return
800
822
  end
@@ -803,7 +825,7 @@ module Girl
803
825
  atun_wbuff = [ dst_id ].pack( 'n' )
804
826
 
805
827
  until src_info[ :rbuff ].empty? do
806
- data = src_info[ :rbuff ][ 0, 65535 ]
828
+ data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
807
829
  data_size = data.bytesize
808
830
  # puts "debug move src.rbuff #{ data_size } to atun.wbuff"
809
831
  atun_wbuff << pack_a_chunk( data )
@@ -861,7 +883,7 @@ module Girl
861
883
  data = @custom.encode( data )
862
884
 
863
885
  begin
864
- @ctl.sendmsg( data, 0, @proxyd_addr )
886
+ @ctl.sendmsg( data, 0, @ctl_info[ :ctld_addr ] )
865
887
  @ctl_info[ :last_sent_at ] = Time.new
866
888
  rescue Exception => e
867
889
  puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
@@ -869,6 +891,17 @@ module Girl
869
891
  end
870
892
  end
871
893
 
894
+ ##
895
+ # send data
896
+ #
897
+ def send_data( sock, to_addr, data )
898
+ begin
899
+ sock.sendmsg( data, 0, to_addr )
900
+ rescue Exception => e
901
+ puts "p#{ Process.pid } #{ Time.new } sendmsg to #{ to_addr.ip_unpack.inspect } #{ e.class }"
902
+ end
903
+ end
904
+
872
905
  ##
873
906
  # set atun closing
874
907
  #
@@ -882,14 +915,12 @@ module Girl
882
915
  end
883
916
 
884
917
  ##
885
- # send data
918
+ # set ctl closing
886
919
  #
887
- def send_data( sock, to_addr, data )
888
- begin
889
- sock.sendmsg( data, 0, to_addr )
890
- rescue Exception => e
891
- puts "p#{ Process.pid } #{ Time.new } sendmsg to #{ to_addr.ip_unpack.inspect } #{ e.class }"
892
- end
920
+ def set_ctl_closing
921
+ return if @ctl.closed?
922
+ @ctl_info[ :closing ] = true
923
+ next_tick
893
924
  end
894
925
 
895
926
  ##
@@ -934,7 +965,7 @@ module Girl
934
965
  # read dotr
935
966
  #
936
967
  def read_dotr( dotr )
937
- dotr.read_nonblock( 65535 )
968
+ dotr.read_nonblock( READ_SIZE )
938
969
 
939
970
  if @ctl_info && @ctl_info[ :closing ] then
940
971
  send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
@@ -995,7 +1026,7 @@ module Girl
995
1026
  data, addrinfo, rflags, *controls = rsv.recvmsg
996
1027
  # puts "debug rsv recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
997
1028
 
998
- if addrinfo.to_sockaddr == @resolvd_addr then
1029
+ if addrinfo.ip_address == @proxyd_host then
999
1030
  data = @custom.decode( data )
1000
1031
  end
1001
1032
 
@@ -1039,6 +1070,8 @@ module Girl
1039
1070
  destination_port: dest_port, # 目的地端口
1040
1071
  rbuff: '', # 读到的流量
1041
1072
  dst: nil, # :direct的场合,对应的dst
1073
+ dst_created_at: nil, # :direct的场合,对应的dst的创建时间
1074
+ dst_connected: false, # :direct的场合,对应的dst是否已连接
1042
1075
  ctl: nil, # :tunnel的场合,对应的ctl
1043
1076
  atun: nil, # :tunnel的场合,对应的atun
1044
1077
  btun: nil, # :tunnel的场合,对应的btun
@@ -1076,7 +1109,7 @@ module Girl
1076
1109
 
1077
1110
  case ctl_num
1078
1111
  when TUND_PORT then
1079
- return if @ctl_info[ :atund_addr ] || data.size != 5
1112
+ return if @ctl_info[ :atund_addr ] || data.bytesize != 5
1080
1113
  atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
1081
1114
  puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
1082
1115
  @ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
@@ -1090,14 +1123,14 @@ module Girl
1090
1123
  @pending_srcs.clear
1091
1124
  end
1092
1125
  when PAIRED then
1093
- return if data.size != 11
1126
+ return if data.bytesize != 11
1094
1127
  src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
1095
1128
  # puts "debug got paired #{ src_id } #{ dst_id }"
1096
1129
  @ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
1097
1130
  @ctl_info[ :last_recv_at ] = Time.new
1098
1131
  new_tuns( src_id, dst_id )
1099
1132
  when UNKNOWN_CTL_ADDR then
1100
- puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
1133
+ puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
1101
1134
  close_ctl( ctl )
1102
1135
  end
1103
1136
  end
@@ -1114,7 +1147,7 @@ module Girl
1114
1147
  src_info = @src_infos[ src ]
1115
1148
 
1116
1149
  begin
1117
- data = src.read_nonblock( 65535 )
1150
+ data = src.read_nonblock( CHUNK_SIZE )
1118
1151
  rescue IO::WaitReadable
1119
1152
  print 'r'
1120
1153
  return
@@ -1176,7 +1209,7 @@ module Girl
1176
1209
  src = dst_info[ :src ]
1177
1210
 
1178
1211
  begin
1179
- data = dst.read_nonblock( 65535 )
1212
+ data = dst.read_nonblock( CHUNK_SIZE )
1180
1213
  rescue IO::WaitReadable
1181
1214
  print 'r'
1182
1215
  return
@@ -1341,6 +1374,12 @@ module Girl
1341
1374
 
1342
1375
  dst_info = @dst_infos[ dst ]
1343
1376
  src = dst_info[ :src ]
1377
+ src_info = @src_infos[ src ]
1378
+
1379
+ unless src.closed? then
1380
+ src_info[ :dst_connected ] = true
1381
+ end
1382
+
1344
1383
  data = dst_info[ :wbuff ]
1345
1384
 
1346
1385
  # 写前为空,处理关闭写
@@ -1371,7 +1410,6 @@ module Girl
1371
1410
  dst_info[ :wbuff ] = data
1372
1411
 
1373
1412
  unless src.closed? then
1374
- src_info = @src_infos[ src ]
1375
1413
  src_info[ :last_sent_at ] = Time.new
1376
1414
  end
1377
1415
  end
@@ -16,7 +16,7 @@ module Girl
16
16
  dotr, dotw = IO.pipe
17
17
  @dotw = dotw
18
18
  add_read( dotr, :dotr )
19
- new_a_resolvd( resolvd_port )
19
+ new_resolvds( resolvd_port )
20
20
  end
21
21
 
22
22
  ##
@@ -111,13 +111,14 @@ module Girl
111
111
  ##
112
112
  # new a dst
113
113
  #
114
- def new_a_dst( src_addr, data )
114
+ def new_a_dst( resolvd, src_addr, data )
115
115
  dst = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
116
116
  dst.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
117
117
  dst.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
118
118
 
119
119
  puts "p#{ Process.pid } #{ Time.new } new a dst"
120
120
  @dst_infos[ dst ] = {
121
+ resolvd: resolvd,
121
122
  src_addr: src_addr,
122
123
  created_at: Time.new
123
124
  }
@@ -126,16 +127,18 @@ module Girl
126
127
  end
127
128
 
128
129
  ##
129
- # new a resolvd
130
+ # new resolvds
130
131
  #
131
- def new_a_resolvd( resolvd_port )
132
- resolvd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
133
- resolvd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
134
- resolvd.bind( Socket.sockaddr_in( resolvd_port, '0.0.0.0' ) )
135
-
136
- puts "p#{ Process.pid } #{ Time.new } resolvd bind on #{ resolvd_port }"
137
- add_read( resolvd, :resolvd )
138
- @resolvd = resolvd
132
+ def new_resolvds( resolvd_port )
133
+ 10.times do
134
+ resolvd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
135
+ resolvd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
136
+ resolvd.bind( Socket.sockaddr_in( resolvd_port, '0.0.0.0' ) )
137
+
138
+ puts "p#{ Process.pid } #{ Time.new } resolvd bind on #{ resolvd_port }"
139
+ add_read( resolvd, :resolvd )
140
+ resolvd_port += 1
141
+ end
139
142
  end
140
143
 
141
144
  ##
@@ -162,7 +165,7 @@ module Girl
162
165
  # read dotr
163
166
  #
164
167
  def read_dotr( dotr )
165
- dotr.read_nonblock( 65535 )
168
+ dotr.read_nonblock( READ_SIZE )
166
169
 
167
170
  if @closing_dsts.any? then
168
171
  @closing_dsts.each { | dst | close_dst( dst ) }
@@ -177,7 +180,7 @@ module Girl
177
180
  data, addrinfo, rflags, *controls = resolvd.recvmsg
178
181
  # puts "debug1 resolvd recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
179
182
  data = @custom.decode( data )
180
- new_a_dst( addrinfo.to_sockaddr, data )
183
+ new_a_dst( resolvd, addrinfo.to_sockaddr, data )
181
184
  end
182
185
 
183
186
  ##
@@ -188,7 +191,7 @@ module Girl
188
191
  # puts "debug1 dst recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
189
192
  dst_info = @dst_infos[ dst ]
190
193
  data = @custom.encode( data )
191
- send_data( @resolvd, dst_info[ :src_addr ], data )
194
+ send_data( dst_info[ :resolvd ], dst_info[ :src_addr ], data )
192
195
  close_dst( dst )
193
196
  end
194
197
 
@@ -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.3.0'.freeze
2
+ VERSION = '4.8.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.3.0
4
+ version: 4.8.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: 妹子