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
Source
# File lib/net/ssh/proxy/socks5.rb, line 55 def initialize(proxy_host, proxy_port = 1080, options = {}) @proxy_host = proxy_host @proxy_port = proxy_port @options = options end
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.
Public Instance Methods
Source
# File lib/net/ssh/proxy/socks5.rb, line 63 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
Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated.
Private Instance Methods
Source
# File lib/net/ssh/proxy/socks5.rb, line 125 def negotiate_password(socket) packet = [0x01, options[:user].length, options[:user], options[:password].length, options[:password]].pack("CCA*CA*") socket.send packet, 0 version, status = socket.recv(2).unpack("CC") if status != SUCCESS socket.close raise UnauthorizedError, "could not authorize user" end end
Simple username/password negotiation with the SOCKS5
server.