class Net::SSH::Proxy::SOCKS5
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
- ATYP_DOMAIN
The SOCKS address type for connections via domain name.
- ATYP_IPV4
The SOCKS address type for connections via IP address.
- CMD_CONNECT
The SOCKS packet type for requesting a proxy connection.
- METHOD_NONE
The SOCKS authentication type for when there are no supported authentication methods.
- METHOD_NO_AUTH
The SOCKS authentication type for requests without authentication
- METHOD_PASSWD
The SOCKS authentication type for requests via username/password
- SUCCESS
The SOCKS response code for a successful operation.
- VERSION
The SOCKS protocol version used by this class
Attributes
The map of options given at initialization
The proxy's host name or IP address
The proxy's port number
Public Class Methods
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 57 def initialize(proxy_host, proxy_port=1080, options={}) @proxy_host = proxy_host @proxy_port = proxy_port @options = options end
Public Instance Methods
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 65 def open(host, port, connection_options) socket = Socket.tcp(proxy_host, proxy_port, nil, nil, connect_timeout: connection_options[:timeout]) methods = [METHOD_NO_AUTH] methods << METHOD_PASSWD if options[:user] packet = [VERSION, methods.size, *methods].pack("C*") socket.send packet, 0 version, method = socket.recv(2).unpack("CC") if version != VERSION socket.close raise Net::SSH::Proxy::Error, "invalid SOCKS version (#{version})" end if method == METHOD_NONE socket.close raise Net::SSH::Proxy::Error, "no supported authorization methods" end negotiate_password(socket) if method == METHOD_PASSWD packet = [VERSION, CMD_CONNECT, 0].pack("C*") if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ packet << [ATYP_IPV4, $1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*") else packet << [ATYP_DOMAIN, host.length, host].pack("CCA*") end packet << [port].pack("n") socket.send packet, 0 version, reply, = socket.recv(2).unpack("C*") socket.recv(1) address_type = socket.recv(1).getbyte(0) case address_type when 1 socket.recv(4) # get four bytes for IPv4 address when 3 len = socket.recv(1).getbyte(0) hostname = socket.recv(len) when 4 ipv6addr hostname = socket.recv(16) else socket.close raise ConnectError, "Illegal response type" end portnum = socket.recv(2) unless reply == SUCCESS socket.close raise ConnectError, "#{reply}" end return socket end