An implementation of a SOCKS5 proxy. To use it, instantiate it, then pass the instantiated object via the :proxy key to Net::SSH.start:
require 'net/ssh/proxy/socks5' proxy = Net::SSH::Proxy::SOCKS5.new('proxy.host', proxy_port, :user => 'user', :password => "password") Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| ... end
Constants
VERSION | = | 5 | The SOCKS protocol version used by this class | |
METHOD_NO_AUTH | = | 0 | The SOCKS authentication type for requests without authentication | |
METHOD_PASSWD | = | 2 | The SOCKS authentication type for requests via username/password | |
METHOD_NONE | = | 0xFF | The SOCKS authentication type for when there are no supported authentication methods. | |
CMD_CONNECT | = | 1 | The SOCKS packet type for requesting a proxy connection. | |
ATYP_IPV4 | = | 1 | The SOCKS address type for connections via IP address. | |
ATYP_DOMAIN | = | 3 | The SOCKS address type for connections via domain name. | |
SUCCESS | = | 0 | The SOCKS response code for a successful operation. |
Attributes
options | [R] | The map of options given at initialization |
proxy_host | [R] | The proxy’s host name or IP address |
proxy_port | [R] | The proxy’s port number |
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.
[show source]
# File lib/net/ssh/proxy/socks5.rb, line 57 57: def initialize(proxy_host, proxy_port=1080, options={}) 58: @proxy_host = proxy_host 59: @proxy_port = proxy_port 60: @options = options 61: 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.
[show source]
# File lib/net/ssh/proxy/socks5.rb, line 65 65: def open(host, port) 66: socket = TCPSocket.new(proxy_host, proxy_port) 67: 68: methods = [METHOD_NO_AUTH] 69: methods << METHOD_PASSWD if options[:user] 70: 71: packet = [VERSION, methods.size, *methods].pack("C*") 72: socket.send packet, 0 73: 74: version, method = socket.recv(2).unpack("CC") 75: if version != VERSION 76: socket.close 77: raise Net::SSH::Proxy::Error, "invalid SOCKS version (#{version})" 78: end 79: 80: if method == METHOD_NONE 81: socket.close 82: raise Net::SSH::Proxy::Error, "no supported authorization methods" 83: end 84: 85: negotiate_password(socket) if method == METHOD_PASSWD 86: 87: packet = [VERSION, CMD_CONNECT, 0].pack("C*") 88: 89: if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ 90: packet << [ATYP_IPV4, $1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*") 91: else 92: packet << [ATYP_DOMAIN, host.length, host].pack("CCA*") 93: end 94: 95: packet << [port].pack("n") 96: socket.send packet, 0 97: 98: version, reply, = socket.recv(2).unpack("C*") 99: socket.recv(1) 100: address_type = socket.recv(1).getbyte(0) 101: case address_type 102: when 1 103: socket.recv(4) # get four bytes for IPv4 address 104: when 3 105: len = socket.recv(1).getbyte(0) 106: hostname = socket.recv(len) 107: when 4 108: ipv6addr hostname = socket.recv(16) 109: else 110: socket.close 111: raise ConnectionError, "Illegal response type" 112: end 113: portnum = socket.recv(2) 114: 115: unless reply == SUCCESS 116: socket.close 117: raise ConnectError, "#{reply}" 118: end 119: 120: return socket 121: end