girl 4.1.0 → 4.6.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/girl.gemspec +0 -1
- data/lib/girl/concurrent_hash.rb +26 -26
- data/lib/girl/head.rb +7 -3
- data/lib/girl/proxy.rb +4 -6
- data/lib/girl/proxy_custom.rb +16 -16
- data/lib/girl/proxy_worker.rb +101 -68
- data/lib/girl/proxyd_custom.rb +12 -12
- data/lib/girl/proxyd_worker.rb +80 -28
- data/lib/girl/relay.rb +1 -1
- data/lib/girl/relay_worker.rb +93 -65
- data/lib/girl/resolv_custom.rb +2 -2
- data/lib/girl/resolvd_worker.rb +4 -4
- data/lib/girl/ssl_worker.rb +50 -14
- data/lib/girl/version.rb +1 -1
- metadata +3 -4
- data/lib/girl/custom_dns_query.rb +0 -11
data/lib/girl/proxyd_custom.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require 'girl/custom'
|
2
|
-
|
3
|
-
module Girl
|
4
|
-
class ProxydCustom
|
5
|
-
include Custom
|
6
|
-
|
7
|
-
def check( data, addrinfo )
|
8
|
-
:success
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
1
|
+
require 'girl/custom'
|
2
|
+
|
3
|
+
module Girl
|
4
|
+
class ProxydCustom
|
5
|
+
include Custom
|
6
|
+
|
7
|
+
def check( data, addrinfo )
|
8
|
+
:success
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -221,7 +221,7 @@ module Girl
|
|
221
221
|
close_sock( btun )
|
222
222
|
btun_info = @btun_infos.delete( btun )
|
223
223
|
dst = btun_info[ :dst ]
|
224
|
-
|
224
|
+
|
225
225
|
if dst then
|
226
226
|
@paused_dsts.delete( dst )
|
227
227
|
end
|
@@ -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,6 +338,7 @@ 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
|
@@ -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
|
@@ -507,6 +516,7 @@ module Girl
|
|
507
516
|
#
|
508
517
|
def new_a_tund
|
509
518
|
tund = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
519
|
+
tund.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
510
520
|
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
511
521
|
tund.listen( 127 )
|
512
522
|
tund
|
@@ -519,6 +529,14 @@ module Girl
|
|
519
529
|
@dotw.write( '.' )
|
520
530
|
end
|
521
531
|
|
532
|
+
##
|
533
|
+
# pack a chunk
|
534
|
+
#
|
535
|
+
def pack_a_chunk( data )
|
536
|
+
data = @custom.encode( data )
|
537
|
+
"#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
|
538
|
+
end
|
539
|
+
|
522
540
|
##
|
523
541
|
# resolve domain
|
524
542
|
#
|
@@ -564,6 +582,8 @@ module Girl
|
|
564
582
|
# send ctlmsg
|
565
583
|
#
|
566
584
|
def send_ctlmsg( data, to_addr )
|
585
|
+
data = @custom.encode( data )
|
586
|
+
|
567
587
|
begin
|
568
588
|
@ctld.sendmsg( data, 0, to_addr )
|
569
589
|
rescue Exception => e
|
@@ -599,7 +619,7 @@ module Girl
|
|
599
619
|
# read dotr
|
600
620
|
#
|
601
621
|
def read_dotr( dotr )
|
602
|
-
dotr.read_nonblock(
|
622
|
+
dotr.read_nonblock( READ_SIZE )
|
603
623
|
|
604
624
|
if @deleting_ctl_infos.any? then
|
605
625
|
@deleting_ctl_infos.each { | ctl_addr | del_ctl_info( ctl_addr ) }
|
@@ -635,6 +655,7 @@ module Girl
|
|
635
655
|
#
|
636
656
|
def read_ctld( ctld )
|
637
657
|
data, addrinfo, rflags, *controls = ctld.recvmsg
|
658
|
+
data = @custom.decode( data )
|
638
659
|
ctl_num = data[ 0 ].unpack( 'C' ).first
|
639
660
|
ctl_addr = addrinfo.to_sockaddr
|
640
661
|
ctl_info = @ctl_infos[ ctl_addr ]
|
@@ -644,7 +665,7 @@ module Girl
|
|
644
665
|
if ctl_info then
|
645
666
|
atund_port, btund_port = ctl_info[ :atund_port ], ctl_info[ :btund_port ]
|
646
667
|
else
|
647
|
-
return if data.
|
668
|
+
return if data.bytesize <= 1
|
648
669
|
im = data[ 1..-1 ]
|
649
670
|
result = @custom.check( im, addrinfo )
|
650
671
|
|
@@ -698,7 +719,7 @@ module Girl
|
|
698
719
|
return
|
699
720
|
end
|
700
721
|
|
701
|
-
return if data.
|
722
|
+
return if data.bytesize <= 9
|
702
723
|
src_id = data[ 1, 8 ].unpack( 'Q>' ).first
|
703
724
|
dst_id = ctl_info[ :dst_ids ][ src_id ]
|
704
725
|
|
@@ -761,7 +782,7 @@ module Girl
|
|
761
782
|
btun = dst_info[ :btun ]
|
762
783
|
|
763
784
|
begin
|
764
|
-
data = dst.read_nonblock(
|
785
|
+
data = dst.read_nonblock( CHUNK_SIZE )
|
765
786
|
rescue IO::WaitReadable
|
766
787
|
print 'r'
|
767
788
|
return
|
@@ -777,12 +798,10 @@ module Girl
|
|
777
798
|
end
|
778
799
|
|
779
800
|
@traff_ins[ dst_info[ :im ] ] += data.bytesize
|
780
|
-
# puts "debug read dst #{ data.bytesize }
|
781
|
-
data = @custom.encode( data )
|
782
|
-
data = "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
|
801
|
+
# puts "debug read dst #{ data.bytesize }"
|
783
802
|
|
784
803
|
if btun then
|
785
|
-
add_btun_wbuff( btun, data )
|
804
|
+
add_btun_wbuff( btun, pack_a_chunk( data ) )
|
786
805
|
else
|
787
806
|
# puts "debug add dst.rbuff #{ data.bytesize }"
|
788
807
|
add_dst_rbuff( dst, data )
|
@@ -816,7 +835,8 @@ module Girl
|
|
816
835
|
dst: nil, # 对应dst
|
817
836
|
domain_port: nil, # dst的目的地和端口
|
818
837
|
rbuff: '', # 暂存当前块没收全的流量
|
819
|
-
wait_bytes: 0
|
838
|
+
wait_bytes: 0, # 还差多少字节收全当前块
|
839
|
+
lbuff: '' # 流量截断在长度前缀处
|
820
840
|
}
|
821
841
|
|
822
842
|
add_read( atun, :atun )
|
@@ -912,22 +932,44 @@ module Girl
|
|
912
932
|
end
|
913
933
|
|
914
934
|
until data.empty? do
|
915
|
-
rbuff = atun_info[ :rbuff ]
|
916
935
|
wait_bytes = atun_info[ :wait_bytes ]
|
917
936
|
|
918
937
|
if wait_bytes > 0 then
|
919
938
|
len = wait_bytes
|
920
939
|
# puts "debug wait bytes #{ len }"
|
921
940
|
else
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
941
|
+
lbuff = atun_info[ :lbuff ]
|
942
|
+
|
943
|
+
if lbuff.empty? then
|
944
|
+
# 长度缓存为空,从读到的流量里取长度
|
945
|
+
# 两个字节以下,记进长度缓存
|
946
|
+
if data.bytesize <= 2 then
|
947
|
+
# puts "debug set atun.lbuff #{ data.inspect }"
|
948
|
+
atun_info[ :lbuff ] = data
|
949
|
+
return
|
950
|
+
end
|
951
|
+
|
952
|
+
len = data[ 0, 2 ].unpack( 'n' ).first
|
953
|
+
data = data[ 2..-1 ]
|
954
|
+
elsif lbuff.bytesize == 1 then
|
955
|
+
# 长度缓存记有一个字节,补一个字节
|
956
|
+
lbuff = "#{ lbuff }#{ data[ 0 ] }"
|
927
957
|
|
928
|
-
|
929
|
-
|
930
|
-
|
958
|
+
if data.bytesize == 1 then
|
959
|
+
# puts "debug add atun.lbuff a byte #{ data.inspect }"
|
960
|
+
atun_info[ :lbuff ] = lbuff
|
961
|
+
return
|
962
|
+
end
|
963
|
+
|
964
|
+
# 使用长度缓存
|
965
|
+
len = lbuff.unpack( 'n' ).first
|
966
|
+
atun_info[ :lbuff ].clear
|
967
|
+
data = data[ 1..-1 ]
|
968
|
+
else
|
969
|
+
# 使用长度缓存
|
970
|
+
len = lbuff.unpack( 'n' ).first
|
971
|
+
atun_info[ :lbuff ].clear
|
972
|
+
end
|
931
973
|
end
|
932
974
|
|
933
975
|
chunk = data[ 0, len ]
|
@@ -935,7 +977,7 @@ module Girl
|
|
935
977
|
|
936
978
|
if chunk_size == len then
|
937
979
|
# 取完整了
|
938
|
-
chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
|
980
|
+
chunk = @custom.decode( "#{ atun_info[ :rbuff ] }#{ chunk }" )
|
939
981
|
# puts "debug decode and add dst.wbuff #{ chunk.bytesize }"
|
940
982
|
add_dst_wbuff( dst, chunk )
|
941
983
|
atun_info[ :rbuff ].clear
|
@@ -1009,8 +1051,17 @@ module Girl
|
|
1009
1051
|
btun_info[ :domain_port ] = dst_info[ :domain_port ]
|
1010
1052
|
|
1011
1053
|
unless dst_info[ :rbuff ].empty? then
|
1012
|
-
|
1013
|
-
|
1054
|
+
data2 = ''
|
1055
|
+
|
1056
|
+
until dst_info[ :rbuff ].empty? do
|
1057
|
+
_data = dst_info[ :rbuff ][ 0, CHUNK_SIZE ]
|
1058
|
+
data_size = _data.bytesize
|
1059
|
+
# puts "debug move dst.rbuff to btun.wbuff"
|
1060
|
+
data2 << pack_a_chunk( _data )
|
1061
|
+
dst_info[ :rbuff ] = dst_info[ :rbuff ][ data_size..-1 ]
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
add_btun_wbuff( btun, data2 )
|
1014
1065
|
end
|
1015
1066
|
|
1016
1067
|
dst_info[ :btun ] = btun
|
@@ -1026,6 +1077,7 @@ module Girl
|
|
1026
1077
|
end
|
1027
1078
|
|
1028
1079
|
dst_info = @dst_infos[ dst ]
|
1080
|
+
dst_info[ :connected ] = true
|
1029
1081
|
atun = dst_info[ :atun ]
|
1030
1082
|
data = dst_info[ :wbuff ]
|
1031
1083
|
|
data/lib/girl/relay.rb
CHANGED
data/lib/girl/relay_worker.rb
CHANGED
@@ -13,7 +13,6 @@ module Girl
|
|
13
13
|
@directs = directs
|
14
14
|
@remotes = remotes
|
15
15
|
@custom = Girl::ProxyCustom.new( im )
|
16
|
-
@resolv_custom = Girl::ResolvCustom.new
|
17
16
|
@reads = []
|
18
17
|
@writes = []
|
19
18
|
@closing_rsvs = []
|
@@ -24,7 +23,7 @@ module Girl
|
|
24
23
|
@resume_srcs = []
|
25
24
|
@resume_dsts = []
|
26
25
|
@resume_btuns = []
|
27
|
-
@pending_srcs = [] #
|
26
|
+
@pending_srcs = [] # 还没得到atund和btund地址,暂存的src
|
28
27
|
@roles = ConcurrentHash.new # sock => :dotr / :resolv / :rsv / :redir / :proxy / :src / :dst / :atun / :btun
|
29
28
|
@rsv_infos = ConcurrentHash.new # rsv => {}
|
30
29
|
@src_infos = ConcurrentHash.new # src => {}
|
@@ -445,9 +444,8 @@ module Girl
|
|
445
444
|
return if src.closed?
|
446
445
|
src_info = @src_infos[ src ]
|
447
446
|
|
448
|
-
if
|
449
|
-
|| ip_info.
|
450
|
-
|| ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) then
|
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
|
451
449
|
puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
|
452
450
|
add_closing_src( src )
|
453
451
|
return
|
@@ -464,7 +462,6 @@ module Girl
|
|
464
462
|
is_direct = @is_direct_caches[ ip_info.ip_address ]
|
465
463
|
else
|
466
464
|
is_direct = @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
|
467
|
-
# 判断直连耗时较长(树莓派 0.27秒),这里可能切去主线程,回来src可能已关闭
|
468
465
|
puts "p#{ Process.pid } #{ Time.new } cache is direct #{ ip_info.ip_address } #{ is_direct }"
|
469
466
|
@is_direct_caches[ ip_info.ip_address ] = is_direct
|
470
467
|
end
|
@@ -473,7 +470,6 @@ module Girl
|
|
473
470
|
# puts "debug #{ ip_info.inspect } hit directs"
|
474
471
|
new_a_dst( src, ip_info )
|
475
472
|
else
|
476
|
-
# 走远端
|
477
473
|
# puts "debug #{ ip_info.inspect } go tunnel"
|
478
474
|
set_proxy_type_tunnel( src )
|
479
475
|
end
|
@@ -524,8 +520,8 @@ module Girl
|
|
524
520
|
if @ctl && !@ctl.closed? then
|
525
521
|
last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
|
526
522
|
|
527
|
-
if now - last_recv_at >=
|
528
|
-
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 }"
|
529
525
|
@ctl_info[ :closing ] = true
|
530
526
|
next_tick
|
531
527
|
end
|
@@ -541,9 +537,24 @@ module Girl
|
|
541
537
|
@src_infos.each do | src, src_info |
|
542
538
|
last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
|
543
539
|
last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
|
544
|
-
expire_after = ( src_info[ :dst ] || src_info[ :tun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
|
545
540
|
|
546
|
-
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
|
547
558
|
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
|
548
559
|
add_closing_src( src )
|
549
560
|
|
@@ -572,7 +583,7 @@ module Girl
|
|
572
583
|
if !dst.closed? then
|
573
584
|
dst_info = @dst_infos[ dst ]
|
574
585
|
|
575
|
-
if dst_info[ :wbuff ].
|
586
|
+
if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
|
576
587
|
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
577
588
|
add_resume_src( src )
|
578
589
|
end
|
@@ -583,7 +594,7 @@ module Girl
|
|
583
594
|
if atun && !atun.closed? then
|
584
595
|
atun_info = @atun_infos[ atun ]
|
585
596
|
|
586
|
-
if atun_info[ :wbuff ].
|
597
|
+
if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
|
587
598
|
puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
|
588
599
|
add_resume_src( src )
|
589
600
|
end
|
@@ -598,7 +609,7 @@ module Girl
|
|
598
609
|
if src && !src.closed? then
|
599
610
|
src_info = @src_infos[ src ]
|
600
611
|
|
601
|
-
if src_info[ :wbuff ].
|
612
|
+
if src_info[ :wbuff ].bytesize < RESUME_BELOW then
|
602
613
|
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
|
603
614
|
add_resume_dst( dst )
|
604
615
|
end
|
@@ -612,7 +623,7 @@ module Girl
|
|
612
623
|
if src && !src.closed? then
|
613
624
|
src_info = @src_infos[ src ]
|
614
625
|
|
615
|
-
if src_info[ :wbuff ].
|
626
|
+
if src_info[ :wbuff ].bytesize < RESUME_BELOW then
|
616
627
|
puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
|
617
628
|
add_resume_btun( btun )
|
618
629
|
end
|
@@ -656,14 +667,14 @@ module Girl
|
|
656
667
|
domain = src_info[ :destination_domain ]
|
657
668
|
destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
|
658
669
|
dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
659
|
-
dst.setsockopt( Socket::
|
670
|
+
dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
660
671
|
|
661
672
|
begin
|
662
673
|
dst.connect_nonblock( destination_addr )
|
663
674
|
rescue IO::WaitWritable
|
664
675
|
# connect nonblock 必抛 wait writable
|
665
676
|
rescue Exception => e
|
666
|
-
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 }"
|
667
678
|
dst.close
|
668
679
|
add_closing_src( src )
|
669
680
|
return
|
@@ -678,15 +689,17 @@ module Girl
|
|
678
689
|
}
|
679
690
|
|
680
691
|
@dst_infos[ dst ] = dst_info
|
681
|
-
add_read( dst, :dst )
|
682
692
|
src_info[ :proxy_type ] = :direct
|
683
693
|
src_info[ :dst ] = dst
|
694
|
+
src_info[ :dst_created_at ] = Time.new
|
684
695
|
|
685
696
|
if src_info[ :rbuff ] then
|
686
697
|
# puts "debug move src.rbuff to dst.wbuff"
|
687
698
|
dst_info[ :wbuff ] << src_info[ :rbuff ]
|
688
|
-
add_write( dst )
|
689
699
|
end
|
700
|
+
|
701
|
+
add_read( dst, :dst )
|
702
|
+
add_write( dst )
|
690
703
|
end
|
691
704
|
|
692
705
|
##
|
@@ -722,6 +735,7 @@ module Girl
|
|
722
735
|
#
|
723
736
|
def new_a_redir( redir_port )
|
724
737
|
redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
738
|
+
redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
725
739
|
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
726
740
|
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
727
741
|
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
@@ -754,13 +768,13 @@ module Girl
|
|
754
768
|
rsv.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
755
769
|
|
756
770
|
if @qnames.any? { | qname | data.include?( qname ) } then
|
757
|
-
data = @
|
771
|
+
data = @custom.encode( data )
|
758
772
|
to_addr = @resolvd_addr
|
759
773
|
else
|
760
774
|
to_addr = @nameserver_addr
|
761
775
|
end
|
762
776
|
|
763
|
-
puts "
|
777
|
+
# puts "debug new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
|
764
778
|
|
765
779
|
@rsv_infos[ rsv ] = {
|
766
780
|
src_addr: src_addr,
|
@@ -774,6 +788,7 @@ module Girl
|
|
774
788
|
# new tuns
|
775
789
|
#
|
776
790
|
def new_tuns( src_id, dst_id )
|
791
|
+
return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil?
|
777
792
|
src = @srcs[ src_id ]
|
778
793
|
return if src.nil? || src.closed?
|
779
794
|
src_info = @src_infos[ src ]
|
@@ -781,23 +796,25 @@ module Girl
|
|
781
796
|
|
782
797
|
# puts "debug new atun and btun"
|
783
798
|
atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
799
|
+
atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
784
800
|
|
785
801
|
begin
|
786
802
|
atun.connect_nonblock( @ctl_info[ :atund_addr ] )
|
787
803
|
rescue IO::WaitWritable
|
788
804
|
rescue Exception => e
|
789
|
-
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }
|
805
|
+
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
|
790
806
|
atun.close
|
791
807
|
return
|
792
808
|
end
|
793
809
|
|
794
810
|
btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
811
|
+
btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
795
812
|
|
796
813
|
begin
|
797
814
|
btun.connect_nonblock( @ctl_info[ :btund_addr ] )
|
798
815
|
rescue IO::WaitWritable
|
799
816
|
rescue Exception => e
|
800
|
-
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }
|
817
|
+
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
|
801
818
|
btun.close
|
802
819
|
return
|
803
820
|
end
|
@@ -806,7 +823,7 @@ module Girl
|
|
806
823
|
atun_wbuff = [ dst_id ].pack( 'n' )
|
807
824
|
|
808
825
|
until src_info[ :rbuff ].empty? do
|
809
|
-
data = src_info[ :rbuff ][ 0,
|
826
|
+
data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
|
810
827
|
data_size = data.bytesize
|
811
828
|
# puts "debug move src.rbuff #{ data_size } to atun.wbuff"
|
812
829
|
atun_wbuff << pack_a_chunk( data )
|
@@ -827,7 +844,8 @@ module Girl
|
|
827
844
|
domain: domain, # 目的地
|
828
845
|
wbuff: btun_wbuff, # 写前
|
829
846
|
rbuff: '', # 暂存当前块没收全的流量
|
830
|
-
wait_bytes: 0
|
847
|
+
wait_bytes: 0, # 还差多少字节收全当前块
|
848
|
+
lbuff: '' # 流量截断在长度前缀处
|
831
849
|
}
|
832
850
|
|
833
851
|
src_info[ :dst_id ] = dst_id
|
@@ -860,6 +878,7 @@ module Girl
|
|
860
878
|
#
|
861
879
|
def send_ctlmsg( data )
|
862
880
|
return if @ctl.nil? || @ctl.closed?
|
881
|
+
data = @custom.encode( data )
|
863
882
|
|
864
883
|
begin
|
865
884
|
@ctl.sendmsg( data, 0, @proxyd_addr )
|
@@ -888,9 +907,7 @@ module Girl
|
|
888
907
|
def send_data( sock, to_addr, data )
|
889
908
|
begin
|
890
909
|
sock.sendmsg( data, 0, to_addr )
|
891
|
-
rescue
|
892
|
-
print 'w'
|
893
|
-
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
910
|
+
rescue Exception => e
|
894
911
|
puts "p#{ Process.pid } #{ Time.new } sendmsg to #{ to_addr.ip_unpack.inspect } #{ e.class }"
|
895
912
|
end
|
896
913
|
end
|
@@ -933,30 +950,11 @@ module Girl
|
|
933
950
|
add_write( src )
|
934
951
|
end
|
935
952
|
|
936
|
-
##
|
937
|
-
# sub http request
|
938
|
-
#
|
939
|
-
def sub_http_request( data )
|
940
|
-
lines = data.split( "\r\n" )
|
941
|
-
|
942
|
-
return [ data, nil ] if lines.empty?
|
943
|
-
|
944
|
-
method, url, proto = lines.first.split( ' ' )
|
945
|
-
|
946
|
-
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
947
|
-
domain_port = url.split( '/' )[ 2 ]
|
948
|
-
data = data.sub( "http://#{ domain_port }", '' )
|
949
|
-
# puts "debug subed #{ data.inspect } #{ domain_port }"
|
950
|
-
end
|
951
|
-
|
952
|
-
[ data, domain_port ]
|
953
|
-
end
|
954
|
-
|
955
953
|
##
|
956
954
|
# read dotr
|
957
955
|
#
|
958
956
|
def read_dotr( dotr )
|
959
|
-
dotr.read_nonblock(
|
957
|
+
dotr.read_nonblock( READ_SIZE )
|
960
958
|
|
961
959
|
if @ctl_info && @ctl_info[ :closing ] then
|
962
960
|
send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
|
@@ -1018,7 +1016,7 @@ module Girl
|
|
1018
1016
|
# puts "debug rsv recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
|
1019
1017
|
|
1020
1018
|
if addrinfo.to_sockaddr == @resolvd_addr then
|
1021
|
-
data = @
|
1019
|
+
data = @custom.decode( data )
|
1022
1020
|
end
|
1023
1021
|
|
1024
1022
|
rsv_info = @rsv_infos[ rsv ]
|
@@ -1061,6 +1059,8 @@ module Girl
|
|
1061
1059
|
destination_port: dest_port, # 目的地端口
|
1062
1060
|
rbuff: '', # 读到的流量
|
1063
1061
|
dst: nil, # :direct的场合,对应的dst
|
1062
|
+
dst_created_at: nil, # :direct的场合,对应的dst的创建时间
|
1063
|
+
dst_connected: false, # :direct的场合,对应的dst是否已连接
|
1064
1064
|
ctl: nil, # :tunnel的场合,对应的ctl
|
1065
1065
|
atun: nil, # :tunnel的场合,对应的atun
|
1066
1066
|
btun: nil, # :tunnel的场合,对应的btun
|
@@ -1093,11 +1093,12 @@ module Girl
|
|
1093
1093
|
return
|
1094
1094
|
end
|
1095
1095
|
|
1096
|
+
data = @custom.decode( data )
|
1096
1097
|
ctl_num = data[ 0 ].unpack( 'C' ).first
|
1097
1098
|
|
1098
1099
|
case ctl_num
|
1099
1100
|
when TUND_PORT then
|
1100
|
-
return if @ctl_info[ :atund_addr ] || data.
|
1101
|
+
return if @ctl_info[ :atund_addr ] || data.bytesize != 5
|
1101
1102
|
atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
|
1102
1103
|
puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
|
1103
1104
|
@ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
|
@@ -1111,14 +1112,14 @@ module Girl
|
|
1111
1112
|
@pending_srcs.clear
|
1112
1113
|
end
|
1113
1114
|
when PAIRED then
|
1114
|
-
return if
|
1115
|
+
return if data.bytesize != 11
|
1115
1116
|
src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
|
1116
1117
|
# puts "debug got paired #{ src_id } #{ dst_id }"
|
1117
1118
|
@ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
|
1118
1119
|
@ctl_info[ :last_recv_at ] = Time.new
|
1119
1120
|
new_tuns( src_id, dst_id )
|
1120
1121
|
when UNKNOWN_CTL_ADDR then
|
1121
|
-
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr
|
1122
|
+
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
|
1122
1123
|
close_ctl( ctl )
|
1123
1124
|
end
|
1124
1125
|
end
|
@@ -1135,7 +1136,7 @@ module Girl
|
|
1135
1136
|
src_info = @src_infos[ src ]
|
1136
1137
|
|
1137
1138
|
begin
|
1138
|
-
data = src.read_nonblock(
|
1139
|
+
data = src.read_nonblock( CHUNK_SIZE )
|
1139
1140
|
rescue IO::WaitReadable
|
1140
1141
|
print 'r'
|
1141
1142
|
return
|
@@ -1197,7 +1198,7 @@ module Girl
|
|
1197
1198
|
src = dst_info[ :src ]
|
1198
1199
|
|
1199
1200
|
begin
|
1200
|
-
data = dst.read_nonblock(
|
1201
|
+
data = dst.read_nonblock( CHUNK_SIZE )
|
1201
1202
|
rescue IO::WaitReadable
|
1202
1203
|
print 'r'
|
1203
1204
|
return
|
@@ -1238,22 +1239,44 @@ module Girl
|
|
1238
1239
|
end
|
1239
1240
|
|
1240
1241
|
until data.empty? do
|
1241
|
-
rbuff = btun_info[ :rbuff ]
|
1242
1242
|
wait_bytes = btun_info[ :wait_bytes ]
|
1243
1243
|
|
1244
1244
|
if wait_bytes > 0 then
|
1245
1245
|
len = wait_bytes
|
1246
1246
|
# puts "debug wait bytes #{ len }"
|
1247
1247
|
else
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
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
|
1253
1258
|
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
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
|
1257
1280
|
end
|
1258
1281
|
|
1259
1282
|
chunk = data[ 0, len ]
|
@@ -1261,7 +1284,7 @@ module Girl
|
|
1261
1284
|
|
1262
1285
|
if chunk_size == len then
|
1263
1286
|
# 取完整了
|
1264
|
-
chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
|
1287
|
+
chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
|
1265
1288
|
# puts "debug read btun decoded #{ chunk.bytesize }"
|
1266
1289
|
add_src_wbuff( src, chunk )
|
1267
1290
|
btun_info[ :rbuff ] = ''
|
@@ -1340,6 +1363,12 @@ module Girl
|
|
1340
1363
|
|
1341
1364
|
dst_info = @dst_infos[ dst ]
|
1342
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
|
+
|
1343
1372
|
data = dst_info[ :wbuff ]
|
1344
1373
|
|
1345
1374
|
# 写前为空,处理关闭写
|
@@ -1370,7 +1399,6 @@ module Girl
|
|
1370
1399
|
dst_info[ :wbuff ] = data
|
1371
1400
|
|
1372
1401
|
unless src.closed? then
|
1373
|
-
src_info = @src_infos[ src ]
|
1374
1402
|
src_info[ :last_sent_at ] = Time.new
|
1375
1403
|
end
|
1376
1404
|
end
|