class TCPSocket
Constants
- socks_port
- socks_server
Public Class Methods
new(host=nil, port=0, local_host=nil, local_port=nil)
click to toggle source
See tools.ietf.org/html/rfc1928
# File lib/socksify.rb, line 154 def initialize(host=nil, port=0, local_host=nil, local_port=nil) if host.is_a?(SOCKSConnectionPeerAddress) socks_peer = host socks_server = socks_peer.socks_server socks_port = socks_peer.socks_port socks_ignores = [] host = socks_peer.peer_host else socks_server = self.class.socks_server socks_port = self.class.socks_port socks_ignores = self.class.socks_ignores end if socks_server and socks_port and not socks_ignores.include?(host) Socksify::debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}" initialize_tcp socks_server, socks_port socks_authenticate unless @@socks_version =~ /^4/ if host socks_connect(host, port) end else Socksify::debug_notice "Connecting directly to #{host}:#{port}" initialize_tcp host, port, local_host, local_port Socksify::debug_debug "Connected to #{host}:#{port}" end end
Also aliased as: initialize_tcp
socks_ignores()
click to toggle source
# File lib/socksify.rb, line 127 def self.socks_ignores @@socks_ignores ||= %w(localhost) end
socks_ignores=(ignores)
click to toggle source
# File lib/socksify.rb, line 130 def self.socks_ignores=(ignores) @@socks_ignores = ignores end
socks_password()
click to toggle source
# File lib/socksify.rb, line 121 def self.socks_password @@socks_password ||= nil end
socks_password=(password)
click to toggle source
# File lib/socksify.rb, line 124 def self.socks_password=(password) @@socks_password = password end
socks_port()
click to toggle source
# File lib/socksify.rb, line 109 def self.socks_port @@socks_port ||= nil end
socks_port=(port)
click to toggle source
# File lib/socksify.rb, line 112 def self.socks_port=(port) @@socks_port = port end
socks_server()
click to toggle source
# File lib/socksify.rb, line 103 def self.socks_server @@socks_server ||= nil end
socks_server=(host)
click to toggle source
# File lib/socksify.rb, line 106 def self.socks_server=(host) @@socks_server = host end
socks_username()
click to toggle source
# File lib/socksify.rb, line 115 def self.socks_username @@socks_username ||= nil end
socks_username=(username)
click to toggle source
# File lib/socksify.rb, line 118 def self.socks_username=(username) @@socks_username = username end
socks_version()
click to toggle source
# File lib/socksify.rb, line 97 def self.socks_version (@@socks_version == "4a" or @@socks_version == "4") ? "\004" : "\005" end
socks_version=(version)
click to toggle source
# File lib/socksify.rb, line 100 def self.socks_version=(version) @@socks_version = version.to_s end
Public Instance Methods
socks_authenticate()
click to toggle source
Authentication
# File lib/socksify.rb, line 184 def socks_authenticate if self.class.socks_username || self.class.socks_password Socksify::debug_debug "Sending username/password authentication" write "\005\001\002" else Socksify::debug_debug "Sending no authentication" write "\005\001\000" end Socksify::debug_debug "Waiting for authentication reply" auth_reply = recv(2) if auth_reply.empty? raise SOCKSError.new("Server doesn't reply authentication") end if auth_reply[0..0] != "\004" and auth_reply[0..0] != "\005" raise SOCKSError.new("SOCKS version #{auth_reply[0..0]} not supported") end if self.class.socks_username || self.class.socks_password if auth_reply[1..1] != "\002" raise SOCKSError.new("SOCKS authentication method #{auth_reply[1..1]} neither requested nor supported") end auth = "\001" auth += self.class.socks_username.to_s.length.chr auth += self.class.socks_username.to_s auth += self.class.socks_password.to_s.length.chr auth += self.class.socks_password.to_s write auth auth_reply = recv(2) if auth_reply[1..1] != "\000" raise SOCKSError.new("SOCKS authentication failed") end else if auth_reply[1..1] != "\000" raise SOCKSError.new("SOCKS authentication method #{auth_reply[1..1]} neither requested nor supported") end end end
socks_connect(host, port)
click to toggle source
Connect
# File lib/socksify.rb, line 222 def socks_connect(host, port) port = Socket.getservbyname(port) if port.is_a?(String) req = String.new Socksify::debug_debug "Sending destination address" req << TCPSocket.socks_version Socksify::debug_debug TCPSocket.socks_version.unpack "H*" req << "\001" req << "\000" if @@socks_version == "5" req << [port].pack('n') if @@socks_version =~ /^4/ if @@socks_version == "4" host = Resolv::DNS.new.getaddress(host).to_s end Socksify::debug_debug host if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address req << "\001" if @@socks_version == "5" _ip = [$1.to_i, $2.to_i, $3.to_i, $4.to_i ].pack('CCCC') req << _ip elsif host =~ /^[:0-9a-f]+$/ # to IPv6 address raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor" req << "\004" else # to hostname if @@socks_version == "5" req << "\003" + [host.size].pack('C') + host else req << "\000\000\000\001" req << "\007\000" Socksify::debug_notice host req << host req << "\000" end end req << [port].pack('n') if @@socks_version == "5" write req socks_receive_reply Socksify::debug_notice "Connected to #{host}:#{port} over SOCKS" end
socks_receive_reply()
click to toggle source
returns [bind_addr: String, bind_port: Fixnum]
# File lib/socksify.rb, line 266 def socks_receive_reply Socksify::debug_debug "Waiting for SOCKS reply" if @@socks_version == "5" connect_reply = recv(4) if connect_reply.empty? raise SOCKSError.new("Server doesn't reply") end Socksify::debug_debug connect_reply.unpack "H*" if connect_reply[0..0] != "\005" raise SOCKSError.new("SOCKS version #{connect_reply[0..0]} is not 5") end if connect_reply[1..1] != "\000" raise SOCKSError.for_response_code(connect_reply.bytes.to_a[1]) end Socksify::debug_debug "Waiting for bind_addr" bind_addr_len = case connect_reply[3..3] when "\001" 4 when "\003" recv(1).bytes.first when "\004" 16 else raise SOCKSError.for_response_code(connect_reply.bytes.to_a[3]) end bind_addr_s = recv(bind_addr_len) bind_addr = case connect_reply[3..3] when "\001" bind_addr_s.bytes.to_a.join('.') when "\003" bind_addr_s when "\004" # Untested! i = 0 ip6 = "" bind_addr_s.each_byte do |b| if i > 0 and i % 2 == 0 ip6 += ":" end i += 1 ip6 += b.to_s(16).rjust(2, '0') end end bind_port = recv(bind_addr_len + 2) [bind_addr, bind_port.unpack('n')] else connect_reply = recv(8) unless connect_reply[0] == "\000" and connect_reply[1] == "\x5A" Socksify::debug_debug connect_reply.unpack 'H' raise SOCKSError.new("Failed while connecting througth socks") end end end