An implementation of a socket factory that returns a socket which will tunnel the connection through a SOCKS5 proxy. It allows explicit specification of the user and password, but if none are given it will look in the SOCKS_USER/SOCKS_PASSWORD and CONNECT_USER/CONNECT_PASSWORD environment variables as well.

Methods
Constants
SOCKS_VERSION = 5
SOCKS_METHOD_NO_AUTH = 0
SOCKS_METHOD_GSSAPI = 1
SOCKS_METHOD_PASSWD = 2
SOCKS_METHOD_NONE = 0xFF
SOCKS_CMD_CONNECT = 1
SOCKS_ATYP_IPV4 = 1
SOCKS_ATYP_DOMAIN = 3
SOCKS_ATYP_IPV6 = 4
SOCKS_SUCCESS = 0
SOCKS_FAILURE = 1
SOCKS_NOT_ALLOWED = 2
SOCKS_NETWORK_UNREACHABLE = 3
SOCKS_HOST_UNREACHABLE = 4
SOCKS_REFUSED = 5
SOCKS_TTL_EXPIRED = 6
SOCKS_CMD_NOT_SUPPORTED = 7
SOCKS_ADDR_NOT_SUPPORTED = 8
Public Class methods
new( proxy_host, proxy_port=1080, options={} )

Create a new proxy connection to the given proxy host and port. Optionally, @:user@ and @:password@ options may be given to identify the username and password with which to authenticate.

    # File lib/net/ssh/proxy/socks5.rb, line 58
58:         def initialize( proxy_host, proxy_port=1080, options={} )
59:           @proxy_host = proxy_host
60:           @proxy_port = proxy_port
61:           @options = options
62:         end
Public Instance methods
open( host, port )

Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated.

     # File lib/net/ssh/proxy/socks5.rb, line 66
 66:         def open( host, port )
 67:           sock = TCPSocket.new( @proxy_host, @proxy_port )
 68: 
 69:           methods = [ SOCKS_METHOD_NO_AUTH ]
 70:           methods << SOCKS_METHOD_PASSWD if proxy_user
 71: 
 72:           packet = [ SOCKS_VERSION, methods.size, *methods ].pack( "C*" )
 73:           sock.send packet, 0
 74: 
 75:           version, method = sock.recv( 2 ).unpack( "CC" )
 76:           if version != 5
 77:             sock.close
 78:             raise Net::SSH::Proxy::Error,
 79:               "invalid SOCKS version (#{version})"
 80:           end
 81: 
 82:           if method == SOCKS_METHOD_NONE
 83:             sock.close
 84:             raise Net::SSH::Proxy::Error,
 85:               "no supported authorization methods"
 86:           end
 87: 
 88:           case method
 89:             when SOCKS_METHOD_NO_AUTH
 90:               # no method-dependent subnegotiation required
 91: 
 92:             when SOCKS_METHOD_PASSWD
 93:               negotiate_password( sock )
 94:           end
 95: 
 96:           packet = [ SOCKS_VERSION, SOCKS_CMD_CONNECT, 0 ].pack( "C*" )
 97: 
 98:           if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
 99:             packet << [ SOCKS_ATYP_IPV4, $1.to_i, $2.to_i,
100:                         $3.to_i, $4.to_i ].pack( "C*" )
101:           else
102:             packet << [ SOCKS_ATYP_DOMAIN, host.length, host ].pack( "CCA*" )
103:           end
104: 
105:           packet << [ port ].pack( "n" )
106:           sock.send packet, 0
107: 
108:           version, reply, = sock.recv( 4 ).unpack( "C*" )
109:           len = sock.recv( 1 )[0]
110:           sock.recv( len + 2 )
111: 
112:           unless reply == SOCKS_SUCCESS
113:             sock.close
114:             raise ConnectError, "#{reply}"
115:           end
116: 
117:           return sock
118:         end

[Validate]