proxifier-1.0.3/ 0000755 0001750 0001750 00000000000 12677255203 014253 5 ustar kanashiro kanashiro proxifier-1.0.3/lib/ 0000755 0001750 0001750 00000000000 12677255203 015021 5 ustar kanashiro kanashiro proxifier-1.0.3/lib/proxifier.rb 0000644 0001750 0001750 00000001235 12677255203 017356 0 ustar kanashiro kanashiro require "uri"
require "uri/socks"
module Proxifier
require "proxifier/version"
autoload :HTTPProxy, "proxifier/proxies/http"
autoload :SOCKSProxy, "proxifier/proxies/socks"
autoload :SOCKS5Proxy, "proxifier/proxies/socks"
autoload :SOCKS4Proxy, "proxifier/proxies/socks4"
autoload :SOCKS4AProxy, "proxifier/proxies/socks4a"
def self.Proxy(url, options = {})
url = URI.parse(url)
raise(ArgumentError, "proxy url has no scheme") unless url.scheme
begin
klass = const_get("#{url.scheme.upcase}Proxy")
rescue NameError
raise(ArgumentError, "unknown proxy scheme `#{url.scheme}'")
end
klass.new(url, options)
end
end
proxifier-1.0.3/lib/uri/ 0000755 0001750 0001750 00000000000 12677255203 015620 5 ustar kanashiro kanashiro proxifier-1.0.3/lib/uri/socks.rb 0000644 0001750 0001750 00000000526 12677255203 017272 0 ustar kanashiro kanashiro require "uri/generic"
module URI
class SOCKS < Generic
DEFAULT_PORT = 1080
COMPONENT = [:scheme, :userinfo, :host, :port, :query].freeze
end
@@schemes["SOCKS"] = SOCKS
@@schemes["SOCKS5"] = SOCKS
class SOCKS4 < SOCKS
end
@@schemes["SOCKS4"] = SOCKS4
class SOCKS4A < SOCKS
end
@@schemes["SOCKS4A"] = SOCKS4A
end
proxifier-1.0.3/lib/proxifier/ 0000755 0001750 0001750 00000000000 12677255203 017030 5 ustar kanashiro kanashiro proxifier-1.0.3/lib/proxifier/proxies/ 0000755 0001750 0001750 00000000000 12677255203 020521 5 ustar kanashiro kanashiro proxifier-1.0.3/lib/proxifier/proxies/socks4a.rb 0000644 0001750 0001750 00000000300 12677255203 022406 0 ustar kanashiro kanashiro require "proxifier/proxies/socks"
module Proxifier
class SOCKS4AProxy < SOCKSProxy
def do_proxify(*)
raise NotImplementedError, "SOCKS4A is not yet implemented"
end
end
end
proxifier-1.0.3/lib/proxifier/proxies/socks4.rb 0000644 0001750 0001750 00000002450 12677255203 022255 0 ustar kanashiro kanashiro require "proxifier/proxies/socks"
module Proxifier
class SOCKS4Proxy < SOCKSProxy
VERSION = 0x04
protected
def greet(socket)
# noop
end
def authenticate(socket, method)
# noop
end
def connect(socket, host, port)
begin
ip = IPAddr.new(host)
rescue ArgumentError
ip = IPAddr.new(Socket.getaddrinfo(host, nil, :INET, :STREAM).first)
end
socket << [VERSION, 0x01, port].pack("CCn") << ip.hton
socket << user if user
socket << 0x00
version, status, port = socket.read(4).unpack("CCn")
check_version(version, 0x00)
ip = IPAddr.ntop(socket.read(4))
case status
when 0x5A # request granted
when 0x5B # request rejected or failed
raise "request rejected or failed"
when 0x5C # request rejected becasue SOCKS server cannot connect to identd on the client
raise "request rejected becasue SOCKS server cannot connect to identd on the client"
when 0x5D # request rejected because the client program and identd report different user-ids
raise "request rejected because the client program and identd report different user-ids"
else
raise "unknown SOCKS error"
end
end
end
end
proxifier-1.0.3/lib/proxifier/proxies/socks.rb 0000644 0001750 0001750 00000006124 12677255203 022173 0 ustar kanashiro kanashiro require "ipaddr"
require "proxifier/proxy"
module Proxifier
class SOCKSProxy < Proxy
VERSION = 0x05
def do_proxify(socket, host, port)
authenticaton_method = greet(socket)
authenticate(socket, authenticaton_method)
connect(socket, host, port)
end
protected
def greet(socket)
methods = authentication_methods
socket << [VERSION, methods.size, *methods].pack("CCC#{methods.size}")
version, authentication_method = socket.read(2).unpack("CC")
check_version(version)
authentication_method
end
def authenticate(socket, method)
case method
when 0x00 # NO AUTHENTICATION REQUIRED
when 0x02 # USERNAME/PASSWORD
user &&= user[0, 0xFF]
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)
case status
when 0x00 # SUCCESS
else
raise "SOCKS5 username/password authentication failed"
end
else
raise "no acceptable SOCKS5 authentication methods"
end
end
def connect(socket, host, port)
host = host[0, 0xFF]
socket << [VERSION, 0x01, 0x00, 0x03, host.size, host, port].pack("CCCCCA#{host.size}n")
version, status, _, type = socket.read(4).unpack("CCCC")
check_version(version)
case status
when 0x00 # succeeded
when 0x01 # general SOCKS server failure
raise "general SOCKS server failure"
when 0x02 # connection not allowed by ruleset
raise "connection not allowed by ruleset"
when 0x03 # Network unreachable
raise "network unreachable"
when 0x04 # Host unreachable
raise "host unreachable"
when 0x05 # Connection refused
raise "connection refused"
when 0x06 # TTL expired
raise "TTL expired"
when 0x07 # Command not supported
raise "command not supported"
when 0x08 # Address type not supported
raise "address type not supported"
else # unassigned
raise "unknown SOCKS error"
end
case type
when 0x01 # IP V4 address
destination = IPAddr.ntop(socket.read(4))
when 0x03 # DOMAINNAME
length = socket.read(1).unpack("C").first
destination = socket.read(length).unpack("A#{length}")
when 0x04 # IP V6 address
destination = IPAddr.ntop(socket.read(16))
else
raise "unsupported SOCKS5 address type"
end
port = socket.read(2).unpack("n").first
end
def check_version(version, should_be = VERSION)
raise "mismatched SOCKS version" unless version == should_be
end
private
def authentication_methods
methods = []
methods << 0x00 # NO AUTHENTICATION REQUIRED
methods << 0x02 if user # USERNAME/PASSWORD
methods
end
end
SOCKS5Proxy = SOCKSProxy
end
proxifier-1.0.3/lib/proxifier/proxies/http.rb 0000644 0001750 0001750 00000001075 12677255203 022030 0 ustar kanashiro kanashiro require "net/http"
require "proxifier/proxy"
module Proxifier
class HTTPProxy < Proxy
def do_proxify(socket, host, port)
return if query_options["tunnel"] == "false"
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 << "\r\n"
buffer = Net::BufferedIO.new(socket)
response = Net::HTTPResponse.read_new(buffer)
response.error! unless response.is_a?(Net::HTTPOK)
end
end
end
proxifier-1.0.3/lib/proxifier/version.rb 0000644 0001750 0001750 00000000051 12677255203 021036 0 ustar kanashiro kanashiro module Proxifier
VERSION = "1.0.3"
end
proxifier-1.0.3/lib/proxifier/errors.rb 0000644 0001750 0001750 00000000076 12677255203 020674 0 ustar kanashiro kanashiro module Proxifier
class ProxyError < StandardError
end
end
proxifier-1.0.3/lib/proxifier/proxy.rb 0000644 0001750 0001750 00000002666 12677255203 020550 0 ustar kanashiro kanashiro require "socket"
require "uri"
require "uri/socks"
module Proxifier
class Proxy
class << self
def proxify?(host, no_proxy = nil)
return true unless no_proxy
dont_proxy = no_proxy.split(",")
dont_proxy.none? { |h| host =~ /#{h}\Z/ }
end
end
attr_reader :url, :options
def initialize(url, options = {})
url = URI.parse(uri) 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(self.host, self.port, local_host, local_port)
begin
proxify(socket, host, port)
rescue
socket.close
raise
end
socket
end
def proxify?(host)
self.class.proxify?(host, options[:no_proxy])
end
def proxify(socket, host, port)
do_proxify(socket, host, port)
end
%w(host port user password query version).each do |attr|
class_eval "def #{attr}; url.#{attr} end"
end
def query_options
@query_options ||= query ? Hash[query.split("&").map { |q| q.split("=") }] : {}
end
%w(no_proxy).each do |option|
class_eval "def #{option}; options[:#{option}] end"
end
protected
def do_proxify(socket, host, port)
raise NotImplementedError, "#{self} must implement do_proxify"
end
end
end
proxifier-1.0.3/lib/proxifier/env.rb 0000644 0001750 0001750 00000006030 12677255203 020144 0 ustar kanashiro kanashiro require "socket"
require "proxifier"
module Proxifier
class Proxy
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(self.host, self.port, local_host, local_port, :proxy => nil)
begin
proxify(socket, host, port)
rescue
socket.close
raise
end
socket
end
end
module Proxify
def self.included(klass)
klass.class_eval do
alias_method :initialize_without_proxy, :initialize
alias_method :initialize, :initialize_with_proxy
end
end
def initialize_with_proxy(host, port, options_or_local_host = {}, local_port = nil, options_if_local_host = {})
if options_or_local_host.is_a?(Hash)
local_host = nil
options = options_or_local_host
else
local_host = options_or_local_host
options = options_if_local_host
end
if options[:proxy] && (proxy = Proxifier::Proxy(options.delete(:proxy), options)) && proxy.proxify?(host)
initialize_without_proxy(proxy.host, proxy.port, local_host, local_port)
begin
proxy.proxify(self, host, port)
rescue
close
raise
end
else
initialize_without_proxy(host, port, local_host, local_port)
end
end
end
module EnvironmentProxify
def self.included(klass)
klass.class_eval do
extend ClassMethods
alias_method :initialize_without_environment_proxy, :initialize
alias_method :initialize, :initialize_with_environment_proxy
end
end
def initialize_with_environment_proxy(host, port, options_or_local_host = {}, local_port = nil, options_if_local_host = {})
if options_or_local_host.is_a?(Hash)
local_host = nil
options = options_or_local_host
else
local_host = options_or_local_host
options = options_if_local_host
end
options = { :proxy => environment_proxy, :no_proxy => environment_no_proxy }.merge(options)
initialize_without_environment_proxy(host, port, local_host, local_port, options)
end
def environment_proxy
self.class.environment_proxy
end
def environment_no_proxy
self.class.environment_no_proxy
end
module ClassMethods
def environment_proxy
ENV["proxy"] || ENV["PROXY"] || specific_environment_proxy
end
def environment_no_proxy
ENV["no_proxy"] || ENV["NO_PROXY"]
end
private
def specific_environment_proxy
%w(socks socks5 socks4a socks4 http).each do |type|
if proxy = ENV["#{type}_proxy"] || ENV["#{type.upcase}_PROXY"]
scheme = "#{type}://"
proxy = proxy.dup
proxy.insert(0, scheme) unless proxy.index(scheme) == 0
return proxy
end
end
nil
end
end
end
end
class TCPSocket
include Proxifier::Proxify
include Proxifier::EnvironmentProxify
end
proxifier-1.0.3/bin/ 0000755 0001750 0001750 00000000000 12677255203 015023 5 ustar kanashiro kanashiro proxifier-1.0.3/bin/pirb 0000755 0001750 0001750 00000000545 12677255203 015711 0 ustar kanashiro kanashiro #!/usr/bin/env ruby
executable = File.expand_path("../" + Gem.default_exec_format % "irb", Gem.ruby)
full_gem_path = Gem.loaded_specs["proxifier"].full_gem_path
load_paths = Gem.loaded_specs["proxifier"].require_paths.map { |p| "-I#{File.join(full_gem_path, p)}" }
# TODO: support argument switches
exec(executable, *load_paths, "-rproxifier/env", *ARGV)
proxifier-1.0.3/bin/pruby 0000755 0001750 0001750 00000000452 12677255203 016113 0 ustar kanashiro kanashiro #!/usr/bin/env ruby
executable = Gem.ruby
full_gem_path = Gem.loaded_specs["proxifier"].full_gem_path
load_paths = Gem.loaded_specs["proxifier"].require_paths.map { |p| "-I#{File.join(full_gem_path, p)}" }
# TODO: support argument switches
exec(executable, *load_paths, "-rproxifier/env", *ARGV)
proxifier-1.0.3/LICENSE 0000644 0001750 0001750 00000002045 12677255203 015261 0 ustar kanashiro kanashiro Copyright (C) 2011 by Samuel Kadolph
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
proxifier-1.0.3/README.md 0000644 0001750 0001750 00000005605 12677255203 015540 0 ustar kanashiro kanashiro # ruby-proxifier
## Installing
### Recommended
```
gem install proxifier
```
### Edge
```
git clone https://github.com/samuelkadolph/ruby-proxifier
cd ruby-proxifier && rake install
```
## Rationale
This gem was created for 2 purposes.
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
have to use proxies.
The pruby and pirb executables are simple wrappers for
their respective ruby executables that support proxies from environment
variables.
## Usage
### Executable Wrappers & Environment Variables
proxifier provides two executables: `pruby` and `pirb`. They are simple
wrappers for your current `ruby` and `irb` executables that requires the
`"proxifier/env"` script which installs hooks into `TCPSocket` which will use
the proxy environment variables to proxy any `TCPSocket`.
The environment variables that proxifier will check are (in order of descending
precedence):
Variable Name | Alternatives | Notes |
---|---|---|
proxy | PROXY | Requires the proxy scheme to be present. |
socks_proxy | SOCKS_PROXY socks5_proxy SOCKS5_PROXY |
Implies the SOCKS5 proxy scheme. |
socks4a_proxy | SOCKS4A_PROXY | Implies the SOCKS4A proxy scheme. |
socks4_proxy | PROXY | Implies the SOCKS4 proxy scheme. |
http_proxy | HTTP_PROXY | Implies the HTTP proxy scheme. |
Protocol | Formats | Notes |
---|---|---|
HTTP | http://[username[:password]@]host[:port][?tunnel=false] |
The port defaults to 80. This is currently a limitation that may be solved in the future. Appending ?tunnel=false forces the proxy to not use CONNECT . |
SOCKS5 | socks://[username[:password]@]host[:port] socks5://[username[:password]@]host[:port] |
Port defaults to 1080. |
SOCKS4A | socks4a://[username@]host[:port] |
Not yet implemented. |
SOCKS4 | socks4://[username@]host[:port] |
Currently hangs. Not sure if the problem is with code or server. |