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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d3b294765df9759f671cd5916a4315aa5872a85e42ea9739d8e2bd409f55f49
|
4
|
+
data.tar.gz: 8405a9e93e8c038e757c3a191c40c3801ff34e9ce593be0b0187ee728cb70fa7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b09b4c9b12257b9fc8672eace67cd89bfac89b5032ffb6ccf2a6810342a3c09e45ba0b6658b86cafd7d671fdeaf0235de794a3f0b356c2835a3c5248de9743b
|
7
|
+
data.tar.gz: 5e16e91e812c7c53d3fbb47e4c16fc90f7f922a011d4983b6ee955306fd88496b7965e0f02c7ab78b9db80e25a4468c483dffab634d009d1f459d1a16c589a8f
|
data/girl.gemspec
CHANGED
data/lib/girl/concurrent_hash.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
class ConcurrentHash < Hash
|
2
|
-
def initialize
|
3
|
-
super
|
4
|
-
@mutex = Mutex.new
|
5
|
-
end
|
6
|
-
|
7
|
-
def []( *args )
|
8
|
-
@mutex.synchronize { super }
|
9
|
-
end
|
10
|
-
|
11
|
-
def []=( *args )
|
12
|
-
@mutex.synchronize { super }
|
13
|
-
end
|
14
|
-
|
15
|
-
def delete( *args )
|
16
|
-
@mutex.synchronize { super }
|
17
|
-
end
|
18
|
-
|
19
|
-
def each( *args )
|
20
|
-
@mutex.synchronize { super }
|
21
|
-
end
|
22
|
-
|
23
|
-
def clear( *args )
|
24
|
-
@mutex.synchronize { super }
|
25
|
-
end
|
26
|
-
end
|
1
|
+
class ConcurrentHash < Hash
|
2
|
+
def initialize
|
3
|
+
super
|
4
|
+
@mutex = Mutex.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def []( *args )
|
8
|
+
@mutex.synchronize { super }
|
9
|
+
end
|
10
|
+
|
11
|
+
def []=( *args )
|
12
|
+
@mutex.synchronize { super }
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete( *args )
|
16
|
+
@mutex.synchronize { super }
|
17
|
+
end
|
18
|
+
|
19
|
+
def each( *args )
|
20
|
+
@mutex.synchronize { super }
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear( *args )
|
24
|
+
@mutex.synchronize { super }
|
25
|
+
end
|
26
|
+
end
|
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.rb
CHANGED
@@ -14,8 +14,8 @@ require 'socket'
|
|
14
14
|
#
|
15
15
|
=begin
|
16
16
|
C: 1 hello -> hello
|
17
|
-
2 tund port -> n:
|
18
|
-
3 a new source -> Q>: src id ->
|
17
|
+
2 tund port -> n: atund port -> n: btund port
|
18
|
+
3 a new source -> Q>: src id -> destination
|
19
19
|
4 paired -> Q>: src id -> n: dst id
|
20
20
|
5 dest status NOT USE
|
21
21
|
6 source status NOT USE
|
@@ -32,13 +32,11 @@ C: 1 hello -> hello
|
|
32
32
|
17 continue NOT USE
|
33
33
|
18 is resend ready NOT USE
|
34
34
|
19 resend ready NOT USE
|
35
|
-
20 resolv
|
36
|
-
21 resolved
|
35
|
+
20 resolv NOT USE
|
36
|
+
21 resolved NOT USE
|
37
37
|
22 heartbeat NOT USE
|
38
38
|
23 unknown ctl addr
|
39
39
|
24 ctl fin
|
40
|
-
25 source eof -> Q>: dst id
|
41
|
-
26 dest eof -> Q>: src id
|
42
40
|
101 traff infos
|
43
41
|
101 traff infos -> [ C: im len -> im -> Q>: traff in -> Q>: traff out ]
|
44
42
|
=end
|
data/lib/girl/proxy_custom.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
require 'girl/custom'
|
2
|
-
|
3
|
-
module Girl
|
4
|
-
class ProxyCustom
|
5
|
-
include Custom
|
6
|
-
|
7
|
-
def initialize( im )
|
8
|
-
@im = im
|
9
|
-
end
|
10
|
-
|
11
|
-
def hello
|
12
|
-
@im
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
1
|
+
require 'girl/custom'
|
2
|
+
|
3
|
+
module Girl
|
4
|
+
class ProxyCustom
|
5
|
+
include Custom
|
6
|
+
|
7
|
+
def initialize( im )
|
8
|
+
@im = im
|
9
|
+
end
|
10
|
+
|
11
|
+
def hello
|
12
|
+
@im
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -6,6 +6,7 @@ module Girl
|
|
6
6
|
#
|
7
7
|
def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
|
8
8
|
@proxyd_host = proxyd_host
|
9
|
+
@proxyd_port = proxyd_port
|
9
10
|
@proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
|
10
11
|
@directs = directs
|
11
12
|
@remotes = remotes
|
@@ -19,7 +20,7 @@ module Girl
|
|
19
20
|
@resume_srcs = []
|
20
21
|
@resume_dsts = []
|
21
22
|
@resume_btuns = []
|
22
|
-
@pending_srcs = [] #
|
23
|
+
@pending_srcs = [] # 还没得到atund和btund地址,暂存的src
|
23
24
|
@roles = ConcurrentHash.new # sock => :dotr / :redir / :ctl / :src / :dst / :atun / :btun
|
24
25
|
@src_infos = ConcurrentHash.new # src => {}
|
25
26
|
@dst_infos = ConcurrentHash.new # dst => {}
|
@@ -296,7 +297,7 @@ module Girl
|
|
296
297
|
close_sock( atun )
|
297
298
|
atun_info = @atun_infos.delete( atun )
|
298
299
|
src = atun_info[ :src ]
|
299
|
-
|
300
|
+
|
300
301
|
if src then
|
301
302
|
@paused_srcs.delete( src )
|
302
303
|
end
|
@@ -430,9 +431,8 @@ module Girl
|
|
430
431
|
return if src.closed?
|
431
432
|
src_info = @src_infos[ src ]
|
432
433
|
|
433
|
-
if
|
434
|
-
|| ip_info.
|
435
|
-
|| ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) then
|
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
|
436
436
|
puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
|
437
437
|
add_closing_src( src )
|
438
438
|
return
|
@@ -449,7 +449,6 @@ module Girl
|
|
449
449
|
is_direct = @is_direct_caches[ ip_info.ip_address ]
|
450
450
|
else
|
451
451
|
is_direct = @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
|
452
|
-
# 判断直连耗时较长(树莓派 0.27秒),这里可能切去主线程,回来src可能已关闭
|
453
452
|
puts "p#{ Process.pid } #{ Time.new } cache is direct #{ ip_info.ip_address } #{ is_direct }"
|
454
453
|
@is_direct_caches[ ip_info.ip_address ] = is_direct
|
455
454
|
end
|
@@ -458,7 +457,6 @@ module Girl
|
|
458
457
|
# puts "debug #{ ip_info.inspect } hit directs"
|
459
458
|
new_a_dst( src, ip_info )
|
460
459
|
else
|
461
|
-
# 走远端
|
462
460
|
# puts "debug #{ ip_info.inspect } go tunnel"
|
463
461
|
set_proxy_type_tunnel( src )
|
464
462
|
end
|
@@ -509,8 +507,8 @@ module Girl
|
|
509
507
|
if @ctl && !@ctl.closed? then
|
510
508
|
last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
|
511
509
|
|
512
|
-
if now - last_recv_at >=
|
513
|
-
puts "p#{ Process.pid } #{ Time.new } expire ctl"
|
510
|
+
if now - last_recv_at >= EXPIRE_CTL then
|
511
|
+
puts "p#{ Process.pid } #{ Time.new } expire ctl #{ EXPIRE_CTL }"
|
514
512
|
@ctl_info[ :closing ] = true
|
515
513
|
next_tick
|
516
514
|
end
|
@@ -519,9 +517,24 @@ module Girl
|
|
519
517
|
@src_infos.each do | src, src_info |
|
520
518
|
last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
|
521
519
|
last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
|
522
|
-
expire_after = ( src_info[ :dst ] || src_info[ :atun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
|
523
520
|
|
524
|
-
if
|
521
|
+
if src_info[ :dst ] then
|
522
|
+
if src_info[ :dst_connected ] then
|
523
|
+
expire_after = EXPIRE_AFTER
|
524
|
+
is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
|
525
|
+
else
|
526
|
+
expire_after = EXPIRE_CONNECTING
|
527
|
+
is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
|
528
|
+
end
|
529
|
+
elsif src_info[ :atun ] then
|
530
|
+
expire_after = EXPIRE_AFTER
|
531
|
+
is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
|
532
|
+
else
|
533
|
+
expire_after = EXPIRE_NEW
|
534
|
+
is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
|
535
|
+
end
|
536
|
+
|
537
|
+
if is_expire then
|
525
538
|
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
|
526
539
|
add_closing_src( src )
|
527
540
|
|
@@ -550,7 +563,7 @@ module Girl
|
|
550
563
|
if !dst.closed? then
|
551
564
|
dst_info = @dst_infos[ dst ]
|
552
565
|
|
553
|
-
if dst_info[ :wbuff ].
|
566
|
+
if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
|
554
567
|
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
555
568
|
add_resume_src( src )
|
556
569
|
end
|
@@ -561,7 +574,7 @@ module Girl
|
|
561
574
|
if atun && !atun.closed? then
|
562
575
|
atun_info = @atun_infos[ atun ]
|
563
576
|
|
564
|
-
if atun_info[ :wbuff ].
|
577
|
+
if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
|
565
578
|
puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
|
566
579
|
add_resume_src( src )
|
567
580
|
end
|
@@ -576,7 +589,7 @@ module Girl
|
|
576
589
|
if src && !src.closed? then
|
577
590
|
src_info = @src_infos[ src ]
|
578
591
|
|
579
|
-
if src_info[ :wbuff ].
|
592
|
+
if src_info[ :wbuff ].bytesize < RESUME_BELOW then
|
580
593
|
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
|
581
594
|
add_resume_dst( dst )
|
582
595
|
end
|
@@ -590,7 +603,7 @@ module Girl
|
|
590
603
|
if src && !src.closed? then
|
591
604
|
src_info = @src_infos[ src ]
|
592
605
|
|
593
|
-
if src_info[ :wbuff ].
|
606
|
+
if src_info[ :wbuff ].bytesize < RESUME_BELOW then
|
594
607
|
puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
|
595
608
|
add_resume_btun( btun )
|
596
609
|
end
|
@@ -634,13 +647,14 @@ module Girl
|
|
634
647
|
domain = src_info[ :destination_domain ]
|
635
648
|
destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
|
636
649
|
dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
650
|
+
dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
637
651
|
|
638
652
|
begin
|
639
653
|
dst.connect_nonblock( destination_addr )
|
640
654
|
rescue IO::WaitWritable
|
641
655
|
# connect nonblock 必抛 wait writable
|
642
656
|
rescue Exception => e
|
643
|
-
puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }
|
657
|
+
puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
|
644
658
|
dst.close
|
645
659
|
add_closing_src( src )
|
646
660
|
return
|
@@ -655,9 +669,9 @@ module Girl
|
|
655
669
|
}
|
656
670
|
|
657
671
|
@dst_infos[ dst ] = dst_info
|
658
|
-
add_read( dst, :dst )
|
659
672
|
src_info[ :proxy_type ] = :direct
|
660
673
|
src_info[ :dst ] = dst
|
674
|
+
src_info[ :dst_created_at ] = Time.new
|
661
675
|
|
662
676
|
if src_info[ :proxy_proto ] == :http then
|
663
677
|
if src_info[ :is_connect ] then
|
@@ -666,11 +680,13 @@ module Girl
|
|
666
680
|
elsif src_info[ :rbuff ] then
|
667
681
|
# puts "debug move src.rbuff to dst.wbuff"
|
668
682
|
dst_info[ :wbuff ] << src_info[ :rbuff ]
|
669
|
-
add_write( dst )
|
670
683
|
end
|
671
684
|
elsif src_info[ :proxy_proto ] == :socks5 then
|
672
685
|
add_socks5_conn_reply( src )
|
673
686
|
end
|
687
|
+
|
688
|
+
add_read( dst, :dst )
|
689
|
+
add_write( dst )
|
674
690
|
end
|
675
691
|
|
676
692
|
##
|
@@ -706,6 +722,7 @@ module Girl
|
|
706
722
|
#
|
707
723
|
def new_a_redir( redir_port )
|
708
724
|
redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
725
|
+
redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
709
726
|
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
710
727
|
|
711
728
|
if RUBY_PLATFORM.include?( 'linux' ) then
|
@@ -724,6 +741,7 @@ module Girl
|
|
724
741
|
# new tuns
|
725
742
|
#
|
726
743
|
def new_tuns( src_id, dst_id )
|
744
|
+
return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil?
|
727
745
|
src = @srcs[ src_id ]
|
728
746
|
return if src.nil? || src.closed?
|
729
747
|
src_info = @src_infos[ src ]
|
@@ -731,23 +749,25 @@ module Girl
|
|
731
749
|
|
732
750
|
# puts "debug new atun and btun"
|
733
751
|
atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
752
|
+
atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
734
753
|
|
735
754
|
begin
|
736
755
|
atun.connect_nonblock( @ctl_info[ :atund_addr ] )
|
737
756
|
rescue IO::WaitWritable
|
738
757
|
rescue Exception => e
|
739
|
-
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }
|
758
|
+
puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
|
740
759
|
atun.close
|
741
760
|
return
|
742
761
|
end
|
743
762
|
|
744
763
|
btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
764
|
+
btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
|
745
765
|
|
746
766
|
begin
|
747
767
|
btun.connect_nonblock( @ctl_info[ :btund_addr ] )
|
748
768
|
rescue IO::WaitWritable
|
749
769
|
rescue Exception => e
|
750
|
-
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }
|
770
|
+
puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
|
751
771
|
btun.close
|
752
772
|
return
|
753
773
|
end
|
@@ -756,7 +776,7 @@ module Girl
|
|
756
776
|
atun_wbuff = [ dst_id ].pack( 'n' )
|
757
777
|
|
758
778
|
until src_info[ :rbuff ].empty? do
|
759
|
-
data = src_info[ :rbuff ][ 0,
|
779
|
+
data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
|
760
780
|
data_size = data.bytesize
|
761
781
|
# puts "debug move src.rbuff #{ data_size } to atun.wbuff"
|
762
782
|
atun_wbuff << pack_a_chunk( data )
|
@@ -777,7 +797,8 @@ module Girl
|
|
777
797
|
domain: domain, # 目的地
|
778
798
|
wbuff: btun_wbuff, # 写前
|
779
799
|
rbuff: '', # 暂存当前块没收全的流量
|
780
|
-
wait_bytes: 0
|
800
|
+
wait_bytes: 0, # 还差多少字节收全当前块
|
801
|
+
lbuff: '' # 流量截断在长度前缀处
|
781
802
|
}
|
782
803
|
|
783
804
|
src_info[ :dst_id ] = dst_id
|
@@ -809,7 +830,6 @@ module Girl
|
|
809
830
|
# pack a chunk
|
810
831
|
#
|
811
832
|
def pack_a_chunk( data )
|
812
|
-
# puts "debug pack a chunk"
|
813
833
|
data = @custom.encode( data )
|
814
834
|
"#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
|
815
835
|
end
|
@@ -864,6 +884,7 @@ module Girl
|
|
864
884
|
#
|
865
885
|
def send_ctlmsg( data )
|
866
886
|
return if @ctl.nil? || @ctl.closed?
|
887
|
+
data = @custom.encode( data )
|
867
888
|
|
868
889
|
begin
|
869
890
|
@ctl.sendmsg( data, 0, @proxyd_addr )
|
@@ -925,30 +946,11 @@ module Girl
|
|
925
946
|
add_write( src )
|
926
947
|
end
|
927
948
|
|
928
|
-
##
|
929
|
-
# sub http request
|
930
|
-
#
|
931
|
-
def sub_http_request( data )
|
932
|
-
lines = data.split( "\r\n" )
|
933
|
-
|
934
|
-
return [ data, nil ] if lines.empty?
|
935
|
-
|
936
|
-
method, url, proto = lines.first.split( ' ' )
|
937
|
-
|
938
|
-
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
939
|
-
domain_port = url.split( '/' )[ 2 ]
|
940
|
-
data = data.sub( "http://#{ domain_port }", '' )
|
941
|
-
# puts "debug subed #{ data.inspect } #{ domain_port }"
|
942
|
-
end
|
943
|
-
|
944
|
-
[ data, domain_port ]
|
945
|
-
end
|
946
|
-
|
947
949
|
##
|
948
950
|
# read dotr
|
949
951
|
#
|
950
952
|
def read_dotr( dotr )
|
951
|
-
dotr.read_nonblock(
|
953
|
+
dotr.read_nonblock( READ_SIZE )
|
952
954
|
|
953
955
|
if @ctl_info && @ctl_info[ :closing ] then
|
954
956
|
send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
|
@@ -1012,6 +1014,8 @@ module Girl
|
|
1012
1014
|
is_connect: true, # 代理协议是http的场合,是否是CONNECT
|
1013
1015
|
rbuff: '', # 读到的流量
|
1014
1016
|
dst: nil, # :direct的场合,对应的dst
|
1017
|
+
dst_created_at: nil, # :direct的场合,对应的dst的创建时间
|
1018
|
+
dst_connected: false, # :direct的场合,对应的dst是否已连接
|
1015
1019
|
ctl: nil, # :tunnel的场合,对应的ctl
|
1016
1020
|
atun: nil, # :tunnel的场合,对应的atun
|
1017
1021
|
btun: nil, # :tunnel的场合,对应的btun
|
@@ -1042,11 +1046,12 @@ module Girl
|
|
1042
1046
|
return
|
1043
1047
|
end
|
1044
1048
|
|
1049
|
+
data = @custom.decode( data )
|
1045
1050
|
ctl_num = data[ 0 ].unpack( 'C' ).first
|
1046
1051
|
|
1047
1052
|
case ctl_num
|
1048
1053
|
when TUND_PORT then
|
1049
|
-
return if @ctl_info[ :atund_addr ] || data.
|
1054
|
+
return if @ctl_info[ :atund_addr ] || data.bytesize != 5
|
1050
1055
|
atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
|
1051
1056
|
puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
|
1052
1057
|
@ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
|
@@ -1060,14 +1065,14 @@ module Girl
|
|
1060
1065
|
@pending_srcs.clear
|
1061
1066
|
end
|
1062
1067
|
when PAIRED then
|
1063
|
-
return if
|
1068
|
+
return if data.bytesize != 11
|
1064
1069
|
src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
|
1065
1070
|
# puts "debug got paired #{ src_id } #{ dst_id }"
|
1066
1071
|
@ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
|
1067
1072
|
@ctl_info[ :last_recv_at ] = Time.new
|
1068
1073
|
new_tuns( src_id, dst_id )
|
1069
1074
|
when UNKNOWN_CTL_ADDR then
|
1070
|
-
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr
|
1075
|
+
puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
|
1071
1076
|
close_ctl( ctl )
|
1072
1077
|
end
|
1073
1078
|
end
|
@@ -1084,7 +1089,7 @@ module Girl
|
|
1084
1089
|
src_info = @src_infos[ src ]
|
1085
1090
|
|
1086
1091
|
begin
|
1087
|
-
data = src.read_nonblock(
|
1092
|
+
data = src.read_nonblock( CHUNK_SIZE )
|
1088
1093
|
rescue IO::WaitReadable
|
1089
1094
|
print 'r'
|
1090
1095
|
return
|
@@ -1159,7 +1164,16 @@ module Girl
|
|
1159
1164
|
return
|
1160
1165
|
end
|
1161
1166
|
|
1162
|
-
|
1167
|
+
lines = data.split( "\r\n" )
|
1168
|
+
|
1169
|
+
unless lines.empty? then
|
1170
|
+
method, url, proto = lines.first.split( ' ' )
|
1171
|
+
|
1172
|
+
if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
|
1173
|
+
domain_port = url.split( '/' )[ 2 ]
|
1174
|
+
# puts "debug domain port #{ domain_port }"
|
1175
|
+
end
|
1176
|
+
end
|
1163
1177
|
|
1164
1178
|
unless domain_port then
|
1165
1179
|
# puts "debug not HTTP"
|
@@ -1226,10 +1240,6 @@ module Girl
|
|
1226
1240
|
when :tunnel then
|
1227
1241
|
atun = src_info[ :atun ]
|
1228
1242
|
|
1229
|
-
if atun && !src_info[ :is_connect ] then
|
1230
|
-
data, _ = sub_http_request( data )
|
1231
|
-
end
|
1232
|
-
|
1233
1243
|
if atun then
|
1234
1244
|
add_atun_wbuff( atun, pack_a_chunk( data ) )
|
1235
1245
|
else
|
@@ -1240,10 +1250,6 @@ module Girl
|
|
1240
1250
|
dst = src_info[ :dst ]
|
1241
1251
|
|
1242
1252
|
if dst then
|
1243
|
-
unless src_info[ :is_connect ] then
|
1244
|
-
data, _ = sub_http_request( data )
|
1245
|
-
end
|
1246
|
-
|
1247
1253
|
add_dst_wbuff( dst, data )
|
1248
1254
|
else
|
1249
1255
|
# puts "debug add src.rbuff #{ data.bytesize }"
|
@@ -1265,7 +1271,7 @@ module Girl
|
|
1265
1271
|
src = dst_info[ :src ]
|
1266
1272
|
|
1267
1273
|
begin
|
1268
|
-
data = dst.read_nonblock(
|
1274
|
+
data = dst.read_nonblock( CHUNK_SIZE )
|
1269
1275
|
rescue IO::WaitReadable
|
1270
1276
|
print 'r'
|
1271
1277
|
return
|
@@ -1306,22 +1312,44 @@ module Girl
|
|
1306
1312
|
end
|
1307
1313
|
|
1308
1314
|
until data.empty? do
|
1309
|
-
rbuff = btun_info[ :rbuff ]
|
1310
1315
|
wait_bytes = btun_info[ :wait_bytes ]
|
1311
1316
|
|
1312
1317
|
if wait_bytes > 0 then
|
1313
1318
|
len = wait_bytes
|
1314
1319
|
# puts "debug wait bytes #{ len }"
|
1315
1320
|
else
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
+
lbuff = btun_info[ :lbuff ]
|
1322
|
+
|
1323
|
+
if lbuff.empty? then
|
1324
|
+
# 长度缓存为空,从读到的流量里取长度
|
1325
|
+
# 两个字节以下,记进长度缓存
|
1326
|
+
if data.bytesize <= 2 then
|
1327
|
+
# puts "debug set btun.lbuff #{ data.inspect }"
|
1328
|
+
btun_info[ :lbuff ] = data
|
1329
|
+
return
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
len = data[ 0, 2 ].unpack( 'n' ).first
|
1333
|
+
data = data[ 2..-1 ]
|
1334
|
+
elsif lbuff.bytesize == 1 then
|
1335
|
+
# 长度缓存记有一个字节,补一个字节
|
1336
|
+
lbuff = "#{ lbuff }#{ data[ 0 ] }"
|
1321
1337
|
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1338
|
+
if data.bytesize == 1 then
|
1339
|
+
# puts "debug add btun.lbuff a byte #{ data.inspect }"
|
1340
|
+
btun_info[ :lbuff ] = lbuff
|
1341
|
+
return
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
# 使用长度缓存
|
1345
|
+
len = lbuff.unpack( 'n' ).first
|
1346
|
+
btun_info[ :lbuff ].clear
|
1347
|
+
data = data[ 1..-1 ]
|
1348
|
+
else
|
1349
|
+
# 使用长度缓存
|
1350
|
+
len = lbuff.unpack( 'n' ).first
|
1351
|
+
btun_info[ :lbuff ].clear
|
1352
|
+
end
|
1325
1353
|
end
|
1326
1354
|
|
1327
1355
|
chunk = data[ 0, len ]
|
@@ -1329,7 +1357,7 @@ module Girl
|
|
1329
1357
|
|
1330
1358
|
if chunk_size == len then
|
1331
1359
|
# 取完整了
|
1332
|
-
chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
|
1360
|
+
chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
|
1333
1361
|
# puts "debug decode and add src.wbuff #{ chunk.bytesize }"
|
1334
1362
|
add_src_wbuff( src, chunk )
|
1335
1363
|
btun_info[ :rbuff ].clear
|
@@ -1408,6 +1436,12 @@ module Girl
|
|
1408
1436
|
|
1409
1437
|
dst_info = @dst_infos[ dst ]
|
1410
1438
|
src = dst_info[ :src ]
|
1439
|
+
src_info = @src_infos[ src ]
|
1440
|
+
|
1441
|
+
unless src.closed? then
|
1442
|
+
src_info[ :dst_connected ] = true
|
1443
|
+
end
|
1444
|
+
|
1411
1445
|
data = dst_info[ :wbuff ]
|
1412
1446
|
|
1413
1447
|
# 写前为空,处理关闭写
|
@@ -1438,7 +1472,6 @@ module Girl
|
|
1438
1472
|
dst_info[ :wbuff ] = data
|
1439
1473
|
|
1440
1474
|
unless src.closed? then
|
1441
|
-
src_info = @src_infos[ src ]
|
1442
1475
|
src_info[ :last_sent_at ] = Time.new
|
1443
1476
|
end
|
1444
1477
|
end
|