girl 0.95.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of girl might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/girl.gemspec +0 -2
- data/lib/girl/proxy_worker.rb +312 -313
- data/lib/girl/proxyd_worker.rb +227 -178
- data/lib/girl/version.rb +1 -1
- metadata +2 -4
- data/lib/girl/udp.rb +0 -326
- data/lib/girl/udpd.rb +0 -316
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: 0.
|
4
|
+
version: 1.0.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-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: escape evil.
|
14
14
|
email:
|
@@ -27,8 +27,6 @@ files:
|
|
27
27
|
- lib/girl/proxyd.rb
|
28
28
|
- lib/girl/proxyd_custom.rb
|
29
29
|
- lib/girl/proxyd_worker.rb
|
30
|
-
- lib/girl/udp.rb
|
31
|
-
- lib/girl/udpd.rb
|
32
30
|
- lib/girl/version.rb
|
33
31
|
homepage: https://github.com/takafan/girl
|
34
32
|
licenses:
|
data/lib/girl/udp.rb
DELETED
@@ -1,326 +0,0 @@
|
|
1
|
-
require 'girl/version'
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
##
|
5
|
-
# Girl::Udp - udp透明转发,近端。
|
6
|
-
#
|
7
|
-
# usage
|
8
|
-
# ======
|
9
|
-
#
|
10
|
-
# Girl::Udpd.new( 3030 ).looping # 远端
|
11
|
-
#
|
12
|
-
# Girl::Udp.new( 'your.server.ip', 3030, 1313 ).looping # 近端
|
13
|
-
#
|
14
|
-
# iptables -t nat -A PREROUTING -p udp -d game.server.ip -j REDIRECT --to-ports 1313
|
15
|
-
#
|
16
|
-
module Girl
|
17
|
-
class Udp
|
18
|
-
|
19
|
-
def initialize( udpd_host, udpd_port = 3030, redir_port = 1313 )
|
20
|
-
@udpd_host = udpd_host
|
21
|
-
@udpd_addr = Socket.sockaddr_in( udpd_port, udpd_host )
|
22
|
-
@mutex = Mutex.new
|
23
|
-
@reads = []
|
24
|
-
@writes = []
|
25
|
-
@roles = {} # :dotr / :redir / :tun
|
26
|
-
@redir_wbuffs = [] # [ src_addr data ] ...
|
27
|
-
@tuns = {} # [ orig_src_addr dst_addr ]=> tun
|
28
|
-
@mappings = {} # src_addr => [ orig_src_addr dst_addr ]
|
29
|
-
@tun_infos = {} # tun => {}
|
30
|
-
# orig_src_addr: sockaddr
|
31
|
-
# dst_addr: sockaddr
|
32
|
-
# src_addr: sockaddr
|
33
|
-
# tund_addr: sockaddr
|
34
|
-
# rbuffs: []
|
35
|
-
# wbuffs: []
|
36
|
-
# last_traff_at: now
|
37
|
-
dotr, dotw = IO.pipe
|
38
|
-
@dotw = dotw
|
39
|
-
add_read( dotr, :dotr )
|
40
|
-
new_a_redir( redir_port )
|
41
|
-
end
|
42
|
-
|
43
|
-
def looping
|
44
|
-
loop_expire
|
45
|
-
|
46
|
-
loop do
|
47
|
-
rs, ws = IO.select( @reads, @writes )
|
48
|
-
|
49
|
-
@mutex.synchronize do
|
50
|
-
rs.each do | sock |
|
51
|
-
case @roles[ sock ]
|
52
|
-
when :dotr then
|
53
|
-
read_dotr( sock )
|
54
|
-
when :redir then
|
55
|
-
read_redir( sock )
|
56
|
-
when :tun then
|
57
|
-
read_tun( sock )
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
ws.each do | sock |
|
62
|
-
case @roles[ sock ]
|
63
|
-
when :redir then
|
64
|
-
write_redir( sock )
|
65
|
-
when :tun then
|
66
|
-
write_tun( sock )
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def quit!
|
74
|
-
exit
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def loop_expire
|
80
|
-
Thread.new do
|
81
|
-
loop do
|
82
|
-
sleep 30
|
83
|
-
|
84
|
-
@mutex.synchronize do
|
85
|
-
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 then
|
91
|
-
set_is_closing( tun )
|
92
|
-
trigger = true
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
next_tick if trigger
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def new_a_redir( redir_port )
|
103
|
-
redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
104
|
-
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
105
|
-
redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
|
106
|
-
puts "redir bound on #{ redir_port } #{ Time.new }"
|
107
|
-
@redir = redir
|
108
|
-
add_read( redir, :redir )
|
109
|
-
end
|
110
|
-
|
111
|
-
def new_a_tun( orig_src_addr, dst_addr, src_addr )
|
112
|
-
tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
113
|
-
tun.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
114
|
-
tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
115
|
-
|
116
|
-
@tun_infos[ tun ] = {
|
117
|
-
orig_src_addr: orig_src_addr,
|
118
|
-
dst_addr: dst_addr,
|
119
|
-
src_addr: src_addr,
|
120
|
-
tund_addr: nil,
|
121
|
-
rbuffs: [],
|
122
|
-
wbuffs: [],
|
123
|
-
last_traff_at: Time.new,
|
124
|
-
is_closing: false
|
125
|
-
}
|
126
|
-
|
127
|
-
@tuns[ [ orig_src_addr, dst_addr ].join ] = tun
|
128
|
-
add_read( tun, :tun )
|
129
|
-
|
130
|
-
tun
|
131
|
-
end
|
132
|
-
|
133
|
-
def add_redir_wbuff( redir, to_addr, data )
|
134
|
-
@redir_wbuffs << [ to_addr, data ]
|
135
|
-
add_write( redir )
|
136
|
-
end
|
137
|
-
|
138
|
-
def add_tun_wbuff( tun, to_addr, data )
|
139
|
-
tun_info = @tun_infos[ tun ]
|
140
|
-
|
141
|
-
if to_addr then
|
142
|
-
tun_info[ :wbuffs ] << [ to_addr, data ]
|
143
|
-
add_write( tun )
|
144
|
-
else
|
145
|
-
tun_info[ :rbuffs ] << data
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def add_read( sock, role )
|
150
|
-
unless @reads.include?( sock ) then
|
151
|
-
@reads << sock
|
152
|
-
end
|
153
|
-
|
154
|
-
@roles[ sock ] = role
|
155
|
-
end
|
156
|
-
|
157
|
-
def add_write( sock )
|
158
|
-
unless @writes.include?( sock ) then
|
159
|
-
@writes << sock
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def set_is_closing( tun )
|
164
|
-
if tun && !tun.closed? then
|
165
|
-
# puts "debug1 set tun is closing"
|
166
|
-
|
167
|
-
tun_info = @tun_infos[ tun ]
|
168
|
-
tun_info[ :is_closing ] = true
|
169
|
-
|
170
|
-
@reads.delete( tun )
|
171
|
-
add_write( tun )
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def send_data( sock, data, to_addr )
|
176
|
-
begin
|
177
|
-
sock.sendmsg( data, 0, to_addr )
|
178
|
-
rescue IO::WaitWritable, Errno::EINTR
|
179
|
-
return false
|
180
|
-
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
181
|
-
if @roles[ sock ] == :tun then
|
182
|
-
puts "#{ Time.new } #{ e.class }, close tun"
|
183
|
-
close_tun( sock )
|
184
|
-
return false
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
true
|
189
|
-
end
|
190
|
-
|
191
|
-
def close_tun( tun )
|
192
|
-
tun.close
|
193
|
-
@reads.delete( tun )
|
194
|
-
@writes.delete( tun )
|
195
|
-
@roles.delete( tun )
|
196
|
-
tun_info = @tun_infos.delete( tun )
|
197
|
-
@tuns.delete( [ tun_info[ :orig_src_addr ], tun_info[ :dst_addr ] ].join )
|
198
|
-
|
199
|
-
if @mappings.include?( tun_info[ :src_addr ] ) then
|
200
|
-
orig_src_addr, dst_addr, timeout, read_at = @mappings[ tun_info[ :src_addr ] ]
|
201
|
-
|
202
|
-
if orig_src_addr == tun_info[ :orig_src_addr ] && dst_addr == tun_info[ :dst_addr ] then
|
203
|
-
@mappings.delete( tun_info[ :src_addr ] )
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def write_redir( redir )
|
209
|
-
while @redir_wbuffs.any? do
|
210
|
-
to_addr, data = @redir_wbuffs.first
|
211
|
-
return unless send_data( redir, data, to_addr )
|
212
|
-
@redir_wbuffs.shift
|
213
|
-
end
|
214
|
-
|
215
|
-
@writes.delete( redir )
|
216
|
-
end
|
217
|
-
|
218
|
-
def write_tun( tun )
|
219
|
-
tun_info = @tun_infos[ tun ]
|
220
|
-
|
221
|
-
if tun_info[ :is_closing ] then
|
222
|
-
close_tun( tun )
|
223
|
-
return
|
224
|
-
end
|
225
|
-
|
226
|
-
while tun_info[ :wbuffs ].any? do
|
227
|
-
to_addr, data = tun_info[ :wbuffs ].first
|
228
|
-
return unless send_data( tun, data, to_addr )
|
229
|
-
tun_info[ :wbuffs ].shift
|
230
|
-
end
|
231
|
-
|
232
|
-
@writes.delete( tun )
|
233
|
-
end
|
234
|
-
|
235
|
-
def read_dotr( dotr )
|
236
|
-
dotr.read( 1 )
|
237
|
-
end
|
238
|
-
|
239
|
-
def read_redir( redir )
|
240
|
-
data, addrinfo, rflags, *controls = redir.recvmsg
|
241
|
-
src_addr = addrinfo.to_sockaddr
|
242
|
-
is_hit_cache = false
|
243
|
-
now = Time.new
|
244
|
-
# puts "debug redir recv #{ data.inspect } from #{ addrinfo.inspect }"
|
245
|
-
|
246
|
-
if @mappings.include?( src_addr ) then
|
247
|
-
orig_src_addr, dst_addr, timeout, read_at = @mappings[ src_addr ]
|
248
|
-
|
249
|
-
if now - read_at < timeout then
|
250
|
-
# puts "debug hit cache #{ addrinfo.inspect }"
|
251
|
-
is_hit_cache = true
|
252
|
-
else
|
253
|
-
# puts "debug cache timeout #{ addrinfo.inspect }"
|
254
|
-
@mappings.delete( src_addr )
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
unless is_hit_cache then
|
259
|
-
# 2 udp 4 timeout 5 src 7 sport 9 [UNREPLIED] 11 dst 13 dport
|
260
|
-
# 2 udp 4 timeout 5 src 7 sport 10 dst 12 dport
|
261
|
-
bin = IO.binread( '/proc/net/nf_conntrack' )
|
262
|
-
rows = bin.split( "\n" ).map { | line | line.split( ' ' ) }
|
263
|
-
row = rows.find { | _row | _row[ 2 ] == 'udp' && ( ( _row[ 10 ].split( '=' )[ 1 ] == addrinfo.ip_address && _row[ 12 ].split( '=' )[ 1 ].to_i == addrinfo.ip_port ) || ( _row[ 9 ] == '[UNREPLIED]' && _row[ 11 ].split( '=' )[ 1 ] == addrinfo.ip_address && _row[ 13 ].split( '=' )[ 1 ].to_i == addrinfo.ip_port ) ) }
|
264
|
-
|
265
|
-
unless row then
|
266
|
-
puts "miss conntrack #{ addrinfo.inspect } #{ Time.new }"
|
267
|
-
IO.binwrite( '/tmp/nf_conntrack', bin )
|
268
|
-
return
|
269
|
-
end
|
270
|
-
|
271
|
-
timeout = row[ 4 ].to_i
|
272
|
-
orig_src_ip = row[ 5 ].split( '=' )[ 1 ]
|
273
|
-
orig_src_port = row[ 7 ].split( '=' )[ 1 ].to_i
|
274
|
-
dst_ip = row[ 6 ].split( '=' )[ 1 ]
|
275
|
-
dst_port = row[ 8 ].split( '=' )[ 1 ].to_i
|
276
|
-
orig_src_addr = Socket.sockaddr_in( orig_src_port, orig_src_ip )
|
277
|
-
dst_addr = Socket.sockaddr_in( dst_port, dst_ip )
|
278
|
-
|
279
|
-
if Addrinfo.new( dst_addr ).ipv4_private? then
|
280
|
-
puts "dst is private? #{ Addrinfo.new( dst_addr ).inspect } #{ Addrinfo.new( src_addr ).inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Time.new }"
|
281
|
-
add_redir_wbuff( redir, dst_addr, data )
|
282
|
-
return
|
283
|
-
end
|
284
|
-
|
285
|
-
# puts "debug save cache #{ addrinfo.inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect } #{ timeout } #{ now }"
|
286
|
-
@mappings[ src_addr ] = [ orig_src_addr, dst_addr, timeout, now ]
|
287
|
-
end
|
288
|
-
|
289
|
-
tun = @tuns[ [ orig_src_addr, dst_addr ].join ]
|
290
|
-
|
291
|
-
unless tun then
|
292
|
-
tun = new_a_tun( orig_src_addr, dst_addr, src_addr )
|
293
|
-
|
294
|
-
# puts "debug tun send to udpd #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect }"
|
295
|
-
ctlmsg = [ orig_src_addr, dst_addr ].join
|
296
|
-
add_tun_wbuff( tun, @udpd_addr, ctlmsg )
|
297
|
-
end
|
298
|
-
|
299
|
-
tun_info = @tun_infos[ tun ]
|
300
|
-
add_tun_wbuff( tun, tun_info[ :tund_addr ], data )
|
301
|
-
end
|
302
|
-
|
303
|
-
def read_tun( tun )
|
304
|
-
data, addrinfo, rflags, *controls = tun.recvmsg
|
305
|
-
from_addr = addrinfo.to_sockaddr
|
306
|
-
tun_info = @tun_infos[ tun ]
|
307
|
-
tun_info[ :last_traff_at ] = Time.new
|
308
|
-
|
309
|
-
if from_addr == @udpd_addr then
|
310
|
-
tund_port = data[ 0, 2 ].unpack( 'n' ).first
|
311
|
-
tund_addr = Socket.sockaddr_in( tund_port, @udpd_host )
|
312
|
-
tun_info[ :tund_addr ] = tund_addr
|
313
|
-
|
314
|
-
if tun_info[ :rbuffs ].any? then
|
315
|
-
tun_info[ :wbuffs ] += tun_info[ :rbuffs ].map{ | rbuff | [ tund_addr, rbuff ] }
|
316
|
-
tun_info[ :rbuffs ].clear
|
317
|
-
add_write( tun )
|
318
|
-
end
|
319
|
-
|
320
|
-
elsif from_addr == tun_info[ :tund_addr ] then
|
321
|
-
add_redir_wbuff( @redir, tun_info[ :src_addr ], data )
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
end
|
326
|
-
end
|
data/lib/girl/udpd.rb
DELETED
@@ -1,316 +0,0 @@
|
|
1
|
-
require 'girl/version'
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
##
|
5
|
-
# Girl::Udpd - udp透明转发,远端。
|
6
|
-
#
|
7
|
-
module Girl
|
8
|
-
class Udpd
|
9
|
-
|
10
|
-
def initialize( port = 3030 )
|
11
|
-
@mutex = Mutex.new
|
12
|
-
@reads = []
|
13
|
-
@writes = []
|
14
|
-
@roles = {} # :dotr / :udpd / :tund
|
15
|
-
@udpd_wbuffs = [] # [ tun_addr ctlmsg ] ...
|
16
|
-
@tunds = {} # [ tun_ip_addr orig_src_addr ] => tund
|
17
|
-
@tund_infos = {} # tund => {}
|
18
|
-
# port: port
|
19
|
-
# tun_ip_addr: sockaddr
|
20
|
-
# orig_src_addr: sockaddr
|
21
|
-
# wbuffs: [] # [ to_addr, data ] ...
|
22
|
-
# dst_addrs: { tun_addr => dst_addr }
|
23
|
-
# tun_addrs: { dst_addr => tun_addr }
|
24
|
-
# is_tunneleds: { [ tun_addr dst_addr ] => false }
|
25
|
-
# unpaired_dst_rbuffs: { dst_addr => [] }
|
26
|
-
# last_traff_at: now
|
27
|
-
dotr, dotw = IO.pipe
|
28
|
-
@dotw = dotw
|
29
|
-
add_read( dotr, :dotr )
|
30
|
-
new_a_udpd( port )
|
31
|
-
end
|
32
|
-
|
33
|
-
def looping
|
34
|
-
loop_expire
|
35
|
-
|
36
|
-
loop do
|
37
|
-
rs, ws = IO.select( @reads, @writes )
|
38
|
-
|
39
|
-
@mutex.synchronize do
|
40
|
-
ws.each do | sock |
|
41
|
-
case @roles[ sock ]
|
42
|
-
when :udpd then
|
43
|
-
write_udpd( sock )
|
44
|
-
when :tund then
|
45
|
-
write_tund( sock )
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
rs.each do | sock |
|
50
|
-
case @roles[ sock ]
|
51
|
-
when :dotr then
|
52
|
-
read_dotr( sock )
|
53
|
-
when :udpd then
|
54
|
-
read_udpd( sock )
|
55
|
-
when :tund then
|
56
|
-
read_tund( sock )
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def quit!
|
64
|
-
exit
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def loop_expire
|
70
|
-
Thread.new do
|
71
|
-
loop do
|
72
|
-
sleep 30
|
73
|
-
|
74
|
-
@mutex.synchronize do
|
75
|
-
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 then
|
81
|
-
set_is_closing( tund )
|
82
|
-
trigger = true
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
next_tick if trigger
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def new_a_udpd( port )
|
93
|
-
udpd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
94
|
-
udpd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
95
|
-
udpd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
|
96
|
-
puts "udpd bound on #{ port } #{ Time.new }"
|
97
|
-
@udpd = udpd
|
98
|
-
add_read( udpd, :udpd )
|
99
|
-
end
|
100
|
-
|
101
|
-
def pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
|
102
|
-
from_addr = [ tun_ip_addr, orig_src_addr ].join
|
103
|
-
td_addr = [ tun_addr, dst_addr ].join
|
104
|
-
tund = @tunds[ from_addr ]
|
105
|
-
|
106
|
-
if tund then
|
107
|
-
tund_info = @tund_infos[ tund ]
|
108
|
-
tund_info[ :dst_addrs ][ tun_addr ] = dst_addr
|
109
|
-
tund_info[ :tun_addrs ][ dst_addr ] = tun_addr
|
110
|
-
tund_info[ :is_tunneleds ][ td_addr ] = false
|
111
|
-
else
|
112
|
-
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
113
|
-
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
114
|
-
tund.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
|
115
|
-
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
116
|
-
tund_port = tund.local_address.ip_unpack.last
|
117
|
-
|
118
|
-
@tund_infos[ tund ] = {
|
119
|
-
port: tund_port,
|
120
|
-
tun_ip_addr: tun_ip_addr,
|
121
|
-
orig_src_addr: orig_src_addr,
|
122
|
-
wbuffs: [],
|
123
|
-
dst_addrs: { tun_addr => dst_addr },
|
124
|
-
tun_addrs: { dst_addr => tun_addr },
|
125
|
-
is_tunneleds: { td_addr => false },
|
126
|
-
unpaired_dst_rbuffs: {},
|
127
|
-
last_traff_at: Time.new,
|
128
|
-
is_closing: false
|
129
|
-
}
|
130
|
-
|
131
|
-
@tunds[ from_addr ] = tund
|
132
|
-
add_read( tund, :tund )
|
133
|
-
end
|
134
|
-
|
135
|
-
tund
|
136
|
-
end
|
137
|
-
|
138
|
-
def add_tund_wbuff( tund, to_addr, data )
|
139
|
-
tund_info = @tund_infos[ tund ]
|
140
|
-
tund_info[ :wbuffs ] << [ to_addr, data ]
|
141
|
-
|
142
|
-
add_write( tund )
|
143
|
-
end
|
144
|
-
|
145
|
-
def add_read( sock, role )
|
146
|
-
unless @reads.include?( sock ) then
|
147
|
-
@reads << sock
|
148
|
-
end
|
149
|
-
|
150
|
-
@roles[ sock ] = role
|
151
|
-
end
|
152
|
-
|
153
|
-
def add_write( sock )
|
154
|
-
unless @writes.include?( sock ) then
|
155
|
-
@writes << sock
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def set_is_closing( tund )
|
160
|
-
if tund && !tund.closed? then
|
161
|
-
# puts "debug1 set tund is closing"
|
162
|
-
|
163
|
-
tund_info = @tund_infos[ tund ]
|
164
|
-
tund_info[ :is_closing ] = true
|
165
|
-
|
166
|
-
@reads.delete( tund )
|
167
|
-
add_write( tund )
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def send_data( sock, data, to_addr )
|
172
|
-
begin
|
173
|
-
sock.sendmsg( data, 0, to_addr )
|
174
|
-
rescue IO::WaitWritable, Errno::EINTR
|
175
|
-
return false
|
176
|
-
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
177
|
-
if @roles[ sock ] == :tund then
|
178
|
-
puts "#{ Time.new } #{ e.class }, close tund"
|
179
|
-
close_tund( sock )
|
180
|
-
return false
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
true
|
185
|
-
end
|
186
|
-
|
187
|
-
def close_tund( tund )
|
188
|
-
tund.close
|
189
|
-
@reads.delete( tund )
|
190
|
-
@writes.delete( tund )
|
191
|
-
@roles.delete( tund )
|
192
|
-
tund_info = @tund_infos.delete( tund )
|
193
|
-
@tunds.delete( [ tund_info[ :tun_ip_addr ], tund_info[ :orig_src_addr ] ].join )
|
194
|
-
end
|
195
|
-
|
196
|
-
def next_tick
|
197
|
-
@dotw.write( '.' )
|
198
|
-
end
|
199
|
-
|
200
|
-
def write_udpd( udpd )
|
201
|
-
while @udpd_wbuffs.any? do
|
202
|
-
to_addr, data = @udpd_wbuffs.first
|
203
|
-
return unless send_data( udpd, data, to_addr )
|
204
|
-
@udpd_wbuffs.shift
|
205
|
-
end
|
206
|
-
|
207
|
-
@writes.delete( udpd )
|
208
|
-
end
|
209
|
-
|
210
|
-
def write_tund( tund )
|
211
|
-
tund_info = @tund_infos[ tund ]
|
212
|
-
|
213
|
-
if tund_info[ :is_closing ] then
|
214
|
-
close_tund( tund )
|
215
|
-
return
|
216
|
-
end
|
217
|
-
|
218
|
-
while tund_info[ :wbuffs ].any? do
|
219
|
-
to_addr, data = tund_info[ :wbuffs ].first
|
220
|
-
return unless send_data( tund, data, to_addr )
|
221
|
-
tund_info[ :wbuffs ].shift
|
222
|
-
end
|
223
|
-
|
224
|
-
@writes.delete( tund )
|
225
|
-
end
|
226
|
-
|
227
|
-
def read_dotr( dotr )
|
228
|
-
dotr.read( 1 )
|
229
|
-
end
|
230
|
-
|
231
|
-
def read_udpd( udpd )
|
232
|
-
data, addrinfo, rflags, *controls = udpd.recvmsg
|
233
|
-
# puts "debug udpd recv #{ data.inspect } from #{ addrinfo.inspect }"
|
234
|
-
orig_src_addr = data[ 0, 16 ]
|
235
|
-
dst_addr = data[ 16, 16 ]
|
236
|
-
tun_addr = addrinfo.to_sockaddr
|
237
|
-
tun_ip_addr = Addrinfo.ip( addrinfo.ip_address ).to_sockaddr
|
238
|
-
|
239
|
-
return unless Addrinfo.new( orig_src_addr ).ipv4?
|
240
|
-
|
241
|
-
dst_addrinfo = Addrinfo.new( dst_addr )
|
242
|
-
return unless dst_addrinfo.ipv4?
|
243
|
-
return if dst_addrinfo.ipv4_private?
|
244
|
-
|
245
|
-
tund = pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
|
246
|
-
tund_info = @tund_infos[ tund ]
|
247
|
-
tund_port = tund_info[ :port ]
|
248
|
-
|
249
|
-
# puts "debug udpd send to tun #{ tund_port } #{ addrinfo.inspect }"
|
250
|
-
ctlmsg = [ tund_port ].pack( 'n' )
|
251
|
-
@udpd_wbuffs << [ tun_addr, ctlmsg ]
|
252
|
-
add_write( udpd )
|
253
|
-
end
|
254
|
-
|
255
|
-
def read_tund( tund )
|
256
|
-
data, addrinfo, rflags, *controls = tund.recvmsg
|
257
|
-
from_addr = addrinfo.to_sockaddr
|
258
|
-
tund_info = @tund_infos[ tund ]
|
259
|
-
tund_info[ :last_traff_at ] = Time.new
|
260
|
-
to_addr = tund_info[ :dst_addrs ][ from_addr ]
|
261
|
-
|
262
|
-
if to_addr then
|
263
|
-
# 来自tun,发给dst。
|
264
|
-
td_addr = [ from_addr, to_addr ].join
|
265
|
-
is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
|
266
|
-
|
267
|
-
unless is_tunneled then
|
268
|
-
# puts "debug first traffic from tun #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
269
|
-
# 发暂存
|
270
|
-
if tund_info[ :unpaired_dst_rbuffs ].include?( to_addr ) then
|
271
|
-
rbuffs = tund_info[ :unpaired_dst_rbuffs ].delete( to_addr )
|
272
|
-
# puts "debug move tund.dst.rbuffs to tund.wbuffs #{ rbuffs.inspect }"
|
273
|
-
tund_info[ :wbuffs ] += rbuffs.map{ | rbuff | [ from_addr, rbuff ] }
|
274
|
-
end
|
275
|
-
|
276
|
-
tund_info[ :is_tunneleds ][ td_addr ] = true
|
277
|
-
end
|
278
|
-
|
279
|
-
# 如果对面没来过流量,且在nat里,nat规则是只对去过的目的地做接收,那么,先过去的流量会撞死。
|
280
|
-
# 没关系,撞死的流量通常是打洞数据,在应用计算之内,打洞数据通常是连发的。
|
281
|
-
# puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
282
|
-
add_tund_wbuff( tund, to_addr, data )
|
283
|
-
return
|
284
|
-
end
|
285
|
-
|
286
|
-
to_addr = tund_info[ :tun_addrs ][ from_addr ]
|
287
|
-
|
288
|
-
if to_addr then
|
289
|
-
# 来自dst,发给tun。
|
290
|
-
# puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
291
|
-
|
292
|
-
td_addr = [ to_addr, from_addr ].join
|
293
|
-
is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
|
294
|
-
|
295
|
-
if is_tunneled then
|
296
|
-
add_tund_wbuff( tund, to_addr, data )
|
297
|
-
return
|
298
|
-
end
|
299
|
-
|
300
|
-
# puts "debug #{ Addrinfo.new( to_addr ).inspect } #{ addrinfo.inspect } not tunneled"
|
301
|
-
end
|
302
|
-
|
303
|
-
# 来自未知的地方,或者对应的tun还没来流量,记暂存
|
304
|
-
unless tund_info[ :unpaired_dst_rbuffs ][ from_addr ] then
|
305
|
-
tund_info[ :unpaired_dst_rbuffs ][ from_addr ] = []
|
306
|
-
end
|
307
|
-
|
308
|
-
# 暂存5条(连发打洞数据,不需要存多)。
|
309
|
-
if tund_info[ :unpaired_dst_rbuffs ][ from_addr ].size < 5 then
|
310
|
-
# puts "debug save other dst rbuff #{ addrinfo.inspect } #{ data.inspect }"
|
311
|
-
tund_info[ :unpaired_dst_rbuffs ][ from_addr ] << data
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
end
|
316
|
-
end
|