Compare commits
10 Commits
7f8a0b3ffe
...
26c39a7977
Author | SHA1 | Date |
---|---|---|
rulingcom | 26c39a7977 | |
rulingcom | ebbf1f57dc | |
rulingcom | aef6d5f766 | |
rulingcom | 1d9659309b | |
rulingcom | bf1f0bee18 | |
Samuel Kadolph | 41ead73b21 | |
Bernie Durfee | 71c5598e93 | |
Samuel Kadolph | e87a95208f | |
Samuel Kadolph | 452121209b | |
Samuel Kadolph | b710babed6 |
|
@ -23,7 +23,7 @@ First is to enable ruby programmers to use HTTP or SOCKS proxies
|
||||||
interchangeably when using TCPSockets. Either manually with
|
interchangeably when using TCPSockets. Either manually with
|
||||||
`Proxifier::Proxy#open` or by `require "proxifier/env"`.
|
`Proxifier::Proxy#open` or by `require "proxifier/env"`.
|
||||||
|
|
||||||
The second purpose is to use ruby code that doesn't user proxies for users that
|
The second purpose is to use ruby code that doesn't use proxies for users that
|
||||||
have to use proxies.<br>The pruby and pirb executables are simple wrappers for
|
have to use proxies.<br>The pruby and pirb executables are simple wrappers for
|
||||||
their respective ruby executables that support proxies from environment
|
their respective ruby executables that support proxies from environment
|
||||||
variables.
|
variables.
|
||||||
|
|
11
Rakefile
11
Rakefile
|
@ -1 +1,10 @@
|
||||||
require "bundler/gem_tasks"
|
require 'bundler/gem_tasks'
|
||||||
|
require 'rake/testtask'
|
||||||
|
|
||||||
|
task default: :test
|
||||||
|
|
||||||
|
Rake::TestTask.new do |task|
|
||||||
|
task.libs << 'lib' << 'spec'
|
||||||
|
task.pattern = 'spec/**/*_spec.rb'
|
||||||
|
task.verbose = true
|
||||||
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Proxifier
|
||||||
def open(host, port, local_host = nil, local_port = nil)
|
def open(host, port, local_host = nil, local_port = nil)
|
||||||
return TCPSocket.new(host, port, local_host, local_port, :proxy => nil) unless proxify?(host)
|
return TCPSocket.new(host, port, local_host, local_port, :proxy => nil) unless proxify?(host)
|
||||||
|
|
||||||
socket = TCPSocket.new(proxy.host, proxy.port, local_host, local_port, :proxy => nil)
|
socket = TCPSocket.new(self.host, self.port, local_host, local_port, :proxy => nil)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
proxify(socket, host, port)
|
proxify(socket, host, port)
|
||||||
|
|
|
@ -8,7 +8,8 @@ module Proxifier
|
||||||
|
|
||||||
socket << "CONNECT #{host}:#{port} HTTP/1.1\r\n"
|
socket << "CONNECT #{host}:#{port} HTTP/1.1\r\n"
|
||||||
socket << "Host: #{host}:#{port}\r\n"
|
socket << "Host: #{host}:#{port}\r\n"
|
||||||
socket << "Proxy-Authorization: Basic #{["#{user}:#{password}"].pack("m").chomp}\r\n" if user
|
socket << "Proxy-Authorization: Basic #{Base64.strict_encode64("#{user}:#{password}").chomp}\r\n" if user
|
||||||
|
socket << "User-Agent: #{user_agent}\r\n" if user_agent
|
||||||
socket << "\r\n"
|
socket << "\r\n"
|
||||||
|
|
||||||
buffer = Net::BufferedIO.new(socket)
|
buffer = Net::BufferedIO.new(socket)
|
||||||
|
|
|
@ -3,7 +3,8 @@ require "proxifier/proxy"
|
||||||
|
|
||||||
module Proxifier
|
module Proxifier
|
||||||
class SOCKSProxy < Proxy
|
class SOCKSProxy < Proxy
|
||||||
VERSION = 0x05
|
VERSION = 0x05
|
||||||
|
SUBNEGOTIATION_VERSION = 0x01
|
||||||
|
|
||||||
def do_proxify(socket, host, port)
|
def do_proxify(socket, host, port)
|
||||||
authenticaton_method = greet(socket)
|
authenticaton_method = greet(socket)
|
||||||
|
@ -26,12 +27,12 @@ module Proxifier
|
||||||
case method
|
case method
|
||||||
when 0x00 # NO AUTHENTICATION REQUIRED
|
when 0x00 # NO AUTHENTICATION REQUIRED
|
||||||
when 0x02 # USERNAME/PASSWORD
|
when 0x02 # USERNAME/PASSWORD
|
||||||
user &&= user[0, 0xFF]
|
_user = user ? user[0, 0xFF] : ''
|
||||||
password &&= password[0, 0xFF]
|
_password = password ? password[0, 0xFF] : ''
|
||||||
|
|
||||||
socket << [user.size, user, password.size, password].pack("CA#{user.size}CA#{password.size}")
|
socket << [SUBNEGOTIATION_VERSION, _user.size, _user, _password.size, _password].pack("CCA#{_user.size}CA#{_password.size}")
|
||||||
version, status = socket.read(2).unpack("CC")
|
version, status = socket.read(2).unpack('CC')
|
||||||
check_version(version)
|
check_version(version, SUBNEGOTIATION_VERSION)
|
||||||
|
|
||||||
case status
|
case status
|
||||||
when 0x00 # SUCCESS
|
when 0x00 # SUCCESS
|
||||||
|
|
|
@ -16,14 +16,14 @@ module Proxifier
|
||||||
attr_reader :url, :options
|
attr_reader :url, :options
|
||||||
|
|
||||||
def initialize(url, options = {})
|
def initialize(url, options = {})
|
||||||
url = URI.parse(uri) unless url.is_a?(URI::Generic)
|
url = URI.parse(url) unless url.is_a?(URI::Generic)
|
||||||
@url, @options = url, options
|
@url, @options = url, options
|
||||||
end
|
end
|
||||||
|
|
||||||
def open(host, port, local_host = nil, local_port = nil)
|
def open(host, port, local_host = nil, local_port = nil)
|
||||||
return TCPSocket.new(host, port, local_host, local_port) unless proxify?(host)
|
return TCPSocket.new(host, port, local_host, local_port) unless proxify?(host)
|
||||||
|
|
||||||
socket = TCPSocket.new(proxy.host, proxy.port, local_host, local_port)
|
socket = TCPSocket.new(self.host, self.port, local_host, local_port)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
proxify(socket, host, port)
|
proxify(socket, host, port)
|
||||||
|
@ -51,7 +51,7 @@ module Proxifier
|
||||||
@query_options ||= query ? Hash[query.split("&").map { |q| q.split("=") }] : {}
|
@query_options ||= query ? Hash[query.split("&").map { |q| q.split("=") }] : {}
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(no_proxy).each do |option|
|
%w(no_proxy user_agent).each do |option|
|
||||||
class_eval "def #{option}; options[:#{option}] end"
|
class_eval "def #{option}; options[:#{option}] end"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Proxifier
|
module Proxifier
|
||||||
VERSION = "1.0.1"
|
VERSION = '1.0.4'
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,32 @@
|
||||||
require "uri/generic"
|
require 'uri/generic'
|
||||||
|
|
||||||
module URI
|
module URI
|
||||||
class SOCKS < Generic
|
class Socks < Generic
|
||||||
DEFAULT_PORT = 1080
|
DEFAULT_PORT = 1080
|
||||||
COMPONENT = [:scheme, :userinfo, :host, :port, :query].freeze
|
COMPONENT = [:scheme, :userinfo, :host, :port, :query].freeze
|
||||||
end
|
|
||||||
@@schemes["SOCKS"] = SOCKS
|
|
||||||
@@schemes["SOCKS5"] = SOCKS
|
|
||||||
|
|
||||||
class SOCKS4 < SOCKS
|
def self.build(args)
|
||||||
|
tmp = Util.make_components_hash(self, args)
|
||||||
|
super(tmp)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@schemes["SOCKS4"] = SOCKS4
|
|
||||||
|
|
||||||
class SOCKS4A < SOCKS
|
class Socks4 < Socks
|
||||||
|
end
|
||||||
|
|
||||||
|
class Socks4A < Socks
|
||||||
|
end
|
||||||
|
|
||||||
|
mapping = {
|
||||||
|
'SOCKS' => Socks,
|
||||||
|
'SOCKS5' => Socks,
|
||||||
|
'SOCKS4' => Socks4,
|
||||||
|
'SOCKS4A' => Socks4A
|
||||||
|
}
|
||||||
|
if URI::VERSION_CODE >= "001100"
|
||||||
|
mapping.each { |scheme, class_name| register_scheme scheme, class_name }
|
||||||
|
else
|
||||||
|
mapping.each { |scheme, class_name| @@schemes[scheme] = class_name }
|
||||||
end
|
end
|
||||||
@@schemes["SOCKS4A"] = SOCKS4A
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,12 @@ Gem::Specification.new do |s|
|
||||||
s.authors = ["Samuel Kadolph"]
|
s.authors = ["Samuel Kadolph"]
|
||||||
s.email = ["samuel@kadolph.com"]
|
s.email = ["samuel@kadolph.com"]
|
||||||
s.homepage = "https://github.com/samuelkadolph/ruby-proxifier"
|
s.homepage = "https://github.com/samuelkadolph/ruby-proxifier"
|
||||||
s.summary = %q{}
|
s.summary = %q{Proxifier is a gem to force ruby to use a proxy.}
|
||||||
s.description = %q{}
|
s.description = %q{Proxifier adds support for HTTP or SOCKS proxies and lets you force TCPSocket to use proxies.}
|
||||||
|
s.license = "MIT"
|
||||||
|
|
||||||
s.files = Dir["bin/*", "lib/**/*"] + ["LICENSE", "README.md"]
|
s.files = Dir["bin/*", "lib/**/*"] + ["LICENSE", "README.md"]
|
||||||
s.executables = ["pirb", "pruby"]
|
s.executables = ["pirb", "pruby"]
|
||||||
|
|
||||||
|
s.add_development_dependency 'minitest', '>= 4.6.0'
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'uri'
|
||||||
|
require 'proxifier/proxies/socks'
|
||||||
|
|
||||||
|
describe Proxifier::SOCKSProxy do
|
||||||
|
|
||||||
|
before do
|
||||||
|
@socket = MiniTest::Mock.new
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should comply with SOCKS5 authentication specification' do
|
||||||
|
proxy = Proxifier::Proxy('socks://joe:sekret@myproxy:60123')
|
||||||
|
|
||||||
|
proxy.must_be_instance_of Proxifier::SOCKSProxy
|
||||||
|
|
||||||
|
TCPSocket.stub :new, @socket do
|
||||||
|
@socket.expect :<<, nil, ["\x05\x02\x00\x02"]
|
||||||
|
@socket.expect :read, "\x05\x02", [2]
|
||||||
|
@socket.expect :<<, nil, ["\x01\x03joe\x06sekret"]
|
||||||
|
@socket.expect :read, "\x01\x00", [2]
|
||||||
|
@socket.expect :<<, nil, ["\x05\x01\x00\x03\tlocalhost\x048"]
|
||||||
|
@socket.expect :read, "\x05\x00\x00\x01", [4]
|
||||||
|
@socket.expect :read, "\x7F\x00\x00\x01", [4]
|
||||||
|
@socket.expect :read, "\x08", [2]
|
||||||
|
|
||||||
|
proxy.open('localhost', 1080)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'uri'
|
||||||
|
require 'proxifier/proxy'
|
||||||
|
|
||||||
|
describe Proxifier::Proxy do
|
||||||
|
|
||||||
|
it 'should create proxy from URL String' do
|
||||||
|
proxy = Proxifier::Proxy.new('socks://joe:sekret@myproxy:60123')
|
||||||
|
|
||||||
|
proxy.url.scheme.must_equal 'socks'
|
||||||
|
proxy.user.must_equal 'joe'
|
||||||
|
proxy.password.must_equal 'sekret'
|
||||||
|
proxy.host.must_equal 'myproxy'
|
||||||
|
proxy.port.must_equal 60123
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create proxy from generic URI' do
|
||||||
|
uri = URI::Generic.new('socks', 'joe:sekret', 'myproxy', 60123, nil, nil, nil, nil, nil)
|
||||||
|
proxy = Proxifier::Proxy.new(uri)
|
||||||
|
|
||||||
|
proxy.url.scheme.must_equal 'socks'
|
||||||
|
proxy.user.must_equal 'joe'
|
||||||
|
proxy.password.must_equal 'sekret'
|
||||||
|
proxy.host.must_equal 'myproxy'
|
||||||
|
proxy.port.must_equal 60123
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,20 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'proxifier/proxies/socks'
|
||||||
|
|
||||||
|
describe Proxifier do
|
||||||
|
|
||||||
|
it 'should have a version number' do
|
||||||
|
Proxifier::VERSION.wont_be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create Proxy from URL String' do
|
||||||
|
proxy = Proxifier::Proxy('socks://joe:sekret@myproxy:60123')
|
||||||
|
|
||||||
|
proxy.must_be_instance_of Proxifier::SOCKSProxy
|
||||||
|
proxy.user.must_equal 'joe'
|
||||||
|
proxy.password.must_equal 'sekret'
|
||||||
|
proxy.host.must_equal 'myproxy'
|
||||||
|
proxy.port.must_equal 60123
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,8 @@
|
||||||
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
||||||
|
require 'rubygems'
|
||||||
|
|
||||||
|
gem 'minitest' # ensure we are using the gem version
|
||||||
|
require 'minitest/spec'
|
||||||
|
require 'minitest/autorun'
|
||||||
|
|
||||||
|
require 'proxifier'
|
Loading…
Reference in New Issue