girl 0.70.0 → 0.73.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb6d1abdce7bdbf84b4fa3c745be76cf5a990ebc0e7533deae6a97567e043524
4
- data.tar.gz: 501bf156af3a02a6ef17f98e8ea16d71c152c02da3e1eba3593e11f6dd0f1541
3
+ metadata.gz: d975dc92620d5ea2c27493ed0fbbb19a145fc7ecda564c2f5609eb710e06912d
4
+ data.tar.gz: 5c098f6b8aecc89d246e8e4b1c477eb42e86ce695b27d4329962255d380b4f09
5
5
  SHA512:
6
- metadata.gz: 7485329397159e630ad15807d9d973a9080261ab44ce18a99fc0a1eb6832b70b82ff177968049b59383a79cc23db00f951d265cf22d2ad9fbdeaf1332a314185
7
- data.tar.gz: b60356633483e23338e2f926905cfa0fd3d2d39e98a6b638705d26831406564082bea91ba7bab4d02b3eab77abd020854677be9597890ac070b05edd916c8081
6
+ metadata.gz: 326b198254e6508e42b00145e00c56214574510448ba05b852b257b44da2c54b443509d1e2af514a668b1394e27cfff2ae93cf1957526adf9315a73e32a3ebbd
7
+ data.tar.gz: 21e0cab87ffe323314607d74c3884eb2987208a9375b417c1158d1768e7aafcf536d7370d5fdff58b08d1d7acb95da009eba57ddcc9d9d22702e405078b2c7e5
@@ -1,17 +1,17 @@
1
1
  module Girl
2
- PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
- CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
- WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
5
- WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
6
- RESUME_BELOW = 50_000 # 降到多少以下恢复写
7
- EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
8
- EXPIRE_AFTER = 300 # 多久没有新流量,过期
9
- CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
10
- STATUS_INTERVAL = 0.5 # 发送状态间隔
11
- SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
12
- BREAK_SEND_MISS = 10_000 # miss包个数上限,达到上限忽略要后面的段,可控碎片缓存
13
- CONFUSE_UNTIL = 5 # 混淆前几个包
14
- RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
2
+ PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
+ CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
+ WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
5
+ WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
6
+ RESUME_BELOW = 50_000 # 降到多少以下恢复写
7
+ EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
8
+ EXPIRE_AFTER = 300 # 多久没有新流量,过期
9
+ CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
10
+ STATUS_INTERVAL = 0.5 # 发送状态间隔
11
+ SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
12
+ BREAK_SEND_MISS = 10_000 # miss包个数上限,达到上限忽略要后面的段,可控碎片缓存
13
+ CONFUSE_UNTIL = 5 # 混淆前几个包
14
+ RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
15
15
  TUND_PORT = 1
16
16
  HEARTBEAT = 2
17
17
  A_NEW_SOURCE = 3
@@ -23,15 +23,15 @@ require 'socket'
23
23
  #
24
24
  # tun-tund:
25
25
  #
26
- # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
- # 3 a new src -> Q>: src id -> encoded destination address
28
- # 4 paired -> Q>: src id -> n: dst port
29
- # 5 dst status -> n: dst port -> Q>: biggest relayed dst pack id -> Q>: continue src pack id
30
- # 6 src status -> Q>: src id -> Q>: biggest relayed src pack id -> Q>: continue dst pack id
31
- # 7 miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end
32
- # 8 fin1 -> Q>/n: src id / dst port -> Q>: biggest src pack id / biggest dst pack id -> Q>: continue dst pack id / continue src pack id
26
+ # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
+ # 3 a new source -> Q>: src id -> encoded destination address
28
+ # 4 paired -> Q>: src id -> n: dst port
29
+ # 5 dest status -> n: dst port -> Q>: biggest relayed dst pack id -> Q>: continue src pack id
30
+ # 6 source status -> Q>: src id -> Q>: biggest relayed src pack id -> Q>: continue dst pack id
31
+ # 7 miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end
32
+ # 8 fin1 -> Q>/n: src id / dst port -> Q>: biggest src pack id / biggest dst pack id -> Q>: continue dst pack id / continue src pack id
33
33
  # 9 not use
34
- # 10 fin2 -> Q>/n: src id / dst port
34
+ # 10 fin2 -> Q>/n: src id / dst port
35
35
  # 11 not use
36
36
  # 12 tund fin
37
37
  # 13 tun fin
@@ -129,21 +129,19 @@ module Girl
129
129
  end
