girl 0.75.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 +7 -0
- data/girl.gemspec +34 -0
- data/lib/girl.rb +2 -0
- data/lib/girl/custom.rb +12 -0
- data/lib/girl/head.rb +50 -0
- data/lib/girl/proxy.rb +208 -0
- data/lib/girl/proxy_custom.rb +15 -0
- data/lib/girl/proxy_worker.rb +1425 -0
- data/lib/girl/proxyd.rb +96 -0
- data/lib/girl/proxyd_custom.rb +12 -0
- data/lib/girl/proxyd_worker.rb +987 -0
- data/lib/girl/udp.rb +300 -0
- data/lib/girl/udpd.rb +286 -0
- data/lib/girl/version.rb +3 -0
- metadata +57 -0
data/lib/girl/udp.rb
ADDED
@@ -0,0 +1,300 @@
|
|
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
|
+
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
|
+
@udpd_host = udpd_host
|
29
|
+
@udpd_addr = Socket.sockaddr_in( udpd_port, udpd_host )
|
30
|
+
@ctlw = ctlw
|
31
|
+
@redir = redir
|
32
|
+
@reads = [ ctlr, redir ]
|
33
|
+
@writes = []
|
34
|
+
@closings = []
|
35
|
+
@roles = {
|
36
|
+
ctlr => :ctlr, # :ctlr / :redir / :tun
|
37
|
+
redir => :redir
|
38
|
+
}
|
39
|
+
@redir_wbuffs = [] # [ src_addr data ] ...
|
40
|
+
@tuns = {} # [ orig_src_addr dst_addr ]=> tun
|
41
|
+
@mappings = {} # src_addr => [ orig_src_addr dst_addr ]
|
42
|
+
@tun_infos = {} # tun => {}
|
43
|
+
# orig_src_addr: sockaddr
|
44
|
+
# dst_addr: sockaddr
|
45
|
+
# src_addr: sockaddr
|
46
|
+
# tund_addr: sockaddr
|
47
|
+
# rbuffs: []
|
48
|
+
# wbuffs: []
|
49
|
+
# last_traff_at: now
|
50
|
+
end
|
51
|
+
|
52
|
+
def looping
|
53
|
+
loop_expire
|
54
|
+
|
55
|
+
loop do
|
56
|
+
rs, ws = IO.select( @reads, @writes )
|
57
|
+
|
58
|
+
@mutex.synchronize do
|
59
|
+
rs.each do | sock |
|
60
|
+
case @roles[ sock ]
|
61
|
+
when :ctlr
|
62
|
+
read_ctlr( sock )
|
63
|
+
when :redir
|
64
|
+
read_redir( sock )
|
65
|
+
when :tun
|
66
|
+
read_tun( sock )
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
ws.each do | sock |
|
71
|
+
case @roles[ sock ]
|
72
|
+
when :redir
|
73
|
+
write_redir( sock )
|
74
|
+
when :tun
|
75
|
+
write_tun( sock )
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def quit!
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def read_ctlr( ctlr )
|
89
|
+
od_addr = ctlr.read( 32 )
|
90
|
+
tun = @tuns[ od_addr ]
|
91
|
+
|
92
|
+
if tun
|
93
|
+
add_closing( tun )
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def read_redir( redir )
|
98
|
+
data, addrinfo, rflags, *controls = redir.recvmsg
|
99
|
+
src_addr = addrinfo.to_sockaddr
|
100
|
+
is_hit_cache = false
|
101
|
+
now = Time.new
|
102
|
+
# puts "debug redir recv #{ data.inspect } from #{ addrinfo.inspect }"
|
103
|
+
|
104
|
+
if @mappings.include?( src_addr )
|
105
|
+
orig_src_addr, dst_addr, timeout, read_at = @mappings[ src_addr ]
|
106
|
+
|
107
|
+
if now - read_at < timeout
|
108
|
+
# puts "debug hit cache #{ addrinfo.inspect }"
|
109
|
+
is_hit_cache = true
|
110
|
+
else
|
111
|
+
# puts "debug cache timeout #{ addrinfo.inspect }"
|
112
|
+
@mappings.delete( src_addr )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
unless is_hit_cache
|
117
|
+
# 2 udp 4 timeout 5 src 7 sport 9 [UNREPLIED] 11 dst 13 dport
|
118
|
+
# 2 udp 4 timeout 5 src 7 sport 10 dst 12 dport
|
119
|
+
bin = IO.binread( '/proc/net/nf_conntrack' )
|
120
|
+
rows = bin.split( "\n" ).map { | line | line.split( ' ' ) }
|
121
|
+
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 ) ) }
|
122
|
+
|
123
|
+
unless row
|
124
|
+
puts "miss conntrack #{ addrinfo.inspect } #{ Time.new }"
|
125
|
+
IO.binwrite( '/tmp/nf_conntrack', bin )
|
126
|
+
return
|
127
|
+
end
|
128
|
+
|
129
|
+
timeout = row[ 4 ].to_i
|
130
|
+
orig_src_ip = row[ 5 ].split( '=' )[ 1 ]
|
131
|
+
orig_src_port = row[ 7 ].split( '=' )[ 1 ].to_i
|
132
|
+
dst_ip = row[ 6 ].split( '=' )[ 1 ]
|
133
|
+
dst_port = row[ 8 ].split( '=' )[ 1 ].to_i
|
134
|
+
orig_src_addr = Socket.sockaddr_in( orig_src_port, orig_src_ip )
|
135
|
+
dst_addr = Socket.sockaddr_in( dst_port, dst_ip )
|
136
|
+
|
137
|
+
if Addrinfo.new( dst_addr ).ipv4_private?
|
138
|
+
puts "dst is private? #{ Addrinfo.new( dst_addr ).inspect } #{ Addrinfo.new( src_addr ).inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Time.new }"
|
139
|
+
add_redir_wbuff( redir, dst_addr, data )
|
140
|
+
return
|
141
|
+
end
|
142
|
+
|
143
|
+
# puts "debug save cache #{ addrinfo.inspect } #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect } #{ timeout } #{ now }"
|
144
|
+
@mappings[ src_addr ] = [ orig_src_addr, dst_addr, timeout, now ]
|
145
|
+
end
|
146
|
+
|
147
|
+
tun = @tuns[ [ orig_src_addr, dst_addr ].join ]
|
148
|
+
|
149
|
+
unless tun
|
150
|
+
tun = new_a_tun( orig_src_addr, dst_addr, src_addr )
|
151
|
+
|
152
|
+
# puts "debug tun send to udpd #{ Addrinfo.new( orig_src_addr ).inspect } #{ Addrinfo.new( dst_addr ).inspect }"
|
153
|
+
ctlmsg = [ orig_src_addr, dst_addr ].join
|
154
|
+
add_tun_wbuff( tun, @udpd_addr, ctlmsg )
|
155
|
+
end
|
156
|
+
|
157
|
+
tun_info = @tun_infos[ tun ]
|
158
|
+
add_tun_wbuff( tun, tun_info[ :tund_addr ], data )
|
159
|
+
end
|
160
|
+
|
161
|
+
def read_tun( tun )
|
162
|
+
data, addrinfo, rflags, *controls = tun.recvmsg
|
163
|
+
from_addr = addrinfo.to_sockaddr
|
164
|
+
tun_info = @tun_infos[ tun ]
|
165
|
+
tun_info[ :last_traff_at ] = Time.new
|
166
|
+
|
167
|
+
if from_addr == @udpd_addr
|
168
|
+
tund_port = data[ 0, 2 ].unpack( 'n' ).first
|
169
|
+
tund_addr = Socket.sockaddr_in( tund_port, @udpd_host )
|
170
|
+
tun_info[ :tund_addr ] = tund_addr
|
171
|
+
|
172
|
+
if tun_info[ :rbuffs ].any?
|
173
|
+
tun_info[ :wbuffs ] += tun_info[ :rbuffs ].map{ | rbuff | [ tund_addr, rbuff ] }
|
174
|
+
tun_info[ :rbuffs ].clear
|
175
|
+
add_write( tun )
|
176
|
+
end
|
177
|
+
|
178
|
+
elsif from_addr == tun_info[ :tund_addr ]
|
179
|
+
add_redir_wbuff( @redir, tun_info[ :src_addr ], data )
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
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
|
+
end
|
300
|
+
end
|
data/lib/girl/udpd.rb
ADDED
@@ -0,0 +1,286 @@
|
|
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
|
+
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
|
+
@mutex = Mutex.new
|
19
|
+
@ctlw = ctlw
|
20
|
+
@udpd = udpd
|
21
|
+
@reads = [ ctlr, udpd ]
|
22
|
+
@writes = []
|
23
|
+
@closings = []
|
24
|
+
@roles = {
|
25
|
+
ctlr => :ctlr, # :ctlr / :udpd / :tund
|
26
|
+
udpd => :udpd
|
27
|
+
}
|
28
|
+
@udpd_wbuffs = [] # [ tun_addr ctlmsg ] ...
|
29
|
+
@tunds = {} # [ tun_ip_addr orig_src_addr ] => tund
|
30
|
+
@tund_infos = {} # tund => {}
|
31
|
+
# port: port
|
32
|
+
# tun_ip_addr: sockaddr
|
33
|
+
# orig_src_addr: sockaddr
|
34
|
+
# wbuffs: [] # [ to_addr, data ] ...
|
35
|
+
# dst_addrs: { tun_addr => dst_addr }
|
36
|
+
# tun_addrs: { dst_addr => tun_addr }
|
37
|
+
# is_tunneleds: { [ tun_addr dst_addr ] => false }
|
38
|
+
# unpaired_dst_rbuffs: { dst_addr => [] }
|
39
|
+
# last_traff_at: now
|
40
|
+
end
|
41
|
+
|
42
|
+
def looping
|
43
|
+
loop_expire
|
44
|
+
|
45
|
+
loop do
|
46
|
+
rs, ws = IO.select( @reads, @writes )
|
47
|
+
|
48
|
+
@mutex.synchronize do
|
49
|
+
rs.each do | sock |
|
50
|
+
case @roles[ sock ]
|
51
|
+
when :ctlr
|
52
|
+
read_ctlr( sock )
|
53
|
+
when :udpd
|
54
|
+
read_udpd( sock )
|
55
|
+
when :tund
|
56
|
+
read_tund( sock )
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
ws.each do | sock |
|
61
|
+
case @roles[ sock ]
|
62
|
+
when :udpd
|
63
|
+
write_udpd( sock )
|
64
|
+
when :tund
|
65
|
+
write_tund( sock )
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def quit!
|
73
|
+
exit
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def read_ctlr( ctlr )
|
79
|
+
to_addr = ctlr.read( 32 )
|
80
|
+
tund = @tunds[ to_addr ]
|
81
|
+
|
82
|
+
if tund
|
83
|
+
add_closing( tund )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def read_udpd( udpd )
|
88
|
+
data, addrinfo, rflags, *controls = udpd.recvmsg
|
89
|
+
# puts "debug udpd recv #{ data.inspect } from #{ addrinfo.inspect }"
|
90
|
+
orig_src_addr = data[ 0, 16 ]
|
91
|
+
dst_addr = data[ 16, 16 ]
|
92
|
+
tun_addr = addrinfo.to_sockaddr
|
93
|
+
tun_ip_addr = Addrinfo.ip( addrinfo.ip_address ).to_sockaddr
|
94
|
+
|
95
|
+
return unless Addrinfo.new( orig_src_addr ).ipv4?
|
96
|
+
|
97
|
+
dst_addrinfo = Addrinfo.new( dst_addr )
|
98
|
+
return unless dst_addrinfo.ipv4?
|
99
|
+
return if dst_addrinfo.ipv4_private?
|
100
|
+
|
101
|
+
tund = pair_tund( tun_addr, tun_ip_addr, orig_src_addr, dst_addr )
|
102
|
+
tund_info = @tund_infos[ tund ]
|
103
|
+
tund_port = tund_info[ :port ]
|
104
|
+
|
105
|
+
# puts "debug udpd send to tun #{ tund_port } #{ addrinfo.inspect }"
|
106
|
+
ctlmsg = [ tund_port ].pack( 'n' )
|
107
|
+
@udpd_wbuffs << [ tun_addr, ctlmsg ]
|
108
|
+
add_write( udpd )
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_tund( tund )
|
112
|
+
data, addrinfo, rflags, *controls = tund.recvmsg
|
113
|
+
from_addr = addrinfo.to_sockaddr
|
114
|
+
tund_info = @tund_infos[ tund ]
|
115
|
+
tund_info[ :last_traff_at ] = Time.new
|
116
|
+
to_addr = tund_info[ :dst_addrs ][ from_addr ]
|
117
|
+
|
118
|
+
if to_addr
|
119
|
+
# 来自tun,发给dst。
|
120
|
+
td_addr = [ from_addr, to_addr ].join
|
121
|
+
is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
|
122
|
+
|
123
|
+
unless is_tunneled
|
124
|
+
# puts "debug first traffic from tun #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
125
|
+
# 发暂存
|
126
|
+
if tund_info[ :unpaired_dst_rbuffs ].include?( to_addr )
|
127
|
+
rbuffs = tund_info[ :unpaired_dst_rbuffs ].delete( to_addr )
|
128
|
+
# puts "debug move tund.dst.rbuffs to tund.wbuffs #{ rbuffs.inspect }"
|
129
|
+
tund_info[ :wbuffs ] += rbuffs.map{ | rbuff | [ from_addr, rbuff ] }
|
130
|
+
end
|
131
|
+
|
132
|
+
tund_info[ :is_tunneleds ][ td_addr ] = true
|
133
|
+
end
|
134
|
+
|
135
|
+
# 如果对面没来过流量,且在nat里,nat规则是只对去过的目的地做接收,那么,先过去的流量会撞死。
|
136
|
+
# 没关系,撞死的流量通常是打洞数据,在应用计算之内,打洞数据通常是连发的。
|
137
|
+
# puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
138
|
+
add_tund_wbuff( tund, to_addr, data )
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
to_addr = tund_info[ :tun_addrs ][ from_addr ]
|
143
|
+
|
144
|
+
if to_addr
|
145
|
+
# 来自dst,发给tun。
|
146
|
+
# puts "debug #{ data.inspect } from #{ addrinfo.inspect } to #{ Addrinfo.new( to_addr ).inspect }"
|
147
|
+
|
148
|
+
td_addr = [ to_addr, from_addr ].join
|
149
|
+
is_tunneled = tund_info[ :is_tunneleds ][ td_addr ]
|
150
|
+
|
151
|
+
if is_tunneled
|
152
|
+
add_tund_wbuff( tund, to_addr, data )
|
153
|
+
return
|
154
|
+
end
|
155
|
+
|
156
|
+
# puts "debug #{ Addrinfo.new( to_addr ).inspect } #{ addrinfo.inspect } not tunneled"
|
157
|
+
end
|
158
|
+
|
159
|
+
# 来自未知的地方,或者对应的tun还没来流量,记暂存
|
160
|
+
unless tund_info[ :unpaired_dst_rbuffs ][ from_addr ]
|
161
|
+
tund_info[ :unpaired_dst_rbuffs ][ from_addr ] = []
|
162
|
+
end
|
163
|
+
|
164
|
+
# 暂存5条(连发打洞数据,不需要存多)。
|
165
|
+
if tund_info[ :unpaired_dst_rbuffs ][ from_addr ].size < 5
|
166
|
+
# puts "debug save other dst rbuff #{ addrinfo.inspect } #{ data.inspect }"
|
167
|
+
tund_info[ :unpaired_dst_rbuffs ][ from_addr ] << data
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
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
|
+
end
|
286
|
+
end
|