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 +4 -4
- data/lib/girl/head.rb +7 -3
- data/lib/girl/proxy_worker.rb +100 -40
- data/lib/girl/proxyd_worker.rb +78 -42
- data/lib/girl/relay.rb +1 -0
- data/lib/girl/relay_worker.rb +84 -34
- data/lib/girl/resolvd_worker.rb +1 -1
- data/lib/girl/ssl_worker.rb +34 -11
- data/lib/girl/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e06e25ddc6594959cceb39bd5d4ad420941dfaeec6866a86d7817e974cf9bc2f
|
4
|
+
data.tar.gz: 6d8016cd3a42b0cf611bad16759e34f130f193bb9e68a88f5f8b80597bd62dc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 #
|
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
|
-
|
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 =
|
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
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -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 (
|
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 >=
|
511
|
-
puts "p#{ Process.pid } #{ Time.new } expire ctl"
|
512
|
-
|
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
|
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 ].
|
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 ].
|
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 ].
|
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 ].
|
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 }
|
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 }
|
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 }
|
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,
|
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, @
|
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(
|
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.
|
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.
|
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
|
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(
|
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(
|
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
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
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
|
-
|
1306
|
-
|
1307
|
-
|
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
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -28,7 +28,7 @@ module Girl
|
|
28
28
|
dotr, dotw = IO.pipe
|
29
29
|
@dotw = dotw
|
30
30
|
add_read( dotr, :dotr )
|
31
|
-
|
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
|
-
|
408
|
-
|
409
|
-
|
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
|
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 ].
|
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 ].
|
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
|
-
|
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(
|
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.
|
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.
|
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(
|
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
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
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
|
-
|
939
|
-
|
940
|
-
|
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,
|
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
data/lib/girl/relay_worker.rb
CHANGED
@@ -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 >=
|
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
|
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 ].
|
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 ].
|
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 ].
|
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 ].
|
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::
|
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 }
|
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 "
|
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 }
|
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 }
|
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,
|
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(
|
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.
|
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.
|
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
|
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(
|
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(
|
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
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
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
|
-
|
1233
|
-
|
1234
|
-
|
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
|
data/lib/girl/resolvd_worker.rb
CHANGED
data/lib/girl/ssl_worker.rb
CHANGED
@@ -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
|
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
|
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 ].
|
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 ].
|
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 }
|
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(
|
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(
|
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(
|
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
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.
|
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-
|
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.
|
58
|
+
rubygems_version: 3.2.3
|
59
59
|
signing_key:
|
60
60
|
specification_version: 4
|
61
61
|
summary: 妹子
|