130
130
 
131
131
  src_chunk_dir = File.join( proxy_tmp_dir, 'src.chunk' )
132
- dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
133
- tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
134
-
135
- unless Dir.exist?( proxy_tmp_dir )
136
- Dir.mkdir( proxy_tmp_dir )
137
- end
138
132
 
139
133
  unless Dir.exist?( src_chunk_dir )
140
134
  Dir.mkdir( src_chunk_dir )
141
135
  end
142
136
 
137
+ dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
138
+
143
139
  unless Dir.exist?( dst_chunk_dir )
144
140
  Dir.mkdir( dst_chunk_dir )
145
141
  end
146
142
 
143
+ tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
144
+
147
145
  unless Dir.exist?( tun_chunk_dir )
148
146
  Dir.mkdir( tun_chunk_dir )
149
147
  end
@@ -18,7 +18,6 @@ module Girl
18
18
  @writes = []
19
19
  @roles = {} # sock => :dotr / :proxy / :src / :dst / :tun
20
20
  @src_infos = {} # src => {}
21
- @dsts = {} # local_port => dst
22
21
  @dst_infos = {} # dst => {}
23
22
  @resolv_caches = {} # domain => [ ip, created_at ]
24
23
 
@@ -192,15 +191,31 @@ module Girl
192
191
  end
193
192
 
194
193
  ##
195
- # resolve domain
194
+ # loop send a new source
196
195
  #
197
- def resolve_domain( src, domain )
198
- if ( /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\Z/ =~ domain ) && domain.split( '.' ).all? { | part | part.to_i < 256 }
199
- # puts "debug1 #{ domain } is a ip"
200
- deal_with_destination_ip( src, domain )
201
- return
196
+ def loop_send_a_new_source( src_ext, data )
197
+ Thread.new do
198
+ EXPIRE_NEW.times do
199
+ if src_ext[ :src ].closed? || src_ext[ :dst_port ]
200
+ # puts "debug1 break loop send a new source #{ src_ext[ :dst_port ] }"
201
+ break
202
+ end
203
+
204
+ @mutex.synchronize do
205
+ # puts "debug1 send a new source #{ data.inspect }"
206
+ add_tun_ctlmsg( data )
207
+ next_tick
208
+ end
209
+
210
+ sleep 1
211
+ end
202
212
  end
213
+ end
203
214
 
215
+ ##
216
+ # resolve domain
217
+ #
218
+ def resolve_domain( src, domain )
204
219
  if @remotes.any? { | remote | ( domain.size >= remote.size ) && ( domain[ ( remote.size * -1 )..-1 ] == remote ) }
205
220
  # puts "debug1 #{ domain } hit remotes"
206
221
  new_a_src_ext( src )
@@ -210,11 +225,11 @@ module Girl
210
225
  resolv_cache = @resolv_caches[ domain ]
211
226
 
212
227
  if resolv_cache
213
- destination_ip, created_at = resolv_cache
228
+ ip_info, created_at = resolv_cache
214
229
 
215
230
  if Time.new - created_at < RESOLV_CACHE_EXPIRE
216
- # puts "debug1 #{ domain } hit resolv cache #{ destination_ip }"
217
- deal_with_destination_ip( src, destination_ip )
231
+ # puts "debug1 #{ domain } hit resolv cache #{ ip_info.inspect }"
232
+ deal_with_destination_ip( src, ip_info )
218
233
  return
219
234
  end
220
235
 
@@ -234,12 +249,11 @@ module Girl
234
249
 
235
250
  @mutex.synchronize do
236
251
  if ip_info
237
- destination_ip = ip_info.ip_address
238
- # puts "debug1 resolved #{ domain } #{ destination_ip }"
239
- @resolv_caches[ domain ] = [ destination_ip, Time.new ]
252
+ @resolv_caches[ domain ] = [ ip_info, Time.new ]
240
253
 
241
254
  unless src.closed?
242
- deal_with_destination_ip( src, destination_ip )
255
+ puts "p#{ Process.pid } #{ Time.new } resolved #{ domain } #{ ip_info.ip_address }"
256
+ deal_with_destination_ip( src, ip_info )
243
257
  end
244
258
  else
245
259
  set_is_closing( src )
@@ -253,11 +267,11 @@ module Girl
253
267
  ##
254
268
  # deal with destination ip
255
269
  #
256
- def deal_with_destination_ip( src, destination_ip )
257
- if @directs.any? { | direct | direct.include?( destination_ip ) }
270
+ def deal_with_destination_ip( src, ip_info )
271
+ if @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
258
272
  # ip命中直连列表,直连
