Class: Net::SSH::Proxy::SOCKS5
- Inherits:
-
Object
- Object
- Net::SSH::Proxy::SOCKS5
- Defined in:
- lib/net/ssh/proxy/socks5.rb
Overview
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
Constant Summary collapse
- VERSION =
The SOCKS protocol version used by this class
5
- METHOD_NO_AUTH =
The SOCKS authentication type for requests without authentication
0
- METHOD_PASSWD =
The SOCKS authentication type for requests via username/password
2
- METHOD_NONE =
The SOCKS authentication type for when there are no supported authentication methods.
0xFF
- CMD_CONNECT =
The SOCKS packet type for requesting a proxy connection.
1
- ATYP_IPV4 =
The SOCKS address type for connections via IP address.
1
- ATYP_DOMAIN =
The SOCKS address type for connections via domain name.
3
- SUCCESS =
The SOCKS response code for a successful operation.
0
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
The map of options given at initialization.
-
#proxy_host ⇒ Object
readonly
The proxy’s host name or IP address.
-
#proxy_port ⇒ Object
readonly
The proxy’s port number.
Instance Method Summary collapse
-
#initialize(proxy_host, proxy_port = 1080, options = {}) ⇒ SOCKS5
constructor
Create a new proxy connection to the given proxy host and port.
-
#open(host, port, connection_options) ⇒ Object
Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated.
Constructor Details
#initialize(proxy_host, proxy_port = 1080, options = {}) ⇒ SOCKS5
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.
55 56 57 58 59 |
# File 'lib/net/ssh/proxy/socks5.rb', line 55 def initialize(proxy_host, proxy_port = 1080, = {}) @proxy_host = proxy_host @proxy_port = proxy_port @options = end |
Instance Attribute Details
#options ⇒ Object (readonly)
The map of options given at initialization
50 51 52 |
# File 'lib/net/ssh/proxy/socks5.rb', line 50 def @options end |
#proxy_host ⇒ Object (readonly)
The proxy’s host name or IP address
44 45 46 |
# File 'lib/net/ssh/proxy/socks5.rb', line 44 def proxy_host @proxy_host end |
#proxy_port ⇒ Object (readonly)
The proxy’s port number
47 48 49 |
# File 'lib/net/ssh/proxy/socks5.rb', line 47 def proxy_port @proxy_port end |
Instance Method Details
#open(host, port, connection_options) ⇒ Object
Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/net/ssh/proxy/socks5.rb', line 63 def open(host, port, ) socket = Socket.tcp(proxy_host, proxy_port, nil, nil, connect_timeout: [:timeout]) methods = [METHOD_NO_AUTH] methods << METHOD_PASSWD if [: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 |