girl 9.1.2 → 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 +66 -75
- data/lib/girl/proxy_worker.rb +968 -978
- data/lib/girl/proxyd.rb +55 -58
- data/lib/girl/proxyd_worker.rb +626 -629
- 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,56 +14,53 @@ 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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
expire_resolv_cache = conf[ :expire_resolv_cache ] # dns查询结果缓存多久(秒)
|
|
65
|
-
expire_short_after = conf[ :expire_short_after ] # 短连接创建多久后关闭(秒)
|
|
66
|
-
is_debug = conf[ :is_debug ]
|
|
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]
|
|
67
64
|
|
|
68
65
|
redir_host = redir_host ? redir_host.to_s : '0.0.0.0'
|
|
69
66
|
redir_port = redir_port ? redir_port.to_i : 6666
|
|
@@ -75,20 +72,20 @@ module Girl
|
|
|
75
72
|
raise "missing proxyd host" unless proxyd_host
|
|
76
73
|
proxyd_port = proxyd_port ? proxyd_port.to_i : 6060
|
|
77
74
|
nameserver = '114.114.114.114' unless nameserver
|
|
78
|
-
nameservers = nameserver.split(
|
|
75
|
+
nameservers = nameserver.split(' ')
|
|
79
76
|
im = 'office-pc' unless im
|
|
80
77
|
directs = []
|
|
81
78
|
|
|
82
|
-
if direct_path
|
|
83
|
-
raise "not found direct file #{
|
|
84
|
-
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)}
|
|
85
82
|
end
|
|
86
83
|
|
|
87
84
|
remotes = []
|
|
88
85
|
|
|
89
|
-
if remote_path
|
|
90
|
-
raise "not found remote file #{
|
|
91
|
-
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}
|
|
92
89
|
end
|
|
93
90
|
|
|
94
91
|
appd_host = appd_host ? appd_host.to_s : '127.0.0.1'
|
|
@@ -120,29 +117,23 @@ module Girl
|
|
|
120
117
|
expire_short_after = expire_short_after ? expire_short_after.to_i : 5
|
|
121
118
|
is_client_fastopen = is_server_fastopen = false
|
|
122
119
|
|
|
123
|
-
if RUBY_PLATFORM.include?(
|
|
124
|
-
IO.popen(
|
|
120
|
+
if RUBY_PLATFORM.include?('linux')
|
|
121
|
+
IO.popen('sysctl -n net.ipv4.tcp_fastopen') do |io|
|
|
125
122
|
output = io.read
|
|
126
123
|
val = output.to_i % 4
|
|
127
|
-
|
|
128
|
-
if [
|
|
129
|
-
is_client_fastopen = true
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
if [ 2, 3 ].include?( val ) then
|
|
133
|
-
is_server_fastopen = true
|
|
134
|
-
end
|
|
124
|
+
is_client_fastopen = true if [1, 3].include?(val)
|
|
125
|
+
is_server_fastopen = true if [2, 3].include?(val)
|
|
135
126
|
end
|
|
136
127
|
end
|
|
137
128
|
|
|
138
|
-
puts "girl proxy #{
|
|
139
|
-
puts "#{
|
|
140
|
-
puts "#{
|
|
141
|
-
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"
|
|
142
133
|
|
|
143
|
-
if %w[
|
|
144
|
-
Process.setrlimit(
|
|
145
|
-
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}"
|
|
146
137
|
end
|
|
147
138
|
|
|
148
139
|
worker = Girl::ProxyWorker.new(
|
|
@@ -190,7 +181,7 @@ module Girl
|
|
|
190
181
|
is_client_fastopen,
|
|
191
182
|
is_server_fastopen )
|
|
192
183
|
|
|
193
|
-
Signal.trap(
|
|
184
|
+
Signal.trap(:TERM) do
|
|
194
185
|
puts 'exit'
|
|
195
186
|
worker.quit!
|
|
196
187
|
end
|