Compare commits

...

10 Commits

Author SHA1 Message Date
rulingcom 26c39a7977 Add Ruby 3.1 support for socks. 2024-02-24 12:15:11 +08:00
rulingcom ebbf1f57dc gemspec: add license metadata. 2024-02-24 12:09:20 +08:00
rulingcom aef6d5f766 Use strict Base64 encoding to prevent bad requests. 2024-02-24 12:07:49 +08:00
rulingcom 1d9659309b Allow customizing User-Agent header (HTTP only). 2024-02-24 12:01:29 +08:00
rulingcom bf1f0bee18 Fixes for Proxy creation from URL String and SOCKS5 authentication. Bump version number to 1.0.4. 2024-02-24 11:58:46 +08:00
Samuel Kadolph 41ead73b21 Merge pull request #4 from berniedurfee/master
Update README.md
2014-06-12 12:25:15 -04:00
Bernie Durfee 71c5598e93 Update README.md
Fixed typo...
2014-06-11 08:03:52 -04:00
Samuel Kadolph e87a95208f Bump version 2012-03-06 15:15:22 -05:00
Samuel Kadolph 452121209b Fix typo 2012-03-06 15:11:26 -05:00
Samuel Kadolph b710babed6 Add gem summary and description. Bump version to 1.0.2. 2011-08-22 23:32:47 -04:00
13 changed files with 139 additions and 25 deletions

View File

@ -23,7 +23,7 @@ First is to enable ruby programmers to use HTTP or SOCKS proxies
interchangeably when using TCPSockets. Either manually with
`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
their respective ruby executables that support proxies from environment
variables.

View File

@ -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

View File

@ -6,7 +6,7 @@ module Proxifier
def open(host, port, local_host = nil, local_port = nil)
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
proxify(socket, host, port)

View File

@ -8,7 +8,8 @@ module Proxifier
socket << "CONNECT #{host}:#{port} HTTP/1.1\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"
buffer = Net::BufferedIO.new(socket)

View File

@ -3,7 +3,8 @@ require "proxifier/proxy"
module Proxifier
class SOCKSProxy < Proxy
VERSION = 0x05
VERSION = 0x05
SUBNEGOTIATION_VERSION = 0x01
def do_proxify(socket, host, port)
authenticaton_method = greet(socket)
@ -26,12 +27,12 @@ module Proxifier
case method
when 0x00 # NO AUTHENTICATION REQUIRED
when 0x02 # USERNAME/PASSWORD
user &&= user[0, 0xFF]
password &&= password[0, 0xFF]
_user = user ? user[0, 0xFF] : ''
_password = password ? password[0, 0xFF] : ''
socket << [user.size, user, password.size, password].pack("CA#{user.size}CA#{password.size}")
version, status = socket.read(2).unpack("CC")
check_version(version)
socket << [SUBNEGOTIATION_VERSION, _user.size, _user, _password.size, _password].pack("CCA#{_user.size}CA#{_password.size}")
version, status = socket.read(2).unpack('CC')
check_version(version, SUBNEGOTIATION_VERSION)
case status
when 0x00 # SUCCESS

View File

@ -16,14 +16,14 @@ module Proxifier
attr_reader :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
end
def open(host, port, local_host = nil, local_port = nil)
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
proxify(socket, host, port)
@ -51,7 +51,7 @@ module Proxifier
@query_options ||= query ? Hash[query.split("&").map { |q| q.split("=") }] : {}
end
%w(no_proxy).each do |option|
%w(no_proxy user_agent).each do |option|
class_eval "def #{option}; options[:#{option}] end"
end

View File

@ -1,3 +1,3 @@
module Proxifier
VERSION = "1.0.1"
VERSION = '1.0.4'
end

View File

@ -1,18 +1,32 @@
require "uri/generic"
require 'uri/generic'
module URI
class SOCKS < Generic
class Socks < Generic
DEFAULT_PORT = 1080
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
@@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
@@schemes["SOCKS4A"] = SOCKS4A
end

View File

@ -8,9 +8,12 @@ Gem::Specification.new do |s|
s.authors = ["Samuel Kadolph"]
s.email = ["samuel@kadolph.com"]
s.homepage = "https://github.com/samuelkadolph/ruby-proxifier"
s.summary = %q{}
s.description = %q{}
s.summary = %q{Proxifier is a gem to force ruby to use a proxy.}
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.executables = ["pirb", "pruby"]
s.add_development_dependency 'minitest', '>= 4.6.0'
end

View File

@ -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

View File

@ -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

20
spec/proxifier_spec.rb Normal file
View File

@ -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

8
spec/spec_helper.rb Normal file
View File

@ -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'