Class | Net::SSH::Proxy::SOCKS5 |
In: |
lib/net/ssh/proxy/socks5.rb
|
Parent: | Object |
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.
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 |
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
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