girl 0.81.0 → 0.86.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 +1 -1
- data/lib/girl/head.rb +3 -2
- data/lib/girl/proxy.rb +24 -1
- data/lib/girl/proxy_worker.rb +16 -14
- data/lib/girl/proxyd_worker.rb +20 -18
- data/lib/girl/udp.rb +181 -145
- data/lib/girl/udpd.rb +181 -141
- 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: 48f438a56f35bb4fd0fbb76e57f08b5ea1a6e8890b8a2b7542881b1f69e89461
|
4
|
+
data.tar.gz: 8ad2943b900e91f8a6e29306fe29249d467374f738261daadaaa429961370206
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98512a3678ebde91bff827995447765c57c558f885313d05ecd8c831e85354a9ea81beb5ff038c18787b1bd0c15fe88317b85a3b6e84458a5709bcf59b027fff
|
7
|
+
data.tar.gz: 263aff6f7b79025d5404f6b6e4a68b01dfa899df0af4556b0085f72e9bb3227d6423be77e3c1cd12445fb1c9727c426be9750a9f7cea72d112b72c59702917a7
|
data/girl.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ['qqtakafan@gmail.com']
|
11
11
|
|
12
12
|
spec.summary = %q{妹子}
|
13
|
-
spec.description = %q{
|
13
|
+
spec.description = %q{escape evil.}
|
14
14
|
spec.homepage = 'https://github.com/takafan/girl'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
data/lib/girl/head.rb
CHANGED
@@ -7,9 +7,10 @@ module Girl
|
|
7
7
|
EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
|
8
8
|
EXPIRE_AFTER = 300 # 多久没有新流量,过期
|
9
9
|
CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
|
10
|
-
|
10
|
+
CHECK_STATUS_INTERVAL = 0.5 # 发送状态间隔
|
11
11
|
SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
|
12
|
-
|
12
|
+
MISS_RANGE_LIMIT = 500 # miss段上限,达到上限忽略要后面的段
|
13
|
+
RESENDING_LIMIT = 5000 # 重传队列上限
|
13
14
|
CONFUSE_UNTIL = 5 # 混淆前几个包
|
14
15
|
RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
|
15
16
|
TUND_PORT = 1
|
data/lib/girl/proxy.rb
CHANGED
@@ -108,7 +108,7 @@ module Girl
|
|
108
108
|
raise "not found direct file #{ direct_path }"
|
109
109
|
end
|
110
110
|
|
111
|
-
directs = (
|
111
|
+
directs = ( RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map { | line | IPAddr.new( line.strip ) }
|
112
112
|
end
|
113
113
|
|
114
114
|
remotes = []
|
@@ -170,6 +170,29 @@ module Girl
|
|
170
170
|
puts "im #{ im }"
|
171
171
|
puts "worker count #{ worker_count }"
|
172
172
|
|
173
|
+
names = %w[
|
174
|
+
PACK_SIZE
|
175
|
+
CHUNK_SIZE
|
176
|
+
WBUFFS_LIMIT
|
177
|
+
WMEMS_LIMIT
|
178
|
+
RESUME_BELOW
|
179
|
+
EXPIRE_NEW
|
180
|
+
EXPIRE_AFTER
|
181
|
+
CHECK_EXPIRE_INTERVAL
|
182
|
+
CHECK_STATUS_INTERVAL
|
183
|
+
SEND_STATUS_UNTIL
|
184
|
+
MISS_RANGE_LIMIT
|
185
|
+
RESENDING_LIMIT
|
186
|
+
CONFUSE_UNTIL
|
187
|
+
RESOLV_CACHE_EXPIRE
|
188
|
+
]
|
189
|
+
|
190
|
+
len = names.map{ | name | name.size }.max
|
191
|
+
|
192
|
+
names.each do | name |
|
193
|
+
puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
|
194
|
+
end
|
195
|
+
|
173
196
|
if RUBY_PLATFORM.include?( 'linux' )
|
174
197
|
$0 = title
|
175
198
|
workers = []
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -152,7 +152,7 @@ module Girl
|
|
152
152
|
def loop_check_status
|
153
153
|
Thread.new do
|
154
154
|
loop do
|
155
|
-
sleep
|
155
|
+
sleep CHECK_STATUS_INTERVAL
|
156
156
|
|
157
157
|
@mutex.synchronize do
|
158
158
|
if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
|
@@ -264,8 +264,10 @@ module Girl
|
|
264
264
|
# deal with destination ip
|
265
265
|
#
|
266
266
|
def deal_with_destination_ip( src, ip_info )
|
267
|
-
|
268
|
-
|
267
|
+
src_info = @src_infos[ src ]
|
268
|
+
|
269
|
+
if ( @directs.any? { | direct | direct.include?( ip_info.ip_address ) } ) || ( ( src_info[ :destination_domain ] == @proxyd_host ) && ![ 80, 443 ].include?( src_info[ :destination_port ] ) )
|
270
|
+
# ip命中直连列表,或者访问远端非80/443端口,直连
|
269
271
|
# puts "debug1 #{ ip_info.inspect } hit directs"
|
270
272
|
new_a_dst( src, ip_info )
|
271
273
|
else
|
@@ -1224,7 +1226,7 @@ module Girl
|
|
1224
1226
|
|
1225
1227
|
tund_port = data[ 9, 2 ].unpack( 'n' ).first
|
1226
1228
|
|
1227
|
-
|
1229
|
+
puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
|
1228
1230
|
tund_addr = Socket.sockaddr_in( tund_port, @proxyd_host )
|
1229
1231
|
@tun_info[ :tund_addr ] = tund_addr
|
1230
1232
|
|
@@ -1289,36 +1291,36 @@ module Girl
|
|
1289
1291
|
# 发miss
|
1290
1292
|
if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < relay_dst_pack_id )
|
1291
1293
|
ranges = []
|
1294
|
+
ignored = false
|
1292
1295
|
curr_pack_id = src_ext[ :continue_dst_pack_id ] + 1
|
1293
1296
|
|
1294
1297
|
src_ext[ :pieces ].keys.sort.each do | pack_id |
|
1295
1298
|
if pack_id > curr_pack_id
|
1296
1299
|
ranges << [ curr_pack_id, pack_id - 1 ]
|
1300
|
+
|
1301
|
+
if ranges.size >= MISS_RANGE_LIMIT
|
1302
|
+
puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
|
1303
|
+
ignored = true
|
1304
|
+
break
|
1305
|
+
end
|
1297
1306
|
end
|
1298
1307
|
|
1299
1308
|
curr_pack_id = pack_id + 1
|
1300
1309
|
end
|
1301
1310
|
|
1302
|
-
if curr_pack_id <= relay_dst_pack_id
|
1311
|
+
if !ignored && ( curr_pack_id <= relay_dst_pack_id )
|
1303
1312
|
ranges << [ curr_pack_id, relay_dst_pack_id ]
|
1304
1313
|
end
|
1305
1314
|
|
1306
|
-
pack_count = 0
|
1307
1315
|
# puts "debug1 continue/relay #{ src_ext[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
|
1308
1316
|
|
1309
1317
|
ranges.each do | pack_id_begin, pack_id_end |
|
1310
|
-
if pack_count >= BREAK_SEND_MISS
|
1311
|
-
puts "p#{ Process.pid } #{ Time.new } break send miss at #{ pack_id_begin }"
|
1312
|
-
break
|
1313
|
-
end
|
1314
|
-
|
1315
1318
|
data2 = [ 0, MISS, dst_port, pack_id_begin, pack_id_end ].pack( 'Q>CnQ>Q>' )
|
1316
1319
|
add_tun_ctlmsg( data2 )
|
1317
|
-
pack_count += ( pack_id_end - pack_id_begin + 1 )
|
1318
1320
|
end
|
1319
1321
|
end
|
1320
1322
|
when MISS
|
1321
|
-
return if from_addr != @tun_info[ :tund_addr ]
|
1323
|
+
return if ( from_addr != @tun_info[ :tund_addr ] ) || ( @tun_info[ :resendings ].size >= RESENDING_LIMIT )
|
1322
1324
|
|
1323
1325
|
src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
1324
1326
|
|
@@ -1329,7 +1331,7 @@ module Girl
|
|
1329
1331
|
send_at = src_ext[ :send_ats ][ pack_id ]
|
1330
1332
|
|
1331
1333
|
if send_at
|
1332
|
-
break if now - send_at <
|
1334
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
1333
1335
|
@tun_info[ :resendings ] << [ src_id, pack_id ]
|
1334
1336
|
end
|
1335
1337
|
end
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -144,7 +144,7 @@ module Girl
|
|
144
144
|
def loop_check_status
|
145
145
|
Thread.new do
|
146
146
|
loop do
|
147
|
-
sleep
|
147
|
+
sleep CHECK_STATUS_INTERVAL
|
148
148
|
|
149
149
|
if @tunds.any?
|
150
150
|
@mutex.synchronize do
|
@@ -418,15 +418,17 @@ module Girl
|
|
418
418
|
##
|
419
419
|
# send data
|
420
420
|
#
|
421
|
-
def send_data(
|
421
|
+
def send_data( sock, data, to_addr )
|
422
422
|
begin
|
423
|
-
|
423
|
+
sock.sendmsg( data, 0, to_addr )
|
424
424
|
rescue IO::WaitWritable, Errno::EINTR
|
425
425
|
return false
|
426
426
|
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
427
|
-
|
428
|
-
|
429
|
-
|
427
|
+
if @roles[ sock ] == :tund
|
428
|
+
puts "#{ Time.new } #{ e.class }, close tund"
|
429
|
+
close_tund( sock )
|
430
|
+
return false
|
431
|
+
end
|
430
432
|
end
|
431
433
|
|
432
434
|
true
|
@@ -541,9 +543,7 @@ module Girl
|
|
541
543
|
while @proxyd_ctlmsgs.any?
|
542
544
|
to_addr, data = @proxyd_ctlmsgs.first
|
543
545
|
|
544
|
-
|
545
|
-
proxyd.sendmsg( data, 0, to_addr )
|
546
|
-
rescue IO::WaitWritable, Errno::EINTR
|
546
|
+
unless send_data( proxyd, data, to_addr )
|
547
547
|
return
|
548
548
|
end
|
549
549
|
|
@@ -866,35 +866,37 @@ module Girl
|
|
866
866
|
# 发miss
|
867
867
|
if !dst_ext[ :dst ].closed? && ( dst_ext[ :continue_src_pack_id ] < relay_src_pack_id )
|
868
868
|
ranges = []
|
869
|
+
ignored = false
|
869
870
|
curr_pack_id = dst_ext[ :continue_src_pack_id ] + 1
|
870
871
|
|
871
872
|
dst_ext[ :pieces ].keys.sort.each do | pack_id |
|
872
873
|
if pack_id > curr_pack_id
|
873
874
|
ranges << [ curr_pack_id, pack_id - 1 ]
|
875
|
+
|
876
|
+
if ranges.size >= MISS_RANGE_LIMIT
|
877
|
+
puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
|
878
|
+
ignored = true
|
879
|
+
break
|
880
|
+
end
|
874
881
|
end
|
875
882
|
|
876
883
|
curr_pack_id = pack_id + 1
|
877
884
|
end
|
878
885
|
|
879
|
-
if curr_pack_id <= relay_src_pack_id
|
886
|
+
if !ignored && ( curr_pack_id <= relay_src_pack_id )
|
880
887
|
ranges << [ curr_pack_id, relay_src_pack_id ]
|
881
888
|
end
|
882
889
|
|
883
|
-
pack_count = 0
|
884
890
|
# puts "debug1 continue/relay #{ dst_ext[ :continue_src_pack_id ] }/#{ relay_src_pack_id } send MISS #{ ranges.size }"
|
885
891
|
|
886
892
|
ranges.each do | pack_id_begin, pack_id_end |
|
887
|
-
if pack_count >= BREAK_SEND_MISS
|
888
|
-
puts "p#{ Process.pid } #{ Time.new } break send miss at #{ pack_id_begin }"
|
889
|
-
break
|
890
|
-
end
|
891
|
-
|
892
893
|
data2 = [ 0, MISS, src_id, pack_id_begin, pack_id_end ].pack( 'Q>CQ>Q>Q>' )
|
893
894
|
add_tund_ctlmsg( tund, data2 )
|
894
|
-
pack_count += ( pack_id_end - pack_id_begin + 1 )
|
895
895
|
end
|
896
896
|
end
|
897
897
|
when MISS
|
898
|
+
return if tund_info[ :resendings ].size >= RESENDING_LIMIT
|
899
|
+
|
898
900
|
dst_local_port, pack_id_begin, pack_id_end = data[ 9, 18 ].unpack( 'nQ>Q>' )
|
899
901
|
|
900
902
|
dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
|
@@ -904,7 +906,7 @@ module Girl
|
|
904
906
|
send_at = dst_ext[ :send_ats ][ pack_id ]
|
905
907
|
|
906
908
|
if send_at
|
907
|
-
break if now - send_at <
|
909
|
+
break if now - send_at < CHECK_STATUS_INTERVAL
|
908
910
|
tund_info[ :resendings ] << [ dst_local_port, pack_id ]
|
909
911
|
end
|
910
912
|
end
|
data/lib/girl/udp.rb
CHANGED
@@ -17,25 +17,12 @@ module Girl
|
|
17
17
|
class Udp
|
18
18
|
|
19
19
|
def initialize( udpd_host, udpd_port = 3030, redir_port = 1313 )
|
20
|
-
ctlr, ctlw = IO.pipe
|
21
|
-
|
22
|
-
redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
23
|
-
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
24
|
-
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
25
|
-
puts "redir bound on #{ redir_port } #{ Time.new }"
|
26
|
-
|
27
|
-
@mutex = Mutex.new
|
28
20
|
@udpd_host = udpd_host
|
29
21
|
@udpd_addr = Socket.sockaddr_in( udpd_port, udpd_host )
|
30
|
-
@
|
31
|
-
@
|
32
|
-
@reads = [ ctlr, redir ]
|
22
|
+
@mutex = Mutex.new
|
23
|
+
@reads = []
|
33
24
|
@writes = []
|
34
|
-
@
|
35
|
-
@roles = {
|
36
|
-
ctlr => :ctlr, # :ctlr / :redir / :tun
|
37
|
-
redir => :redir
|
38
|
-
}
|
25
|
+
@roles = {} # :dotr / :redir / :tun
|
39
26
|
@redir_wbuffs = [] # [ src_addr data ] ...
|
40
27
|
@tuns = {} # [ orig_src_addr dst_addr ]=> tun
|
41
28
|
@mappings = {} # src_addr => [ orig_src_addr dst_addr ]
|
@@ -47,6 +34,10 @@ module Girl
|
|
47
34
|
# rbuffs: []
|
48
35
|
# wbuffs: []
|
49
36
|
# last_traff_at: now
|
37
|
+
dotr, dotw = IO.pipe
|
38
|
+
@dotw = dotw
|
39
|
+
add_read( dotr, :dotr )
|
40
|
+
new_a_redir( redir_port )
|
50
41
|
end
|
51
42
|
|
52
43
|
def looping
|
@@ -56,23 +47,23 @@ module Girl
|
|
56
47
|
rs, ws = IO.select( @reads, @writes )
|
57
48
|
|
58
49
|
@mutex.synchronize do
|
59
|
-
|
50
|
+
ws.each do | sock |
|
60
51
|
case @roles[ sock ]
|
61
|
-
when :ctlr
|
62
|
-
read_ctlr( sock )
|
63
52
|
when :redir
|
64
|
-
|
53
|
+
write_redir( sock )
|
65
54
|
when :tun
|
66
|
-
|
55
|
+
write_tun( sock )
|
67
56
|
end
|
68
57
|
end
|
69
58
|
|
70
|
-
|
59
|
+
rs.each do | sock |
|
71
60
|
case @roles[ sock ]
|
61
|
+
when :dotr
|
62
|
+
read_dotr( sock )
|
72
63
|
when :redir
|
73
|
-
|
64
|
+
read_redir( sock )
|
74
65
|
when :tun
|
75
|
-
|
66
|
+
read_tun( sock )
|
76
67
|
end
|
77
68
|
end
|
78
69
|
end
|
@@ -85,15 +76,176 @@ module Girl
|
|
85
76
|
|
86
77
|
private
|
87
78
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
79
|
+
def loop_expire
|
80
|
+
Thread.new do
|
81
|
+
loop do
|
82
|
+
sleep 30
|
91
83
|
|
92
|
-
|
93
|
-
|
84
|
+
@mutex.synchronize do
|
85
|
+
need_trigger = false
|
86
|
+
now = Time.new
|
87
|
+
|
88
|
+
@tun_infos.each do | tun, tun_info |
|
89
|
+
# net.netfilter.nf_conntrack_udp_timeout_stream
|
90
|
+
if now - tun_info[ :last_traff_at ] > 180
|
91
|
+
set_is_closing( tun )
|
92
|
+
need_trigger = true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
if need_trigger
|
97
|
+
next_tick
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
94
101
|
end
|
95
102
|
end
|
96
103
|
|
104
|
+
def new_a_redir( redir_port )
|
105
|
+
redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
106
|
+
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
107
|
+
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
108
|
+
puts "redir bound on #{ redir_port } #{ Time.new }"
|
109
|
+
@redir = redir
|
110
|
+
add_read( redir, :redir )
|
111
|
+
end
|
112
|
+
|
113
|
+
def new_a_tun( orig_src_addr, dst_addr, src_addr )
|
114
|
+
tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
115
|
+
tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
116
|
+
tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
117
|
+
|
118
|
+
@tun_infos[ tun ] = {
|
119
|
+
orig_src_addr: orig_src_addr,
|
120
|
+
dst_addr: dst_addr,
|
121
|
+
src_addr: src_addr,
|
122
|
+
tund_addr: nil,
|
123
|
+
rbuffs: [],
|
124
|
+
wbuffs: [],
|
125
|
+
last_traff_at: Time.new,
|
126
|
+
is_closing: false
|
127
|
+
}
|
128
|
+
|
129
|
+
@tuns[ [ orig_src_addr, dst_addr ].join ] = tun
|
130
|
+
add_read( tun, :tun )
|
131
|
+
|
132
|
+
tun
|
133
|
+
end
|
134
|
+
|
135
|
+
def add_redir_wbuff( redir, to_addr, data )
|
136
|
+
@redir_wbuffs << [ to_addr, data ]
|
137
|
+
add_write( redir )
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_tun_wbuff( tun, to_addr, data )
|
141
|
+
tun_info = @tun_infos[ tun ]
|
142
|
+
|
143
|
+
if to_addr
|
144
|
+
tun_info[ :wbuffs ] << [ to_addr, data ]
|
145
|
+
add_write( tun )
|
146
|
+
else
|
147
|
+
tun_info[ :rbuffs ] << data
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_read( sock, role )
|
152
|
+
unless @reads.include?( sock )
|
153
|
+
@reads << sock
|
154
|
+
end
|
155
|
+
|
156
|
+
@roles[ sock ] = role
|
157
|
+
end
|
158
|
+
|
159
|
+
def add_write( sock )
|
160
|
+
unless @writes.include?( sock )
|
161
|
+
@writes << sock
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def set_is_closing( tun )
|
166
|
+
if tun && !tun.closed?
|
167
|
+
# puts "debug1 set tun is closing"
|
168
|
+
|
169
|
+
tun_info = @tun_infos[ tun ]
|
170
|
+
tun_info[ :is_closing ] = true
|
171
|
+
|
172
|
+
@reads.delete( tun )
|
173
|
+
add_write( tun )
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def send_data( sock, data, to_addr )
|
178
|
+
begin
|
179
|
+
sock.sendmsg( data, 0, to_addr )
|
180
|
+
rescue IO::WaitWritable, Errno::EINTR
|
181
|
+
return false
|
182
|
+
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
183
|
+
if @roles[ sock ] == :tun
|
184
|
+
puts "#{ Time.new } #{ e.class }, close tun"
|
185
|
+
close_tun( sock )
|
186
|
+
return false
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
true
|
191
|
+
end
|
192
|
+
|
193
|
+
def close_tun( tun )
|
194
|
+
tun.close
|
195
|
+
@reads.delete( tun )
|
196
|
+
@writes.delete( tun )
|
197
|
+
@roles.delete( tun )
|
198
|
+
tun_info = @tun_infos.delete( tun )
|
199
|
+
@tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
|
200
|
+
|
201
|
+
if @mappings.include?( tun_info[ :src_addr ] )
|
202
|
+
orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
|
203
|
+
|
204
|
+
if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ]
|
205
|
+
@mappings.delete( tun_info[ :src_addr ] )
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def write_redir( redir )
|
211
|
+
while @redir_wbuffs.any?
|
212
|
+
to_addr, data = @redir_wbuffs.first
|
213
|
+
|
214
|
+
unless send_data( redir, data, to_addr )
|
215
|
+
return
|
216
|
+
end
|
217
|
+
|
218
|
+
@redir_wbuffs.shift
|
219
|
+
end
|
220
|
+
|
221
|
+
@writes.delete( redir )
|
222
|
+
end
|
223
|
+
|
224
|
+
def write_tun( tun )
|
225
|
+
tun_info = @tun_infos[ tun ]
|
226
|
+
|
227
|
+
if tun_info[ :is_closing ]
|
228
|
+
close_tun( tun )
|
229
|
+
return
|
230
|
+
end
|
231
|
+
|
232
|
+
while tun_info[ :wbuffs ].any?
|
233
|
+
to_addr, data = tun_info[ :wbuffs ].first
|
234
|
+
|
235
|
+
unless send_data( tun, data, to_addr )
|
236
|
+
return
|
237
|
+
end
|
238
|
+
|
239
|
+
tun_info[ :wbuffs ].shift
|
240
|
+
end
|
241
|
+
|
242
|
+
@writes.delete( tun )
|
243
|
+
end
|
244
|
+
|
245
|
+
def read_dotr( dotr )
|
246
|
+
dotr.read( 1 )
|
247
|
+
end
|
248
|
+
|
97
249
|
def read_redir( redir )
|
98
250
|
data, addrinfo, rflags, *controls = redir.recvmsg
|
99
251
|
src_addr = addrinfo.to_sockaddr
|
@@ -180,121 +332,5 @@ module Girl
|
|
180
332
|
end
|
181
333
|
end
|
182
334
|
|
183
|
-
def write_redir( redir )
|
184
|
-
if @redir_wbuffs.empty?
|
185
|
-
@writes.delete( redir )
|
186
|
-
return
|
187
|
-
end
|
188
|
-
|
189
|
-
src_addr, data = @redir_wbuffs.shift
|
190
|
-
redir.sendmsg( data, 0, src_addr )
|
191
|
-
end
|
192
|
-
|
193
|
-
def write_tun( tun )
|
194
|
-
if @closings.include?( tun )
|
195
|
-
close_tun( tun )
|
196
|
-
return
|
197
|
-
end
|
198
|
-
|
199
|
-
tun_info = @tun_infos[ tun ]
|
200
|
-
|
201
|
-
if tun_info[ :wbuffs ].empty?
|
202
|
-
@writes.delete( tun )
|
203
|
-
return
|
204
|
-
end
|
205
|
-
|
206
|
-
to_addr, data = tun_info[ :wbuffs ].shift
|
207
|
-
tun.sendmsg( data, 0, to_addr )
|
208
|
-
end
|
209
|
-
|
210
|
-
def add_redir_wbuff( redir, to_addr, data )
|
211
|
-
@redir_wbuffs << [ to_addr, data ]
|
212
|
-
add_write( redir )
|
213
|
-
end
|
214
|
-
|
215
|
-
def add_tun_wbuff( tun, to_addr, data )
|
216
|
-
tun_info = @tun_infos[ tun ]
|
217
|
-
|
218
|
-
if to_addr
|
219
|
-
tun_info[ :wbuffs ] << [ to_addr, data ]
|
220
|
-
add_write( tun )
|
221
|
-
else
|
222
|
-
tun_info[ :rbuffs ] << data
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def add_write( sock )
|
227
|
-
unless @writes.include?( sock )
|
228
|
-
@writes << sock
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def add_closing( tun )
|
233
|
-
unless @closings.include?( tun )
|
234
|
-
@closings << tun
|
235
|
-
end
|
236
|
-
|
237
|
-
add_write( tun )
|
238
|
-
end
|
239
|
-
|
240
|
-
def close_tun( tun )
|
241
|
-
tun.close
|
242
|
-
@reads.delete( tun )
|
243
|
-
@writes.delete( tun )
|
244
|
-
@closings.delete( tun )
|
245
|
-
@roles.delete( tun )
|
246
|
-
tun_info = @tun_infos.delete( tun )
|
247
|
-
@tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
|
248
|
-
|
249
|
-
if @mappings.include?( tun_info[ :src_addr ] )
|
250
|
-
orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
|
251
|
-
|
252
|
-
if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ]
|
253
|
-
@mappings.delete( tun_info[ :src_addr ] )
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def new_a_tun( orig_src_addr, dst_addr, src_addr )
|
259
|
-
tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
260
|
-
tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
261
|
-
tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
262
|
-
|
263
|
-
@tun_infos[ tun ] = {
|
264
|
-
orig_src_addr: orig_src_addr,
|
265
|
-
dst_addr: dst_addr,
|
266
|
-
src_addr: src_addr,
|
267
|
-
tund_addr: nil,
|
268
|
-
rbuffs: [],
|
269
|
-
wbuffs: [],
|
270
|
-
last_traff_at: Time.new
|
271
|
-
}
|
272
|
-
|
273
|
-
@tuns[ [ orig_src_addr, dst_addr ].join ] = tun
|
274
|
-
@roles[ tun ] = :tun
|
275
|
-
@reads << tun
|
276
|
-
|
277
|
-
tun
|
278
|
-
end
|
279
|
-
|
280
|
-
def loop_expire
|
281
|
-
Thread.new do
|
282
|
-
loop do
|
283
|
-
sleep 30
|
284
|
-
|
285
|
-
@mutex.synchronize do
|
286
|
-
now = Time.new
|
287
|
-
|
288
|
-
@tun_infos.values.each do | tun_info |
|
289
|
-
# net.netfilter.nf_conntrack_udp_timeout_stream
|
290
|
-
if now - tun_info[ :last_traff_at ] > 180
|
291
|
-
@ctlw.write( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
335
|
end
|
300
336
|
end
|
data/lib/girl/udpd.rb
CHANGED
@@ -8,23 +8,10 @@ module Girl
|
|
8
8
|
class Udpd
|
9
9
|
|
10
10
|
def initialize( port = 3030 )
|
11
|
-
ctlr, ctlw = IO.pipe
|
12
|
-
|
13
|
-
udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
14
|
-
udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
15
|
-
udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
|
16
|
-
puts "udpd bound on #{ port } #{ Time.new }"
|
17
|
-
|
18
11
|
@mutex = Mutex.new
|
19
|
-
@
|
20
|
-
@udpd = udpd
|
21
|
-
@reads = [ ctlr, udpd ]
|
12
|
+
@reads = []
|
22
13
|
@writes = []
|
23
|
-
@
|
24
|
-
@roles = {
|
25
|
-
ctlr => :ctlr, # :ctlr / :udpd / :tund
|
26
|
-
udpd => :udpd
|
27
|
-
}
|
14
|
+
@roles = {} # :dotr / :udpd / :tund
|
28
15
|
@udpd_wbuffs = [] # [ tun_addr ctlmsg ] ...
|
29
16
|
@tunds = {} # [ tun_ip_addr orig_src_addr ] => tund
|
30
17
|
@tund_infos = {} # tund => {}
|
@@ -37,6 +24,10 @@ module Girl
|
|
37
24
|
# is_tunneleds: { [ tun_addr dst_addr ] => false }
|
38
25
|
# unpaired_dst_rbuffs: { dst_addr => [] }
|
39
26
|
# last_traff_at: now
|
27
|
+
dotr, dotw = IO.pipe
|
28
|
+
@dotw = dotw
|
29
|
+
add_read( dotr, :dotr )
|
30
|
+
new_a_udpd( port )
|
40
31
|
end
|
41
32
|
|
42
33
|
def looping
|
@@ -46,23 +37,23 @@ module Girl
|
|
46
37
|
rs, ws = IO.select( @reads, @writes )
|
47
38
|
|
48
39
|
@mutex.synchronize do
|
49
|
-
|
40
|
+
ws.each do | sock |
|
50
41
|
case @roles[ sock ]
|
51
|
-
when :ctlr
|
52
|
-
read_ctlr( sock )
|
53
42
|
when :udpd
|
54
|
-
|
43
|
+
write_udpd( sock )
|
55
44
|
when :tund
|
56
|
-
|
45
|
+
write_tund( sock )
|
57
46
|
end
|
58
47
|
end
|
59
48
|
|
60
|
-
|
49
|
+
rs.each do | sock |
|
61
50
|
case @roles[ sock ]
|
51
|
+
when :dotr
|
52
|
+
read_dotr( sock )
|
62
53
|
when :udpd
|
63
|
-
|
54
|
+
read_udpd( sock )
|
64
55
|
when :tund
|
65
|
-
|
56
|
+
read_tund( sock )
|
66
57
|
end
|
67
58
|
end
|
68
59
|
end
|
@@ -75,13 +66,176 @@ module Girl
|
|
75
66
|
|
76
67
|
private
|
77
68
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
69
|
+
def loop_expire
|
70
|
+
Thread.new do
|
71
|
+
loop do
|
72
|
+
sleep 30
|
73
|
+
|
74
|
+
@mutex.synchronize do
|
75
|
+
need_trigger = false
|
76
|
+
now = Time.new
|
77
|
+
|
78
|
+
@tund_infos.each do | tund, tund_info |
|
79
|
+
# net.netfilter.nf_conntrack_udp_timeout_stream
|
80
|
+
if now - tund_info[ :last_traff_at ] > 180
|
81
|
+
set_is_closing( tund )
|
82
|
+
need_trigger = true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if need_trigger
|
87
|
+
next_tick
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def new_a_udpd( port )
|
95
|
+
udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
96
|
+
udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
97
|
+
udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
|
98
|
+
puts "udpd bound on #{ port } #{ Time.new }"
|
99
|
+
@udpd = udpd
|
100
|
+
add_read( udpd, :udpd )
|
101
|
+
end
|
102
|
+
|
103
|
+
def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
|
104
|
+
from_addr = [ tun_ip_addr, orig_src_addr ].join
|
105
|
+
td_addr = [ tun_addr, dst_addr ].join
|
106
|
+
tund = @tunds[ from_addr ]
|
81
107
|
|
82
108
|
if tund
|
83
|
-
|
109
|
+
tund_info = @tund_infos[ tund ]
|
110
|
+
tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
|
111
|
+
tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
|
112
|
+
tund_info[ :is_tunneleds ][ td_addr ] = false
|
113
|
+
else
|
114
|
+
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
115
|
+
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
116
|
+
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
|
117
|
+
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
118
|
+
tund_port = tund.local_address.ip_unpack.last
|
119
|
+
|
120
|
+
@tund_infos[ tund ] = {
|
121
|
+
port: tund_port,
|
122
|
+
tun_ip_addr: tun_ip_addr,
|
123
|
+
orig_src_addr: orig_src_addr,
|
124
|
+
wbuffs: [],
|
125
|
+
dst_addrs: { tun_addr => dst_addr },
|
126
|
+
tun_addrs: { dst_addr => tun_addr },
|
127
|
+
is_tunneleds: { td_addr => false },
|
128
|
+
unpaired_dst_rbuffs: {},
|
129
|
+
last_traff_at: Time.new,
|
130
|
+
is_closing: false
|
131
|
+
}
|
132
|
+
|
133
|
+
@tunds[ from_addr ] = tund
|
134
|
+
add_read( tund, :tund )
|
135
|
+
end
|
136
|
+
|
137
|
+
tund
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_tund_wbuff( tund, to_addr, data )
|
141
|
+
tund_info = @tund_infos[ tund ]
|
142
|
+
tund_info[ :wbuffs ] << [ to_addr, data ]
|
143
|
+
|
144
|
+
add_write( tund )
|
145
|
+
end
|
146
|
+
|
147
|
+
def add_read( sock, role )
|
148
|
+
unless @reads.include?( sock )
|
149
|
+
@reads << sock
|
150
|
+
end
|
151
|
+
|
152
|
+
@roles[ sock ] = role
|
153
|
+
end
|
154
|
+
|
155
|
+
def add_write( sock )
|
156
|
+
unless @writes.include?( sock )
|
157
|
+
@writes << sock
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def set_is_closing( tund )
|
162
|
+
if tund && !tund.closed?
|
163
|
+
# puts "debug1 set tund is closing"
|
164
|
+
|
165
|
+
tund_info = @tund_infos[ tund ]
|
166
|
+
tund_info[ :is_closing ] = true
|
167
|
+
|
168
|
+
@reads.delete( tund )
|
169
|
+
add_write( tund )
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def send_data( sock, data, to_addr )
|
174
|
+
begin
|
175
|
+
sock.sendmsg( data, 0, to_addr )
|
176
|
+
rescue IO::WaitWritable, Errno::EINTR
|
177
|
+
return false
|
178
|
+
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
179
|
+
if @roles[ sock ] == :tund
|
180
|
+
puts "#{ Time.new } #{ e.class }, close tund"
|
181
|
+
close_tund( sock )
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
true
|
187
|
+
end
|
188
|
+
|
189
|
+
def close_tund( tund )
|
190
|
+
tund.close
|
191
|
+
@reads.delete( tund )
|
192
|
+
@writes.delete( tund )
|
193
|
+
@roles.delete( tund )
|
194
|
+
tund_info = @tund_infos.delete( tund )
|
195
|
+
@tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
|
196
|
+
end
|
197
|
+
|
198
|
+
def next_tick
|
199
|
+
@dotw.write( '.' )
|
200
|
+
end
|
201
|
+
|
202
|
+
def write_udpd( udpd )
|
203
|
+
while @udpd_wbuffs.any?
|
204
|
+
to_addr, data = @udpd_wbuffs.first
|
205
|
+
|
206
|
+
unless send_data( udpd, data, to_addr )
|
207
|
+
return
|
208
|
+
end
|
209
|
+
|
210
|
+
@udpd_wbuffs.shift
|
211
|
+
end
|
212
|
+
|
213
|
+
@writes.delete( udpd )
|
214
|
+
end
|
215
|
+
|
216
|
+
def write_tund( tund )
|
217
|
+
tund_info = @tund_infos[ tund ]
|
218
|
+
|
219
|
+
if tund_info[ :is_closing ]
|
220
|
+
close_tund( tund )
|
221
|
+
return
|
222
|
+
end
|
223
|
+
|
224
|
+
while tund_info[ :wbuffs ].any?
|
225
|
+
to_addr, data = tund_info[ :wbuffs ].first
|
226
|
+
|
227
|
+
unless send_data( tund, data, to_addr )
|
228
|
+
return
|
229
|
+
end
|
230
|
+
|
231
|
+
tund_info[ :wbuffs ].shift
|
84
232
|
end
|
233
|
+
|
234
|
+
@writes.delete( tund )
|
235
|
+
end
|
236
|
+
|
237
|
+
def read_dotr( dotr )
|
238
|
+
dotr.read( 1 )
|
85
239
|
end
|
86
240
|
|
87
241
|
def read_udpd( udpd )
|
@@ -168,119 +322,5 @@ module Girl
|
|
168
322
|
end
|
169
323
|
end
|
170
324
|
|
171
|
-
def write_udpd( udpd )
|
172
|
-
if @udpd_wbuffs.empty?
|
173
|
-
@writes.delete( udpd )
|
174
|
-
return
|
175
|
-
end
|
176
|
-
|
177
|
-
tun_addr, ctlmsg = @udpd_wbuffs.shift
|
178
|
-
udpd.sendmsg( ctlmsg, 0, tun_addr )
|
179
|
-
end
|
180
|
-
|
181
|
-
def write_tund( tund )
|
182
|
-
if @closings.include?( tund )
|
183
|
-
close_tund( tund )
|
184
|
-
return
|
185
|
-
end
|
186
|
-
|
187
|
-
tund_info = @tund_infos[ tund ]
|
188
|
-
|
189
|
-
if tund_info[ :wbuffs ].empty?
|
190
|
-
@writes.delete( tund )
|
191
|
-
return
|
192
|
-
end
|
193
|
-
|
194
|
-
to_addr, data = tund_info[ :wbuffs ].shift
|
195
|
-
tund.sendmsg( data, 0, to_addr )
|
196
|
-
end
|
197
|
-
|
198
|
-
def add_tund_wbuff( tund, to_addr, data )
|
199
|
-
tund_info = @tund_infos[ tund ]
|
200
|
-
tund_info[ :wbuffs ] << [ to_addr, data ]
|
201
|
-
|
202
|
-
add_write( tund )
|
203
|
-
end
|
204
|
-
|
205
|
-
def add_write( sock )
|
206
|
-
unless @writes.include?( sock )
|
207
|
-
@writes << sock
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
def add_closing( tund )
|
212
|
-
unless @closings.include?( tund )
|
213
|
-
@closings << tund
|
214
|
-
end
|
215
|
-
|
216
|
-
add_write( tund )
|
217
|
-
end
|
218
|
-
|
219
|
-
def close_tund( tund )
|
220
|
-
tund.close
|
221
|
-
@reads.delete( tund )
|
222
|
-
@writes.delete( tund )
|
223
|
-
@closings.delete( tund )
|
224
|
-
@roles.delete( tund )
|
225
|
-
tund_info = @tund_infos.delete( tund )
|
226
|
-
@tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
|
227
|
-
end
|
228
|
-
|
229
|
-
def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
|
230
|
-
from_addr = [ tun_ip_addr, orig_src_addr ].join
|
231
|
-
td_addr = [ tun_addr, dst_addr ].join
|
232
|
-
tund = @tunds[ from_addr ]
|
233
|
-
|
234
|
-
if tund
|
235
|
-
tund_info = @tund_infos[ tund ]
|
236
|
-
tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
|
237
|
-
tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
|
238
|
-
tund_info[ :is_tunneleds ][ td_addr ] = false
|
239
|
-
else
|
240
|
-
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
241
|
-
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
242
|
-
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
|
243
|
-
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
244
|
-
tund_port = tund.local_address.ip_unpack.last
|
245
|
-
|
246
|
-
@tund_infos[ tund ] = {
|
247
|
-
port: tund_port,
|
248
|
-
tun_ip_addr: tun_ip_addr,
|
249
|
-
orig_src_addr: orig_src_addr,
|
250
|
-
wbuffs: [],
|
251
|
-
dst_addrs: { tun_addr => dst_addr },
|
252
|
-
tun_addrs: { dst_addr => tun_addr },
|
253
|
-
is_tunneleds: { td_addr => false },
|
254
|
-
unpaired_dst_rbuffs: {},
|
255
|
-
last_traff_at: Time.new
|
256
|
-
}
|
257
|
-
|
258
|
-
@roles[ tund ] = :tund
|
259
|
-
@reads << tund
|
260
|
-
@tunds[ from_addr ] = tund
|
261
|
-
end
|
262
|
-
|
263
|
-
tund
|
264
|
-
end
|
265
|
-
|
266
|
-
def loop_expire
|
267
|
-
Thread.new do
|
268
|
-
loop do
|
269
|
-
sleep 30
|
270
|
-
|
271
|
-
@mutex.synchronize do
|
272
|
-
now = Time.new
|
273
|
-
|
274
|
-
@tund_infos.values.each do | tund_info |
|
275
|
-
# net.netfilter.nf_conntrack_udp_timeout_stream
|
276
|
-
if now - tund_info[ :last_traff_at ] > 180
|
277
|
-
@ctlw.write( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
325
|
end
|
286
326
|
end
|
data/lib/girl/version.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: girl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.86.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- takafan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: escape evil.
|
14
14
|
email:
|
15
15
|
- qqtakafan@gmail.com
|
16
16
|
executables: []
|