259
- # puts "debug1 #{ destination_ip } hit directs"
260
- new_a_dst( src, destination_ip )
273
+ # puts "debug1 #{ ip_info.inspect } hit directs"
274
+ new_a_dst( src, ip_info )
261
275
  else
262
276
  # 走远端
263
277
  new_a_src_ext( src )
@@ -321,10 +335,10 @@ module Girl
321
335
  ##
322
336
  # new a dst
323
337
  #
324
- def new_a_dst( src, destination_ip )
338
+ def new_a_dst( src, ip_info )
325
339
  src_info = @src_infos[ src ]
326
- destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], destination_ip )
327
- dst = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
340
+ destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
341
+ dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
328
342
 
329
343
  if RUBY_PLATFORM.include?( 'linux' )
330
344
  dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
@@ -342,7 +356,6 @@ module Girl
342
356
 
343
357
  # puts "debug1 a new dst #{ dst.local_address.inspect }"
344
358
  local_port = dst.local_address.ip_port
345
- @dsts[ local_port ] = dst
346
359
  @dst_infos[ dst ] = {
347
360
  local_port: local_port, # 本地端口
348
361
  src: src, # 对应src
@@ -361,11 +374,9 @@ module Girl
361
374
 
362
375
  if src_info[ :proxy_proto ] == :http
363
376
  if src_info[ :is_connect ]
364
- # CONNECT
365
377
  # puts "debug1 add src wbuff http ok"
366
378
  add_src_wbuff( src, HTTP_OK )
367
379
  else
368
- # not CONNECT
369
380
  # puts "debug1 add src rbuffs to dst wbuff"
370
381
 
371
382
  src_info[ :rbuffs ].each do | _, data |
@@ -408,7 +419,7 @@ module Girl
408
419
  destination_domain = src_info[ :destination_domain ]
409
420
  destination_domain_port = [ destination_domain, destination_port ].join( ':' )
410
421
  data = [ [ 0, A_NEW_SOURCE, src_id ].pack( 'Q>CQ>' ), @custom.encode( destination_domain_port ) ].join
411
- add_tun_ctlmsg( data )
422
+ loop_send_a_new_source( src_ext, data )
412
423
  end
413
424
 
414
425
  ##
@@ -644,7 +655,6 @@ module Girl
644
655
  end
645
656
  end
646
657
 
647
- @dsts.delete( dst_info[ :local_port ] )
648
658
  set_is_closing( dst_info[ :src ] )
649
659
  end
650
660
 
@@ -830,6 +840,10 @@ module Girl
830
840
  tun.sendmsg( data, 0, to_addr )
831
841
  rescue IO::WaitWritable, Errno::EINTR
832
842
  return
843
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
844
+ puts "#{ Time.new } #{ e.class }, close tun"
845
+ close_tun( tun )
846
+ return
833
847
  end
834
848
 
835
849
  @tun_info[ :ctlmsgs ].shift
@@ -848,6 +862,10 @@ module Girl
848
862
  tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
849
863
  rescue IO::WaitWritable, Errno::EINTR
850
864
  return
865
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
866
+ puts "#{ Time.new } #{ e.class }, close tun"
867
+ close_tun( tun )
868
+ return
851
869
  end
852
870
  end
853
871
  end
@@ -916,6 +934,10 @@ module Girl
916
934
  tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
917
935
  rescue IO::WaitWritable, Errno::EINTR
918
936
  return
937
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
938
+ puts "#{ Time.new } #{ e.class }, close tun"
939
+ close_tun( tun )
940
+ return
919
941
  end
920
942
 
921
943
  # puts "debug2 written pack #{ pack_id }"
@@ -1093,7 +1115,7 @@ module Girl
1093
1115
  src_info[ :destination_domain ] = destination_ip
1094
1116
  src_info[ :destination_port ] = destination_port
1095
1117
  # puts "debug1 IP V4 address #{ destination_addrinfo.inspect }"
1096
- deal_with_destination_ip( src, destination_ip )
1118
+ deal_with_destination_ip( src, destination_addrinfo )
1097
1119
  elsif atyp == 3
1098
1120
  domain_len = data[ 4 ].unpack( 'C' ).first
1099
1121
 
@@ -1242,11 +1264,9 @@ module Girl
1242
1264
 
1243
1265
  if src_info[ :proxy_proto ] == :http
1244
1266
  if src_info[ :is_connect ]
1245
- # CONNECT
1246
1267
  # puts "debug1 add src wbuff http ok"
1247
1268
  add_src_wbuff( src, HTTP_OK )
1248
1269
  else
1249
- # not CONNECT
1250
1270
  # puts "debug1 add src rbuffs to tun wbuffs"
1251
1271
 
1252
1272
  src_info[ :rbuffs ].each do | pack_id, _data |
@@ -1336,7 +1356,6 @@ module Girl
1336
1356
  src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1337
1357
  release_wmems( src_ext, continue_src_pack_id )
1338
1358
 
1339
- # 接到对面已关闭,若最后一个包已经进写前,关闭src
1340
1359
  if ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
1341
1360
  # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
1342
1361
  set_is_closing( src_ext[ :src ] )
@@ -37,16 +37,13 @@ module Girl
37
37
  end
38
38
 
39
39
  dst_chunk_dir = File.join( proxyd_tmp_dir, 'dst.chunk' )
40
- tund_chunk_dir = File.join( proxyd_tmp_dir, 'tund.chunk' )
41
-
42
- unless Dir.exist?( proxyd_tmp_dir )
43
- Dir.mkdir( proxyd_tmp_dir )
44
- end
45
40
 
46
41
  unless Dir.exist?( dst_chunk_dir )
47
42
  Dir.mkdir( dst_chunk_dir )
48
43
  end
49
44
 
45
+ tund_chunk_dir = File.join( proxyd_tmp_dir, 'tund.chunk' )
46
+
50
47
  unless Dir.exist?( tund_chunk_dir )
51
48
  Dir.mkdir( tund_chunk_dir )
52
49
  end
@@ -204,13 +204,17 @@ module Girl
204
204
  end
205
205
 
206
206
  Thread.new do
207
- destination_domain, destination_port = destination_domain_port.split( ':' )
208
- destination_port = destination_port.to_i
207
+ colon_idx = destination_domain_port.rindex( ':' )
209
208
 
210
- begin
211
- destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
212
- rescue Exception => e
213
- puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ destination_domain_port } #{ e.class }"
209
+ if colon_idx
210
+ destination_domain = destination_domain_port[ 0...colon_idx ]
211
+ destination_port = destination_domain_port[ ( colon_idx + 1 )..-1 ].to_i
212
+
213
+ begin
214
+ destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
215
+ rescue Exception => e
216
+ puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ destination_domain_port } #{ e.class }"
217
+ end
214
218
  end
