girl 9.1.1 → 9.1.3
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.
- checksums.yaml +4 -4
- data/lib/girl/dns.rb +52 -55
- data/lib/girl/head.rb +2 -2
- data/lib/girl/proxy.rb +73 -74
- data/lib/girl/proxy_worker.rb +975 -985
- data/lib/girl/proxyd.rb +55 -58
- data/lib/girl/proxyd_worker.rb +633 -636
- data/lib/girl/version.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e943b1f4614987358b21807e76e1bd6d063f8ea4b411b0f342c1932341184560
|
|
4
|
+
data.tar.gz: 275796e8b852508ed1fa4589d5c5d6ca4a0d8e85cb0d8adb9170454232fceab9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35e5be4453ddc3d678763e2f7f7b29ae9be72cbb674d50471e751e818c48a2358511f5e7d2ce85829ad2c3b0c1057833b427369f29b1cd59efe5dcb7573c6c1d
|
|
7
|
+
data.tar.gz: e335d7263dbca8c59e27aa90adc0503f5beccc2a541939ffc65cfa2d653edb937b4a32a431cf33f2df573cb34c4bc616dddfd8af8cd716178843f3c978342e30
|
data/lib/girl/dns.rb
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
module Girl
|
|
2
2
|
module Dns
|
|
3
3
|
|
|
4
|
-
def pack_a_query(
|
|
4
|
+
def pack_a_query(domain, type = 1)
|
|
5
5
|
# https://www.ietf.org/rfc/rfc1035.txt
|
|
6
6
|
# https://www.ietf.org/rfc/rfc3596.txt
|
|
7
7
|
raise "domain may not exceed 255 chars" if domain.bytesize > 255
|
|
8
8
|
raise "invalid domain" if domain =~ /[^\w\.\-]/
|
|
9
|
-
data = [
|
|
10
|
-
data << [
|
|
9
|
+
data = [rand(65_535), 1, 0, 1, 0, 0, 0].pack('nCCnnnn')
|
|
10
|
+
data << [pack_domain(domain), type, 1].pack('a*nn')
|
|
11
11
|
data
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def pack_domain(
|
|
14
|
+
def pack_domain(domain)
|
|
15
15
|
data = ''
|
|
16
16
|
|
|
17
|
-
domain.split(
|
|
17
|
+
domain.split('.').each do |label|
|
|
18
18
|
raise "label may not exceed 63 chars" if label.bytesize > 63
|
|
19
|
-
data << [
|
|
19
|
+
data << [label.bytesize, label].pack('Ca*')
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
data << [
|
|
22
|
+
data << [0].pack('C')
|
|
23
23
|
data
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def seek_dn(
|
|
26
|
+
def seek_dn(data, offset)
|
|
27
27
|
name = ""
|
|
28
28
|
datalen = data.bytesize
|
|
29
29
|
|
|
30
30
|
loop do
|
|
31
|
-
raise "offset is greater than datalen" if datalen < (
|
|
31
|
+
raise "offset is greater than datalen" if datalen < (offset + 1)
|
|
32
32
|
|
|
33
|
-
len = data.unpack(
|
|
33
|
+
len = data.unpack("@#{offset} C").first
|
|
34
34
|
|
|
35
35
|
if len == 0
|
|
36
36
|
offset += 1
|
|
37
37
|
break
|
|
38
|
-
elsif (
|
|
39
|
-
raise "data ended before offset expand" if datalen < (
|
|
38
|
+
elsif (len & 0xC0) == 0xC0
|
|
39
|
+
raise "data ended before offset expand" if datalen < (offset + 2)
|
|
40
40
|
|
|
41
|
-
ptr = data.unpack(
|
|
41
|
+
ptr = data.unpack("@#{offset} n").first
|
|
42
42
|
ptr &= 0x3FFF
|
|
43
|
-
name2 = seek_dn(
|
|
43
|
+
name2 = seek_dn(data, ptr).first
|
|
44
44
|
raise "data is malformed" if name2.nil?
|
|
45
45
|
|
|
46
46
|
name += name2
|
|
@@ -48,89 +48,86 @@ module Girl
|
|
|
48
48
|
break
|
|
49
49
|
else
|
|
50
50
|
offset += 1
|
|
51
|
-
raise "no expansion found" if datalen < (
|
|
51
|
+
raise "no expansion found" if datalen < (offset + len)
|
|
52
52
|
|
|
53
|
-
elem = data[
|
|
54
|
-
name += "#{
|
|
53
|
+
elem = data[offset..offset + len - 1]
|
|
54
|
+
name += "#{elem}."
|
|
55
55
|
offset += len
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
[
|
|
59
|
+
[name, offset]
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def seek_ip(
|
|
62
|
+
def seek_ip(data)
|
|
63
63
|
ip = nil
|
|
64
|
-
answer_count = data.unpack(
|
|
65
|
-
# puts "debug answer count #{
|
|
66
|
-
offset = seek_question(
|
|
67
|
-
# puts "debug offset #{
|
|
64
|
+
answer_count = data.unpack("@6 n").first
|
|
65
|
+
# puts "debug answer count #{answer_count}"
|
|
66
|
+
offset = seek_question(data)
|
|
67
|
+
# puts "debug offset #{offset}"
|
|
68
68
|
|
|
69
69
|
answer_count.times do
|
|
70
|
-
ip, offset = seek_rr_ip(
|
|
71
|
-
|
|
72
|
-
if ip then
|
|
73
|
-
break
|
|
74
|
-
end
|
|
70
|
+
ip, offset = seek_rr_ip(data, offset)
|
|
71
|
+
break if ip
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
ip
|
|
78
75
|
end
|
|
79
76
|
|
|
80
|
-
def seek_question(
|
|
77
|
+
def seek_question(data)
|
|
81
78
|
offset = 12
|
|
82
79
|
|
|
83
80
|
loop do
|
|
84
|
-
len = data.unpack(
|
|
85
|
-
# puts "debug len #{
|
|
81
|
+
len = data.unpack("@#{offset} C").first
|
|
82
|
+
# puts "debug len #{len} #{data[offset + 1, len]}"
|
|
86
83
|
break if len == 0
|
|
87
|
-
offset += (
|
|
84
|
+
offset += (1 + len)
|
|
88
85
|
end
|
|
89
86
|
|
|
90
87
|
offset += 5
|
|
91
88
|
offset
|
|
92
89
|
end
|
|
93
90
|
|
|
94
|
-
def seek_question_dn(
|
|
95
|
-
id = data[
|
|
91
|
+
def seek_question_dn(data)
|
|
92
|
+
id = data[0, 2]
|
|
96
93
|
parts = []
|
|
97
94
|
offset = 12
|
|
98
95
|
|
|
99
96
|
loop do
|
|
100
|
-
len = data.unpack(
|
|
101
|
-
# puts "debug len #{
|
|
97
|
+
len = data.unpack("@#{offset} C").first
|
|
98
|
+
# puts "debug len #{len} #{data[offset + 1, len]}"
|
|
102
99
|
break if len == 0
|
|
103
|
-
parts << data[
|
|
104
|
-
offset += (
|
|
100
|
+
parts << data[offset + 1, len]
|
|
101
|
+
offset += (1 + len)
|
|
105
102
|
end
|
|
106
103
|
|
|
107
|
-
type = data.unpack(
|
|
108
|
-
# puts "debug id #{
|
|
109
|
-
[
|
|
104
|
+
type = data.unpack("@#{offset + 1} n").first
|
|
105
|
+
# puts "debug id #{id.inspect} dn #{parts.join('.').inspect} type #{type}"
|
|
106
|
+
[id, parts.join('.'), type]
|
|
110
107
|
end
|
|
111
108
|
|
|
112
|
-
def seek_rr_ip(
|
|
109
|
+
def seek_rr_ip(data, offset)
|
|
113
110
|
ip = nil
|
|
114
|
-
name, offset = seek_dn(
|
|
115
|
-
# puts "debug seek_dn #{
|
|
116
|
-
type = data.unpack(
|
|
117
|
-
# puts "debug type #{
|
|
111
|
+
name, offset = seek_dn(data, offset)
|
|
112
|
+
# puts "debug seek_dn #{name}, #{offset}"
|
|
113
|
+
type = data.unpack("@#{offset} n").first
|
|
114
|
+
# puts "debug type #{type}"
|
|
118
115
|
offset += 8
|
|
119
|
-
rdlen = data.unpack(
|
|
120
|
-
# puts "debug rdlen #{
|
|
116
|
+
rdlen = data.unpack("@#{offset} n").first
|
|
117
|
+
# puts "debug rdlen #{rdlen}"
|
|
121
118
|
offset += 2
|
|
122
119
|
|
|
123
|
-
if type == 1
|
|
120
|
+
if type == 1
|
|
124
121
|
raise "rdlen not 4?" if rdlen != 4
|
|
125
|
-
a, b, c, d = data.unpack(
|
|
126
|
-
ip = "#{
|
|
127
|
-
elsif type == 28
|
|
128
|
-
tokens = data.unpack("@#{
|
|
129
|
-
ip = format(
|
|
122
|
+
a, b, c, d = data.unpack("@#{offset} CCCC")
|
|
123
|
+
ip = "#{a}.#{b}.#{c}.#{d}"
|
|
124
|
+
elsif type == 28
|
|
125
|
+
tokens = data.unpack("@#{offset} n8")
|
|
126
|
+
ip = format("%x:%x:%x:%x:%x:%x:%x:%x", *tokens)
|
|
130
127
|
end
|
|
131
128
|
|
|
132
129
|
offset += rdlen
|
|
133
|
-
[
|
|
130
|
+
[ip, offset]
|
|
134
131
|
end
|
|
135
132
|
|
|
136
133
|
end
|
data/lib/girl/head.rb
CHANGED
|
@@ -2,8 +2,8 @@ module Girl
|
|
|
2
2
|
BACKLOG = 512 # 听队列大小,满后掉SYN包
|
|
3
3
|
RLIMIT = 1024 # sock数上限
|
|
4
4
|
READ_SIZE = 4 * 1024 * 1024 # 一次读多少
|
|
5
|
-
WBUFF_LIMIT =
|
|
6
|
-
RESUME_BELOW =
|
|
5
|
+
WBUFF_LIMIT = READ_SIZE * 2 # 写前上限,超过上限暂停读
|
|
6
|
+
RESUME_BELOW = READ_SIZE # 降到多少以下恢复读
|
|
7
7
|
CLOSE_ABOVE = WBUFF_LIMIT * 3 # 超过多少强制关闭
|
|
8
8
|
HEARTBEAT_INTERVAL = 10 # 心跳间隔
|
|
9
9
|
CHECK_TRAFF_INTERVAL = 3600 # 检查今天是否是流量计数重置日间隔
|
data/lib/girl/proxy.rb
CHANGED
|
@@ -14,76 +14,78 @@ require 'socket'
|
|
|
14
14
|
module Girl
|
|
15
15
|
class Proxy
|
|
16
16
|
|
|
17
|
-
def initialize(
|
|
18
|
-
unless config_path
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
tspd_port = conf[
|
|
30
|
-
proxyd_host = conf[
|
|
31
|
-
proxyd_port = conf[
|
|
32
|
-
nameserver = conf[
|
|
33
|
-
im = conf[
|
|
34
|
-
direct_path = conf[
|
|
35
|
-
remote_path = conf[
|
|
36
|
-
appd_host = conf[
|
|
37
|
-
appd_port = conf[
|
|
38
|
-
head_len = conf[
|
|
39
|
-
h_a_new_source = conf[
|
|
40
|
-
h_a_new_p2 = conf[
|
|
41
|
-
h_dst_close = conf[
|
|
42
|
-
h_heartbeat = conf[
|
|
43
|
-
h_p1_close = conf[
|
|
44
|
-
h_p2_close = conf[
|
|
45
|
-
h_p2_traffic = conf[
|
|
46
|
-
h_p1_overflow = conf[
|
|
47
|
-
h_p1_underhalf = conf[
|
|
48
|
-
h_p2_overflow = conf[
|
|
49
|
-
h_p2_underhalf = conf[
|
|
50
|
-
h_query = conf[
|
|
51
|
-
h_response = conf[
|
|
52
|
-
h_src_close = conf[
|
|
53
|
-
h_traffic = conf[
|
|
54
|
-
h_src_overflow = conf[
|
|
55
|
-
h_src_underhalf = conf[
|
|
56
|
-
h_dst_overflow = conf[
|
|
57
|
-
h_dst_underhalf = conf[
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
17
|
+
def initialize(config_path = nil)
|
|
18
|
+
config_path = File.expand_path('../girl.conf.json', __FILE__) unless config_path
|
|
19
|
+
raise "missing config file #{config_path}" unless File.exist?(config_path)
|
|
20
|
+
|
|
21
|
+
conf = JSON.parse(IO.binread(config_path), symbolize_names: true)
|
|
22
|
+
puts "load #{config_path} #{conf.inspect}"
|
|
23
|
+
redir_host = conf[:redir_host]
|
|
24
|
+
redir_port = conf[:redir_port]
|
|
25
|
+
memd_port = conf[:memd_port]
|
|
26
|
+
relayd_host = conf[:relayd_host]
|
|
27
|
+
relayd_port = conf[:relayd_port]
|
|
28
|
+
tspd_host = conf[:tspd_host]
|
|
29
|
+
tspd_port = conf[:tspd_port]
|
|
30
|
+
proxyd_host = conf[:proxyd_host]
|
|
31
|
+
proxyd_port = conf[:proxyd_port]
|
|
32
|
+
nameserver = conf[:nameserver]
|
|
33
|
+
im = conf[:im]
|
|
34
|
+
direct_path = conf[:direct_path]
|
|
35
|
+
remote_path = conf[:remote_path]
|
|
36
|
+
appd_host = conf[:appd_host]
|
|
37
|
+
appd_port = conf[:appd_port]
|
|
38
|
+
head_len = conf[:head_len] # 头长度
|
|
39
|
+
h_a_new_source = conf[:h_a_new_source] # A
|
|
40
|
+
h_a_new_p2 = conf[:h_a_new_p2] # B
|
|
41
|
+
h_dst_close = conf[:h_dst_close] # D
|
|
42
|
+
h_heartbeat = conf[:h_heartbeat] # H
|
|
43
|
+
h_p1_close = conf[:h_p1_close] # I
|
|
44
|
+
h_p2_close = conf[:h_p2_close] # J
|
|
45
|
+
h_p2_traffic = conf[:h_p2_traffic] # K
|
|
46
|
+
h_p1_overflow = conf[:h_p1_overflow] # L
|
|
47
|
+
h_p1_underhalf = conf[:h_p1_underhalf] # M
|
|
48
|
+
h_p2_overflow = conf[:h_p2_overflow] # N
|
|
49
|
+
h_p2_underhalf = conf[:h_p2_underhalf] # O
|
|
50
|
+
h_query = conf[:h_query] # Q
|
|
51
|
+
h_response = conf[:h_response] # R
|
|
52
|
+
h_src_close = conf[:h_src_close] # S
|
|
53
|
+
h_traffic = conf[:h_traffic] # T
|
|
54
|
+
h_src_overflow = conf[:h_src_overflow] # U
|
|
55
|
+
h_src_underhalf = conf[:h_src_underhalf] # V
|
|
56
|
+
h_dst_overflow = conf[:h_dst_overflow] # W
|
|
57
|
+
h_dst_underhalf = conf[:h_dst_underhalf] # X
|
|
58
|
+
expire_connecting = conf[:expire_connecting] # 连接多久没有建成关闭(秒)
|
|
59
|
+
expire_long_after = conf[:expire_long_after] # 长连接多久没有新流量关闭(秒)
|
|
60
|
+
expire_proxy_after = conf[:expire_proxy_after] # proxy多久没有收到流量重建(秒)
|
|
61
|
+
expire_resolv_cache = conf[:expire_resolv_cache] # dns查询结果缓存多久(秒)
|
|
62
|
+
expire_short_after = conf[:expire_short_after] # 短连接创建多久后关闭(秒)
|
|
63
|
+
is_debug = conf[:is_debug]
|
|
64
|
+
|
|
65
|
+
redir_host = redir_host ? redir_host.to_s : '0.0.0.0'
|
|
66
66
|
redir_port = redir_port ? redir_port.to_i : 6666
|
|
67
67
|
memd_port = memd_port ? memd_port.to_i : redir_port + 1
|
|
68
|
+
relayd_host = relayd_host ? relayd_host.to_s : '0.0.0.0'
|
|
68
69
|
relayd_port = relayd_port ? relayd_port.to_i : redir_port + 2
|
|
70
|
+
tspd_host = tspd_host ? tspd_host.to_s : '0.0.0.0'
|
|
69
71
|
tspd_port = tspd_port ? tspd_port.to_i : 7777
|
|
70
72
|
raise "missing proxyd host" unless proxyd_host
|
|
71
73
|
proxyd_port = proxyd_port ? proxyd_port.to_i : 6060
|
|
72
74
|
nameserver = '114.114.114.114' unless nameserver
|
|
73
|
-
nameservers = nameserver.split(
|
|
75
|
+
nameservers = nameserver.split(' ')
|
|
74
76
|
im = 'office-pc' unless im
|
|
75
77
|
directs = []
|
|
76
78
|
|
|
77
|
-
if direct_path
|
|
78
|
-
raise "not found direct file #{
|
|
79
|
-
directs = (
|
|
79
|
+
if direct_path
|
|
80
|
+
raise "not found direct file #{direct_path}" unless File.exist?(direct_path)
|
|
81
|
+
directs = (RESERVED_ROUTE.split("\n") + IO.binread(direct_path).split("\n")).map{|line| IPAddr.new(line.strip)}
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
remotes = []
|
|
83
85
|
|
|
84
|
-
if remote_path
|
|
85
|
-
raise "not found remote file #{
|
|
86
|
-
remotes = IO.binread(
|
|
86
|
+
if remote_path
|
|
87
|
+
raise "not found remote file #{remote_path}" unless File.exist?(remote_path)
|
|
88
|
+
remotes = IO.binread(remote_path).split("\n").map{|line| line.strip}
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
appd_host = appd_host ? appd_host.to_s : '127.0.0.1'
|
|
@@ -115,35 +117,32 @@ module Girl
|
|
|
115
117
|
expire_short_after = expire_short_after ? expire_short_after.to_i : 5
|
|
116
118
|
is_client_fastopen = is_server_fastopen = false
|
|
117
119
|
|
|
118
|
-
if RUBY_PLATFORM.include?(
|
|
119
|
-
IO.popen(
|
|
120
|
+
if RUBY_PLATFORM.include?('linux')
|
|
121
|
+
IO.popen('sysctl -n net.ipv4.tcp_fastopen') do |io|
|
|
120
122
|
output = io.read
|
|
121
123
|
val = output.to_i % 4
|
|
122
|
-
|
|
123
|
-
if [
|
|
124
|
-
is_client_fastopen = true
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
if [ 2, 3 ].include?( val ) then
|
|
128
|
-
is_server_fastopen = true
|
|
129
|
-
end
|
|
124
|
+
is_client_fastopen = true if [1, 3].include?(val)
|
|
125
|
+
is_server_fastopen = true if [2, 3].include?(val)
|
|
130
126
|
end
|
|
131
127
|
end
|
|
132
128
|
|
|
133
|
-
puts "girl proxy #{
|
|
134
|
-
puts "#{
|
|
135
|
-
puts "#{
|
|
136
|
-
puts "#{
|
|
129
|
+
puts "girl proxy #{Girl::VERSION} #{im} #{redir_port} #{relayd_port} #{tspd_port}"
|
|
130
|
+
puts "#{proxyd_host} #{proxyd_port} #{appd_host} #{appd_port} #{nameservers.inspect} #{is_client_fastopen} #{is_server_fastopen}"
|
|
131
|
+
puts "#{direct_path} #{directs.size} directs"
|
|
132
|
+
puts "#{remote_path} #{remotes.size} remotes"
|
|
137
133
|
|
|
138
|
-
if %w[
|
|
139
|
-
Process.setrlimit(
|
|
140
|
-
puts "NOFILE #{
|
|
134
|
+
if %w[darwin linux].any?{|plat| RUBY_PLATFORM.include?(plat)}
|
|
135
|
+
Process.setrlimit(:NOFILE, RLIMIT)
|
|
136
|
+
puts "NOFILE #{Process.getrlimit(:NOFILE).inspect}"
|
|
141
137
|
end
|
|
142
138
|
|
|
143
139
|
worker = Girl::ProxyWorker.new(
|
|
140
|
+
redir_host,
|
|
144
141
|
redir_port,
|
|
145
142
|
memd_port,
|
|
143
|
+
relayd_host,
|
|
146
144
|
relayd_port,
|
|
145
|
+
tspd_host,
|
|
147
146
|
tspd_port,
|
|
148
147
|
proxyd_host,
|
|
149
148
|
proxyd_port,
|
|
@@ -182,7 +181,7 @@ module Girl
|
|
|
182
181
|
is_client_fastopen,
|
|
183
182
|
is_server_fastopen )
|
|
184
183
|
|
|
185
|
-
Signal.trap(
|
|
184
|
+
Signal.trap(:TERM) do
|
|
186
185
|
puts 'exit'
|
|
187
186
|
worker.quit!
|
|
188
187
|
end
|