girl 9.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ddce98f59f1102d50d58fd02775ed1305f3babb3a2b7998a4ed86f39438e2599
4
+ data.tar.gz: b51d851640addd0acb8d5367b9d6295a67036e720436c6d0bea9ed352222f9bc
5
+ SHA512:
6
+ metadata.gz: 469527cb74ea0a0aab7af6358dcd345852c8c9c25b9adbcb69f70acaa582592b696a2549d92e3970d55b0a607fe400f107c8445e075fffb6c22bc4d82837289a
7
+ data.tar.gz: 1ce78e2d003752fb847c11ec505960c82a241d4d0b8ebde1047e7ac788532bb35ad6d985cf76067e20c638a788736336a35a2381b146664d4c391a5e3441d39f
data/girl.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'girl/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'girl'
8
+ spec.version = Girl::VERSION
9
+ spec.authors = ['takafan']
10
+ spec.email = ['qqtakafan@gmail.com']
11
+
12
+ spec.summary = %q{妹子}
13
+ spec.description = %q{escape evil.}
14
+ spec.homepage = 'https://github.com/takafan/girl'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = %w[
18
+ girl.gemspec
19
+ lib/girl.rb
20
+ lib/girl/dns.rb
21
+ lib/girl/head.rb
22
+ lib/girl/proxy_worker.rb
23
+ lib/girl/proxy.rb
24
+ lib/girl/proxyd_worker.rb
25
+ lib/girl/proxyd.rb
26
+ lib/girl/version.rb
27
+ ]
28
+
29
+ spec.require_paths = ['lib']
30
+ end
data/lib/girl/dns.rb ADDED
@@ -0,0 +1,137 @@
1
+ module Girl
2
+ module Dns
3
+
4
+ def pack_a_query( domain, type = 1 )
5
+ # https://www.ietf.org/rfc/rfc1035.txt
6
+ # https://www.ietf.org/rfc/rfc3596.txt
7
+ raise "domain may not exceed 255 chars" if domain.bytesize > 255
8
+ raise "invalid domain" if domain =~ /[^\w\.\-]/
9
+ data = [ rand( 65_535 ), 1, 0, 1, 0, 0, 0 ].pack( 'nCCnnnn' )
10
+ data << [ pack_domain( domain ), type, 1 ].pack( 'a*nn' )
11
+ data
12
+ end
13
+
14
+ def pack_domain( domain )
15
+ data = ''
16
+
17
+ domain.split( '.' ).each do | label |
18
+ raise "label may not exceed 63 chars" if label.bytesize > 63
19
+ data << [ label.bytesize, label ].pack( 'Ca*' )
20
+ end
21
+
22
+ data << [ 0 ].pack( 'C' )
23
+ data
24
+ end
25
+
26
+ def seek_dn( data, offset )
27
+ name = ""
28
+ datalen = data.bytesize
29
+
30
+ loop do
31
+ raise "offset is greater than datalen" if datalen < ( offset + 1 )
32
+
33
+ len = data.unpack( "@#{ offset } C" ).first
34
+
35
+ if len == 0
36
+ offset += 1
37
+ break
38
+ elsif ( len & 0xC0 ) == 0xC0
39
+ raise "data ended before offset expand" if datalen < ( offset + 2 )
40
+
41
+ ptr = data.unpack( "@#{ offset } n" ).first
42
+ ptr &= 0x3FFF
43
+ name2 = seek_dn( data, ptr ).first
44
+ raise "data is malformed" if name2.nil?
45
+
46
+ name += name2
47
+ offset += 2
48
+ break
49
+ else
50
+ offset += 1
51
+ raise "no expansion found" if datalen < ( offset + len )
52
+
53
+ elem = data[ offset..offset + len - 1 ]
54
+ name += "#{ elem }."
55
+ offset += len
56
+ end
57
+ end
58
+
59
+ [ name, offset ]
60
+ end
61
+
62
+ def seek_ip( data )
63
+ ip = nil
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
+
69
+ answer_count.times do
70
+ ip, offset = seek_rr_ip( data, offset )
71
+
72
+ if ip then
73
+ break
74
+ end
75
+ end
76
+
77
+ ip
78
+ end
79
+
80
+ def seek_question( data )
81
+ offset = 12
82
+
83
+ loop do
84
+ len = data.unpack( "@#{ offset } C" ).first
85
+ # puts "debug len #{ len } #{ data[ offset + 1, len ] }"
86
+ break if len == 0
87
+ offset += ( 1 + len )
88
+ end
89
+
90
+ offset += 5
91
+ offset
92
+ end
93
+
94
+ def seek_question_dn( data )
95
+ id = data[ 0, 2 ]
96
+ parts = []
97
+ offset = 12
98
+
99
+ loop do
100
+ len = data.unpack( "@#{ offset } C" ).first
101
+ # puts "debug len #{ len } #{ data[ offset + 1, len ] }"
102
+ break if len == 0
103
+ parts << data[ offset + 1, len ]
104
+ offset += ( 1 + len )
105
+ end
106
+
107
+ type = data.unpack( "@#{ offset + 1 } n" ).first
108
+ # puts "debug id #{ id.inspect } dn #{ parts.join( '.' ).inspect } type #{ type }"
109
+ [ id, parts.join( '.' ), type ]
110
+ end
111
+
112
+ def seek_rr_ip( data, offset )
113
+ ip = nil
114
+ name, offset = seek_dn( data, offset )
115
+ # puts "debug seek_dn #{ name }, #{ offset }"
116
+ type = data.unpack( "@#{ offset } n" ).first
117
+ # puts "debug type #{ type }"
118
+ offset += 8
119
+ rdlen = data.unpack( "@#{ offset } n" ).first
120
+ # puts "debug rdlen #{ rdlen }"
121
+ offset += 2
122
+
123
+ if type == 1 then
124
+ raise "rdlen not 4?" if rdlen != 4
125
+ a, b, c, d = data.unpack( "@#{ offset } CCCC" )
126
+ ip = "#{ a }.#{ b }.#{ c }.#{ d }"
127
+ elsif type == 28 then
128
+ tokens = data.unpack("@#{ offset } n8")
129
+ ip = format( "%x:%x:%x:%x:%x:%x:%x:%x", *tokens )
130
+ end
131
+
132
+ offset += rdlen
133
+ [ ip, offset ]
134
+ end
135
+
136
+ end
137
+ end
data/lib/girl/head.rb ADDED
@@ -0,0 +1,20 @@
1
+ module Girl
2
+ BACKLOG = 512 # 听队列大小,满后掉SYN包
3
+ RLIMIT = 1024 # sock数上限
4
+ READ_SIZE = 4 * 1024 * 1024 # 一次读多少
5
+ WBUFF_LIMIT = 30 * 1024 * 1024 # 写前上限,超过上限暂停读
6
+ RESUME_BELOW = WBUFF_LIMIT / 2 # 降到多少以下恢复读
7
+ CLOSE_ABOVE = WBUFF_LIMIT * 3 # 超过多少强制关闭
8
+ HEARTBEAT_INTERVAL = 10 # 心跳间隔
9
+ CHECK_TRAFF_INTERVAL = 3600 # 检查今天是否是流量计数重置日间隔
10
+ HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
11
+ RESERVED_ROUTE = <<EOF
12
+ 0.0.0.0/8
13
+ 10.0.0.0/8
14
+ 127.0.0.0/8
15
+ 169.254.0.0/16
16
+ 172.16.0.0/12
17
+ 192.168.0.0/16
18
+ 255.255.255.255/32
19
+ EOF
20
+ end
data/lib/girl/proxy.rb ADDED
@@ -0,0 +1,191 @@
1
+ require 'fileutils'
2
+ require 'girl/dns'
3
+ require 'girl/head'
4
+ require 'girl/proxy_worker'
5
+ require 'girl/version'
6
+ require 'ipaddr'
7
+ require 'json'
8
+ require 'socket'
9
+
10
+ ##
11
+ # Girl::Proxy - 近端
12
+ #
13
+ #
14
+ module Girl
15
+ class Proxy
16
+
17
+ def initialize( config_path = nil )
18
+ unless config_path then
19
+ config_path = File.expand_path( '../girl.conf.json', __FILE__ )
20
+ end
21
+
22
+ raise "missing config file #{ config_path }" unless File.exist?( config_path )
23
+
24
+ conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
25
+ puts "load #{ config_path } #{ conf.inspect }"
26
+ redir_port = conf[ :redir_port ]
27
+ memd_port = conf[ :memd_port ]
28
+ tspd_port = conf[ :tspd_port ]
29
+ proxyd_host = conf[ :proxyd_host ]
30
+ proxyd_port = conf[ :proxyd_port ]
31
+ nameserver = conf[ :nameserver ]
32
+ im = conf[ :im ]
33
+ direct_path = conf[ :direct_path ]
34
+ remote_path = conf[ :remote_path ]
35
+ appd_host = conf[ :appd_host ]
36
+ appd_port = conf[ :appd_port ]
37
+ head_len = conf[ :head_len ] # 头长度
38
+ h_a_new_source = conf[ :h_a_new_source ] # A
39
+ h_a_new_p2 = conf[ :h_a_new_p2 ] # B
40
+ h_dst_close = conf[ :h_dst_close ] # D
41
+ h_heartbeat = conf[ :h_heartbeat ] # H
42
+ h_p1_close = conf[ :h_p1_close ] # I
43
+ h_p2_close = conf[ :h_p2_close ] # J
44
+ h_p2_traffic = conf[ :h_p2_traffic ] # K
45
+ h_p1_overflow = conf[ :h_p1_overflow ] # L
46
+ h_p1_underhalf = conf[ :h_p1_underhalf ] # M
47
+ h_p2_overflow = conf[ :h_p2_overflow ] # N
48
+ h_p2_underhalf = conf[ :h_p2_underhalf ] # O
49
+ h_query = conf[ :h_query ] # Q
50
+ h_response = conf[ :h_response ] # R
51
+ h_src_close = conf[ :h_src_close ] # S
52
+ h_traffic = conf[ :h_traffic ] # T
53
+ h_src_overflow = conf[ :h_src_overflow ] # U
54
+ h_src_underhalf = conf[ :h_src_underhalf ] # V
55
+ h_dst_overflow = conf[ :h_dst_overflow ] # W
56
+ h_dst_underhalf = conf[ :h_dst_underhalf ] # X
57
+
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_port = redir_port ? redir_port.to_i : 6666
66
+ memd_port = memd_port ? memd_port.to_i : redir_port + 1
67
+ tspd_port = tspd_port ? tspd_port.to_i : 7777
68
+ raise "missing proxyd host" unless proxyd_host
69
+ proxyd_port = proxyd_port ? proxyd_port.to_i : 6060
70
+ nameserver = '114.114.114.114' unless nameserver
71
+ nameservers = nameserver.split( ' ' )
72
+ im = 'office-pc' unless im
73
+ directs = []
74
+
75
+ if direct_path then
76
+ raise "not found direct file #{ direct_path }" unless File.exist?( direct_path )
77
+ directs = ( RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map{ | line | IPAddr.new( line.strip ) }
78
+ end
79
+
80
+ remotes = []
81
+
82
+ if remote_path then
83
+ raise "not found remote file #{ remote_path }" unless File.exist?( remote_path )
84
+ remotes = IO.binread( remote_path ).split( "\n" ).map{ | line | line.strip }
85
+ end
86
+
87
+ appd_host = appd_host ? appd_host.to_s : '127.0.0.1'
88
+ appd_port = appd_port ? appd_port.to_i : 22
89
+ head_len = head_len ? head_len.to_i : 59
90
+ h_a_new_source = h_a_new_source ? h_a_new_source.to_s : 'A'
91
+ h_a_new_p2 = h_a_new_p2 ? h_a_new_p2.to_s : 'B'
92
+ h_dst_close = h_dst_close ? h_dst_close.to_s : 'D'
93
+ h_heartbeat = h_heartbeat ? h_heartbeat.to_s : 'H'
94
+ h_p1_close = h_p1_close ? h_p1_close.to_s : 'I'
95
+ h_p2_close = h_p2_close ? h_p2_close.to_s : 'J'
96
+ h_p2_traffic = h_p2_traffic ? h_p2_traffic.to_s : 'K'
97
+ h_p1_overflow = h_p1_overflow ? h_p1_overflow.to_s : 'L'
98
+ h_p1_underhalf = h_p1_underhalf ? h_p1_underhalf.to_s : 'M'
99
+ h_p2_overflow = h_p2_overflow ? h_p2_overflow.to_s : 'N'
100
+ h_p2_underhalf = h_p2_underhalf ? h_p2_underhalf.to_s : 'O'
101
+ h_query = h_query ? h_query.to_s : 'Q'
102
+ h_response = h_response ? h_response.to_s : 'R'
103
+ h_src_close = h_src_close ? h_src_close.to_s : 'S'
104
+ h_traffic = h_traffic ? h_traffic.to_s : 'T'
105
+ h_src_overflow = h_src_overflow ? h_src_overflow.to_s : 'U'
106
+ h_src_underhalf = h_src_underhalf ? h_src_underhalf.to_s : 'V'
107
+ h_dst_overflow = h_dst_overflow ? h_dst_overflow.to_s : 'W'
108
+ h_dst_underhalf = h_dst_underhalf ? h_dst_underhalf.to_s : 'X'
109
+ expire_connecting = expire_connecting ? expire_connecting.to_i : 5
110
+ expire_long_after = expire_long_after ? expire_long_after.to_i : 3600
111
+ expire_proxy_after = expire_proxy_after ? expire_proxy_after.to_i : 60
112
+ expire_resolv_cache = expire_resolv_cache ? expire_resolv_cache.to_i : 600
113
+ expire_short_after = expire_short_after ? expire_short_after.to_i : 5
114
+ is_client_fastopen = is_server_fastopen = false
115
+
116
+ if RUBY_PLATFORM.include?( 'linux' ) then
117
+ IO.popen( 'sysctl -n net.ipv4.tcp_fastopen' ) do | io |
118
+ output = io.read
119
+ val = output.to_i % 4
120
+
121
+ if [ 1, 3 ].include?( val ) then
122
+ is_client_fastopen = true
123
+ end
124
+
125
+ if [ 2, 3 ].include?( val ) then
126
+ is_server_fastopen = true
127
+ end
128
+ end
129
+ end
130
+
131
+ puts "girl proxy #{ Girl::VERSION } #{ im }"
132
+ puts "#{ redir_port } #{ tspd_port } #{ proxyd_host } #{ proxyd_port } #{ appd_host } #{ appd_port } #{ nameservers.inspect } #{ is_client_fastopen } #{ is_server_fastopen }"
133
+ puts "#{ direct_path } #{ directs.size } directs"
134
+ puts "#{ remote_path } #{ remotes.size } remotes"
135
+
136
+ if %w[ darwin linux ].any?{ | plat | RUBY_PLATFORM.include?( plat ) } then
137
+ Process.setrlimit( :NOFILE, RLIMIT )
138
+ puts "NOFILE #{ Process.getrlimit( :NOFILE ).inspect }"
139
+ end
140
+
141
+ worker = Girl::ProxyWorker.new(
142
+ redir_port,
143
+ memd_port,
144
+ tspd_port,
145
+ proxyd_host,
146
+ proxyd_port,
147
+ nameservers,
148
+ im,
149
+ directs,
150
+ remotes,
151
+ appd_host,
152
+ appd_port,
153
+ head_len,
154
+ h_a_new_source,
155
+ h_a_new_p2,
156
+ h_dst_close,
157
+ h_heartbeat,
158
+ h_p1_close,
159
+ h_p2_close,
160
+ h_p2_traffic,
161
+ h_p1_overflow,
162
+ h_p1_underhalf,
163
+ h_p2_overflow,
164
+ h_p2_underhalf,
165
+ h_query,
166
+ h_response,
167
+ h_src_close,
168
+ h_traffic,
169
+ h_src_overflow,
170
+ h_src_underhalf,
171
+ h_dst_overflow,
172
+ h_dst_underhalf,
173
+ expire_connecting,
174
+ expire_long_after,
175
+ expire_proxy_after,
176
+ expire_resolv_cache,
177
+ expire_short_after,
178
+ is_debug,
179
+ is_client_fastopen,
180
+ is_server_fastopen )
181
+
182
+ Signal.trap( :TERM ) do
183
+ puts 'exit'
184
+ worker.quit!
185
+ end
186
+
187
+ worker.looping
188
+ end
189
+
190
+ end
191
+ end