215
219
 
216
220
  @mutex.synchronize do
@@ -232,7 +236,7 @@ module Girl
232
236
  # deal with destination addr
233
237
  #
234
238
  def deal_with_destination_addr( tund, src_id, destination_addr )
235
- dst = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
239
+ dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
236
240
  dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
237
241
 
238
242
  begin
@@ -814,7 +818,6 @@ module Girl
814
818
  when A_NEW_SOURCE
815
819
  src_id = data[ 9, 8 ].unpack( 'Q>' ).first
816
820
  dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
817
- # puts "debug1 got a new source #{ src_id }"
818
821
 
819
822
  if dst_local_port
820
823
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
@@ -831,8 +834,8 @@ module Girl
831
834
  end
832
835
 
833
836
  data = data[ 17..-1 ]
834
- # puts "debug1 #{ data }"
835
837
  destination_domain_port = @custom.decode( data )
838
+ puts "p#{ Process.pid } #{ Time.new } a new source #{ src_id } #{ destination_domain_port }"
836
839
  resolve_domain( tund, src_id, destination_domain_port )
837
840
  when SOURCE_STATUS
838
841
  src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
@@ -908,7 +911,6 @@ module Girl
908
911
  dst_ext[ :biggest_src_pack_id ] = biggest_src_pack_id
909
912
  release_wmems( dst_ext, continue_dst_pack_id )
910
913
 
911
- # 接到对面已关闭,若最后一个包已经进写前,关闭dst
912
914
  if biggest_src_pack_id == dst_ext[ :continue_src_pack_id ]
913
915
  # puts "debug1 4-1. tund recv fin1 -> all traffic received ? -> close dst after write"
914
916
  set_is_closing( dst_ext[ :dst ] )
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '0.70.0'.freeze
2
+ VERSION = '0.73.0'.freeze
3
3
  end
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.70.0
4
+ version: 0.73.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-06-30 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: while internet is evil, here's a girl.
14
14
  email: