proxifier2 1.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 +7 -0
- data/LICENSE +19 -0
- data/README.md +120 -0
- data/bin/pirb +8 -0
- data/bin/pruby +8 -0
- data/lib/proxifier/env.rb +113 -0
- data/lib/proxifier/proxies/http.rb +19 -0
- data/lib/proxifier/proxies/socks.rb +103 -0
- data/lib/proxifier/proxies/socks4.rb +44 -0
- data/lib/proxifier/proxies/socks4a.rb +9 -0
- data/lib/proxifier/proxy.rb +63 -0
- data/lib/proxifier/version.rb +3 -0
- data/lib/proxifier.rb +25 -0
- data/lib/uri/socks.rb +26 -0
- data/proxifier2.gemspec +16 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d830d99c1026cd8eca1768e28ce88fbd16c0619aa36c2625a8ff45370af332d6
|
4
|
+
data.tar.gz: e56d24c40e9523d0d5fd1e47429e77bdbde3b19a9bce40512e6902796a677fb7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b06d8785f76c63fc8fe1751e256accacecfb93db3613cb4e55020a85c0db6c285f938ec01063f34e82bba4dae67c3aa3c8781fa5701001d80fa11d83f53f85b6
|
7
|
+
data.tar.gz: 2733802592c8ad91ec36d357b5cf77b265098e82d29aeb22a65bcdb282c548c9a5eec82d412e215bae93cb1788a482ea22b8595b4c12658058b02a96a40e97ba
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2011 by Samuel Kadolph
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# ruby-proxifier
|
2
|
+
|
3
|
+
## Installing
|
4
|
+
|
5
|
+
### Recommended
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install proxifier
|
9
|
+
```
|
10
|
+
|
11
|
+
### Edge
|
12
|
+
|
13
|
+
```
|
14
|
+
git clone https://github.com/samuelkadolph/ruby-proxifier
|
15
|
+
cd ruby-proxifier && rake install
|
16
|
+
```
|
17
|
+
|
18
|
+
## Rationale
|
19
|
+
|
20
|
+
This gem was created for 2 purposes.
|
21
|
+
|
22
|
+
First is to enable ruby programmers to use HTTP or SOCKS proxies
|
23
|
+
interchangeably when using TCPSockets. Either manually with
|
24
|
+
`Proxifier::Proxy#open` or by `require "proxifier/env"`.
|
25
|
+
|
26
|
+
The second purpose is to use ruby code that doesn't use proxies for users that
|
27
|
+
have to use proxies.<br>The pruby and pirb executables are simple wrappers for
|
28
|
+
their respective ruby executables that support proxies from environment
|
29
|
+
variables.
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
### Executable Wrappers & Environment Variables
|
34
|
+
|
35
|
+
proxifier provides two executables: `pruby` and `pirb`. They are simple
|
36
|
+
wrappers for your current `ruby` and `irb` executables that requires the
|
37
|
+
`"proxifier/env"` script which installs hooks into `TCPSocket` which will use
|
38
|
+
the proxy environment variables to proxy any `TCPSocket`.
|
39
|
+
|
40
|
+
The environment variables that proxifier will check are (in order of descending
|
41
|
+
precedence):
|
42
|
+
|
43
|
+
<table>
|
44
|
+
<tr>
|
45
|
+
<th>Variable Name</th>
|
46
|
+
<th>Alternatives</th>
|
47
|
+
<th>Notes</th>
|
48
|
+
</tr>
|
49
|
+
<tr>
|
50
|
+
<td>proxy</td>
|
51
|
+
<td>PROXY</td>
|
52
|
+
<td>Requires the proxy scheme to be present.</td>
|
53
|
+
</tr>
|
54
|
+
<tr>
|
55
|
+
<td>socks_proxy</td>
|
56
|
+
<td>SOCKS_PROXY<br>socks5_proxy<br>SOCKS5_PROXY</td>
|
57
|
+
<td>Implies the SOCKS5 proxy scheme.</td>
|
58
|
+
</tr>
|
59
|
+
<tr>
|
60
|
+
<td>socks4a_proxy</td>
|
61
|
+
<td>SOCKS4A_PROXY</td>
|
62
|
+
<td>Implies the SOCKS4A proxy scheme.</td>
|
63
|
+
</tr>
|
64
|
+
<tr>
|
65
|
+
<td>socks4_proxy</td>
|
66
|
+
<td>PROXY</td>
|
67
|
+
<td>Implies the SOCKS4 proxy scheme.</td>
|
68
|
+
</tr>
|
69
|
+
<tr>
|
70
|
+
<td>http_proxy</td>
|
71
|
+
<td>HTTP_PROXY</td>
|
72
|
+
<td>Implies the HTTP proxy scheme.</td>
|
73
|
+
</tr>
|
74
|
+
</table>
|
75
|
+
|
76
|
+
### Ruby
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
require "proxifier/proxy"
|
80
|
+
|
81
|
+
proxy = Proxifier::Proxy("socks://localhost")
|
82
|
+
socket = proxy.open("www.google.com", 80)
|
83
|
+
socket << "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"
|
84
|
+
socket.gets # => "HTTP/1.1 200 OK\r\n"
|
85
|
+
```
|
86
|
+
|
87
|
+
## Supported Proxies
|
88
|
+
|
89
|
+
<table>
|
90
|
+
<tr>
|
91
|
+
<th>Protocol</th>
|
92
|
+
<th>Formats</th>
|
93
|
+
<th>Notes</th>
|
94
|
+
</tr>
|
95
|
+
<tr>
|
96
|
+
<td>HTTP</td>
|
97
|
+
<td><pre>http://[username[:password]@]host[:port][?tunnel=false]</pre></td>
|
98
|
+
<td>
|
99
|
+
The port defaults to 80. This is currently a limitation that may be solved in the future.<br>
|
100
|
+
Appending <code>?tunnel=false</code> forces the proxy to not use <code>CONNECT</code>.</td>
|
101
|
+
</tr>
|
102
|
+
<tr>
|
103
|
+
<td>SOCKS5</td>
|
104
|
+
<td><pre>socks://[username[:password]@]host[:port]
|
105
|
+
socks5://[username[:password]@]host[:port]</pre></td>
|
106
|
+
<td>
|
107
|
+
Port defaults to 1080.
|
108
|
+
</td>
|
109
|
+
</tr>
|
110
|
+
<tr>
|
111
|
+
<td>SOCKS4A</td>
|
112
|
+
<td><pre>socks4a://[username@]host[:port]</pre></td>
|
113
|
+
<td>Not yet implemented.</td>
|
114
|
+
</tr>
|
115
|
+
<tr>
|
116
|
+
<td>SOCKS4</td>
|
117
|
+
<td><pre>socks4://[username@]host[:port]</pre></td>
|
118
|
+
<td>Currently hangs. Not sure if the problem is with code or server.</td>
|
119
|
+
</tr>
|
120
|
+
</table>
|
data/bin/pirb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
executable = File.expand_path("../" + Gem.default_exec_format % "irb", Gem.ruby)
|
4
|
+
full_gem_path = Gem.loaded_specs["proxifier"].full_gem_path
|
5
|
+
load_paths = Gem.loaded_specs["proxifier"].require_paths.map { |p| "-I#{File.join(full_gem_path, p)}" }
|
6
|
+
# TODO: support argument switches
|
7
|
+
|
8
|
+
exec(executable, *load_paths, "-rproxifier/env", *ARGV)
|
data/bin/pruby
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
executable = Gem.ruby
|
4
|
+
full_gem_path = Gem.loaded_specs["proxifier"].full_gem_path
|
5
|
+
load_paths = Gem.loaded_specs["proxifier"].require_paths.map { |p| "-I#{File.join(full_gem_path, p)}" }
|
6
|
+
# TODO: support argument switches
|
7
|
+
|
8
|
+
exec(executable, *load_paths, "-rproxifier/env", *ARGV)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "socket"
|
2
|
+
require "proxifier"
|
3
|
+
|
4
|
+
module Proxifier
|
5
|
+
class Proxy
|
6
|
+
def open(host, port, local_host = nil, local_port = nil)
|
7
|
+
return TCPSocket.new(host, port, local_host, local_port, :proxy => nil) unless proxify?(host)
|
8
|
+
|
9
|
+
socket = TCPSocket.new(self.host, self.port, local_host, local_port, :proxy => nil)
|
10
|
+
|
11
|
+
begin
|
12
|
+
proxify(socket, host, port)
|
13
|
+
rescue
|
14
|
+
socket.close
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
|
18
|
+
socket
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Proxify
|
23
|
+
def self.included(klass)
|
24
|
+
klass.class_eval do
|
25
|
+
alias_method :initialize_without_proxy, :initialize
|
26
|
+
alias_method :initialize, :initialize_with_proxy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize_with_proxy(host, port, options_or_local_host = {}, local_port = nil, options_if_local_host = {})
|
31
|
+
if options_or_local_host.is_a?(Hash)
|
32
|
+
local_host = nil
|
33
|
+
options = options_or_local_host
|
34
|
+
else
|
35
|
+
local_host = options_or_local_host
|
36
|
+
options = options_if_local_host
|
37
|
+
end
|
38
|
+
|
39
|
+
if options[:proxy] && (proxy = Proxifier::Proxy(options.delete(:proxy), options)) && proxy.proxify?(host)
|
40
|
+
initialize_without_proxy(proxy.host, proxy.port, local_host, local_port)
|
41
|
+
begin
|
42
|
+
proxy.proxify(self, host, port)
|
43
|
+
rescue
|
44
|
+
close
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
else
|
48
|
+
initialize_without_proxy(host, port, local_host, local_port)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module EnvironmentProxify
|
54
|
+
def self.included(klass)
|
55
|
+
klass.class_eval do
|
56
|
+
extend ClassMethods
|
57
|
+
alias_method :initialize_without_environment_proxy, :initialize
|
58
|
+
alias_method :initialize, :initialize_with_environment_proxy
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize_with_environment_proxy(host, port, options_or_local_host = {}, local_port = nil, options_if_local_host = {})
|
63
|
+
if options_or_local_host.is_a?(Hash)
|
64
|
+
local_host = nil
|
65
|
+
options = options_or_local_host
|
66
|
+
else
|
67
|
+
local_host = options_or_local_host
|
68
|
+
options = options_if_local_host
|
69
|
+
end
|
70
|
+
|
71
|
+
options = { :proxy => environment_proxy, :no_proxy => environment_no_proxy }.merge(options)
|
72
|
+
initialize_without_environment_proxy(host, port, local_host, local_port, options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def environment_proxy
|
76
|
+
self.class.environment_proxy
|
77
|
+
end
|
78
|
+
|
79
|
+
def environment_no_proxy
|
80
|
+
self.class.environment_no_proxy
|
81
|
+
end
|
82
|
+
|
83
|
+
module ClassMethods
|
84
|
+
def environment_proxy
|
85
|
+
ENV["proxy"] || ENV["PROXY"] || specific_environment_proxy
|
86
|
+
end
|
87
|
+
|
88
|
+
def environment_no_proxy
|
89
|
+
ENV["no_proxy"] || ENV["NO_PROXY"]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def specific_environment_proxy
|
94
|
+
%w(socks socks5 socks4a socks4 http).each do |type|
|
95
|
+
if proxy = ENV["#{type}_proxy"] || ENV["#{type.upcase}_PROXY"]
|
96
|
+
scheme = "#{type}://"
|
97
|
+
|
98
|
+
proxy = proxy.dup
|
99
|
+
proxy.insert(0, scheme) unless proxy.index(scheme) == 0
|
100
|
+
return proxy
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class TCPSocket
|
111
|
+
include Proxifier::Proxify
|
112
|
+
include Proxifier::EnvironmentProxify
|
113
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "proxifier/proxy"
|
3
|
+
|
4
|
+
module Proxifier
|
5
|
+
class HTTPProxy < Proxy
|
6
|
+
def do_proxify(socket, host, port)
|
7
|
+
return if query_options["tunnel"] == "false"
|
8
|
+
|
9
|
+
socket << "CONNECT #{host}:#{port} HTTP/1.1\r\n"
|
10
|
+
socket << "Host: #{host}:#{port}\r\n"
|
11
|
+
socket << "Proxy-Authorization: Basic #{["#{user}:#{password}"].pack("m").chomp}\r\n" if user
|
12
|
+
socket << "\r\n"
|
13
|
+
|
14
|
+
buffer = Net::BufferedIO.new(socket)
|
15
|
+
response = Net::HTTPResponse.read_new(buffer)
|
16
|
+
response.error! unless response.is_a?(Net::HTTPOK)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "ipaddr"
|
2
|
+
require "proxifier/proxy"
|
3
|
+
|
4
|
+
module Proxifier
|
5
|
+
class SOCKSProxy < Proxy
|
6
|
+
VERSION = 0x05
|
7
|
+
|
8
|
+
def do_proxify(socket, host, port)
|
9
|
+
authenticaton_method = greet(socket)
|
10
|
+
authenticate(socket, authenticaton_method)
|
11
|
+
connect(socket, host, port)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def greet(socket)
|
16
|
+
methods = authentication_methods
|
17
|
+
|
18
|
+
socket << [VERSION, methods.size, *methods].pack("CCC#{methods.size}")
|
19
|
+
version, authentication_method = socket.read(2).unpack("CC")
|
20
|
+
check_version(version)
|
21
|
+
|
22
|
+
authentication_method
|
23
|
+
end
|
24
|
+
|
25
|
+
def authenticate(socket, method)
|
26
|
+
case method
|
27
|
+
when 0x00 # NO AUTHENTICATION REQUIRED
|
28
|
+
when 0x02 # USERNAME/PASSWORD
|
29
|
+
user &&= user[0, 0xFF]
|
30
|
+
password &&= password[0, 0xFF]
|
31
|
+
|
32
|
+
socket << [user.size, user, password.size, password].pack("CA#{user.size}CA#{password.size}")
|
33
|
+
version, status = socket.read(2).unpack("CC")
|
34
|
+
check_version(version)
|
35
|
+
|
36
|
+
case status
|
37
|
+
when 0x00 # SUCCESS
|
38
|
+
else
|
39
|
+
raise "SOCKS5 username/password authentication failed"
|
40
|
+
end
|
41
|
+
else
|
42
|
+
raise "no acceptable SOCKS5 authentication methods"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def connect(socket, host, port)
|
47
|
+
host = host[0, 0xFF]
|
48
|
+
socket << [VERSION, 0x01, 0x00, 0x03, host.size, host, port].pack("CCCCCA#{host.size}n")
|
49
|
+
version, status, _, type = socket.read(4).unpack("CCCC")
|
50
|
+
check_version(version)
|
51
|
+
|
52
|
+
case status
|
53
|
+
when 0x00 # succeeded
|
54
|
+
when 0x01 # general SOCKS server failure
|
55
|
+
raise "general SOCKS server failure"
|
56
|
+
when 0x02 # connection not allowed by ruleset
|
57
|
+
raise "connection not allowed by ruleset"
|
58
|
+
when 0x03 # Network unreachable
|
59
|
+
raise "network unreachable"
|
60
|
+
when 0x04 # Host unreachable
|
61
|
+
raise "host unreachable"
|
62
|
+
when 0x05 # Connection refused
|
63
|
+
raise "connection refused"
|
64
|
+
when 0x06 # TTL expired
|
65
|
+
raise "TTL expired"
|
66
|
+
when 0x07 # Command not supported
|
67
|
+
raise "command not supported"
|
68
|
+
when 0x08 # Address type not supported
|
69
|
+
raise "address type not supported"
|
70
|
+
else # unassigned
|
71
|
+
raise "unknown SOCKS error"
|
72
|
+
end
|
73
|
+
|
74
|
+
case type
|
75
|
+
when 0x01 # IP V4 address
|
76
|
+
destination = IPAddr.ntop(socket.read(4))
|
77
|
+
when 0x03 # DOMAINNAME
|
78
|
+
length = socket.read(1).unpack("C").first
|
79
|
+
destination = socket.read(length).unpack("A#{length}")
|
80
|
+
when 0x04 # IP V6 address
|
81
|
+
destination = IPAddr.ntop(socket.read(16))
|
82
|
+
else
|
83
|
+
raise "unsupported SOCKS5 address type"
|
84
|
+
end
|
85
|
+
|
86
|
+
port = socket.read(2).unpack("n").first
|
87
|
+
end
|
88
|
+
|
89
|
+
def check_version(version, should_be = VERSION)
|
90
|
+
raise "mismatched SOCKS version" unless version == should_be
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
def authentication_methods
|
95
|
+
methods = []
|
96
|
+
methods << 0x00 # NO AUTHENTICATION REQUIRED
|
97
|
+
methods << 0x02 if user # USERNAME/PASSWORD
|
98
|
+
methods
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
SOCKS5Proxy = SOCKSProxy
|
103
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "proxifier/proxies/socks"
|
2
|
+
|
3
|
+
module Proxifier
|
4
|
+
class SOCKS4Proxy < SOCKSProxy
|
5
|
+
VERSION = 0x04
|
6
|
+
|
7
|
+
protected
|
8
|
+
def greet(socket)
|
9
|
+
# noop
|
10
|
+
end
|
11
|
+
|
12
|
+
def authenticate(socket, method)
|
13
|
+
# noop
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect(socket, host, port)
|
17
|
+
begin
|
18
|
+
ip = IPAddr.new(host)
|
19
|
+
rescue ArgumentError
|
20
|
+
ip = IPAddr.new(Socket.getaddrinfo(host, nil, :INET, :STREAM).first)
|
21
|
+
end
|
22
|
+
|
23
|
+
socket << [VERSION, 0x01, port].pack("CCn") << ip.hton
|
24
|
+
socket << user if user
|
25
|
+
socket << 0x00
|
26
|
+
|
27
|
+
version, status, port = socket.read(4).unpack("CCn")
|
28
|
+
check_version(version, 0x00)
|
29
|
+
ip = IPAddr.ntop(socket.read(4))
|
30
|
+
|
31
|
+
case status
|
32
|
+
when 0x5A # request granted
|
33
|
+
when 0x5B # request rejected or failed
|
34
|
+
raise "request rejected or failed"
|
35
|
+
when 0x5C # request rejected becasue SOCKS server cannot connect to identd on the client
|
36
|
+
raise "request rejected becasue SOCKS server cannot connect to identd on the client"
|
37
|
+
when 0x5D # request rejected because the client program and identd report different user-ids
|
38
|
+
raise "request rejected because the client program and identd report different user-ids"
|
39
|
+
else
|
40
|
+
raise "unknown SOCKS error"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "socket"
|
2
|
+
require "uri"
|
3
|
+
require "uri/socks"
|
4
|
+
|
5
|
+
module Proxifier
|
6
|
+
class Proxy
|
7
|
+
class << self
|
8
|
+
def proxify?(host, no_proxy = nil)
|
9
|
+
return true unless no_proxy
|
10
|
+
|
11
|
+
dont_proxy = no_proxy.split(",")
|
12
|
+
dont_proxy.none? { |h| host =~ /#{h}\Z/ }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :url, :options
|
17
|
+
|
18
|
+
def initialize(url, options = {})
|
19
|
+
url = URI.parse(uri) unless url.is_a?(URI::Generic)
|
20
|
+
@url, @options = url, options
|
21
|
+
end
|
22
|
+
|
23
|
+
def open(host, port, local_host = nil, local_port = nil)
|
24
|
+
return TCPSocket.new(host, port, local_host, local_port) unless proxify?(host)
|
25
|
+
|
26
|
+
socket = TCPSocket.new(self.host, self.port, local_host, local_port)
|
27
|
+
|
28
|
+
begin
|
29
|
+
proxify(socket, host, port)
|
30
|
+
rescue
|
31
|
+
socket.close
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
socket
|
36
|
+
end
|
37
|
+
|
38
|
+
def proxify?(host)
|
39
|
+
self.class.proxify?(host, options[:no_proxy])
|
40
|
+
end
|
41
|
+
|
42
|
+
def proxify(socket, host, port)
|
43
|
+
do_proxify(socket, host, port)
|
44
|
+
end
|
45
|
+
|
46
|
+
%w(host port user password query version).each do |attr|
|
47
|
+
class_eval "def #{attr}; url.#{attr} end"
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_options
|
51
|
+
@query_options ||= query ? Hash[query.split("&").map { |q| q.split("=") }] : {}
|
52
|
+
end
|
53
|
+
|
54
|
+
%w(no_proxy).each do |option|
|
55
|
+
class_eval "def #{option}; options[:#{option}] end"
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
def do_proxify(socket, host, port)
|
60
|
+
raise NotImplementedError, "#{self} must implement do_proxify"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/proxifier.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "uri/socks"
|
3
|
+
|
4
|
+
module Proxifier
|
5
|
+
require "proxifier/version"
|
6
|
+
|
7
|
+
autoload :HTTPProxy, "proxifier/proxies/http"
|
8
|
+
autoload :SOCKSProxy, "proxifier/proxies/socks"
|
9
|
+
autoload :SOCKS5Proxy, "proxifier/proxies/socks"
|
10
|
+
autoload :SOCKS4Proxy, "proxifier/proxies/socks4"
|
11
|
+
autoload :SOCKS4AProxy, "proxifier/proxies/socks4a"
|
12
|
+
|
13
|
+
def self.Proxy(url, options = {})
|
14
|
+
url = URI.parse(url)
|
15
|
+
|
16
|
+
raise(ArgumentError, "proxy url has no scheme") unless url.scheme
|
17
|
+
begin
|
18
|
+
klass = const_get("#{url.scheme.upcase}Proxy")
|
19
|
+
rescue NameError
|
20
|
+
raise(ArgumentError, "unknown proxy scheme `#{url.scheme}'")
|
21
|
+
end
|
22
|
+
|
23
|
+
klass.new(url, options)
|
24
|
+
end
|
25
|
+
end
|
data/lib/uri/socks.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "uri/generic"
|
2
|
+
|
3
|
+
module URI
|
4
|
+
class SOCKS < Generic
|
5
|
+
DEFAULT_PORT = 1080
|
6
|
+
COMPONENT = [:scheme, :userinfo, :host, :port, :query].freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
class SOCKS4 < SOCKS
|
10
|
+
end
|
11
|
+
|
12
|
+
class SOCKS4A < SOCKS
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
@@schemes["SOCKS4"] = SOCKS4
|
17
|
+
@@schemes["SOCKS"] = SOCKS
|
18
|
+
@@schemes["SOCKS5"] = SOCKS
|
19
|
+
@@schemes["SOCKS4A"] = SOCKS4A
|
20
|
+
rescue
|
21
|
+
register_scheme 'SOCKS4', SOCKS4
|
22
|
+
register_scheme 'SOCKS', SOCKS
|
23
|
+
register_scheme 'SOCKS5', SOCKS
|
24
|
+
register_scheme 'SOCKS4A', SOCKS4A
|
25
|
+
end
|
26
|
+
end
|
data/proxifier2.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "proxifier/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "proxifier2"
|
6
|
+
s.version = Proxifier::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Samuel Kadolph"]
|
9
|
+
s.email = ["samuel@kadolph.com"]
|
10
|
+
s.homepage = "https://github.com/chef/ruby-proxifier"
|
11
|
+
s.summary = %q{Proxifier is a gem to force ruby to use a proxy.}
|
12
|
+
s.description = %q{Proxifier adds support for HTTP or SOCKS proxies and lets you force TCPSocket to use proxies.}
|
13
|
+
|
14
|
+
s.files = Dir["bin/*", "lib/**/*"] + ["LICENSE", "README.md", "proxifier2.gemspec"]
|
15
|
+
s.executables = ["pirb", "pruby"]
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proxifier2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Kadolph
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Proxifier adds support for HTTP or SOCKS proxies and lets you force TCPSocket
|
14
|
+
to use proxies.
|
15
|
+
email:
|
16
|
+
- samuel@kadolph.com
|
17
|
+
executables:
|
18
|
+
- pirb
|
19
|
+
- pruby
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- bin/pirb
|
26
|
+
- bin/pruby
|
27
|
+
- lib/proxifier.rb
|
28
|
+
- lib/proxifier/env.rb
|
29
|
+
- lib/proxifier/proxies/http.rb
|
30
|
+
- lib/proxifier/proxies/socks.rb
|
31
|
+
- lib/proxifier/proxies/socks4.rb
|
32
|
+
- lib/proxifier/proxies/socks4a.rb
|
33
|
+
- lib/proxifier/proxy.rb
|
34
|
+
- lib/proxifier/version.rb
|
35
|
+
- lib/uri/socks.rb
|
36
|
+
- proxifier2.gemspec
|
37
|
+
homepage: https://github.com/chef/ruby-proxifier
|
38
|
+
licenses: []
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubygems_version: 3.3.7
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Proxifier is a gem to force ruby to use a proxy.
|
59
|
+
test_files: []
|