Skip to content

Instantly share code, notes, and snippets.

@shurikk
Created April 26, 2014 03:22
Show Gist options
  • Save shurikk/11310927 to your computer and use it in GitHub Desktop.
Save shurikk/11310927 to your computer and use it in GitHub Desktop.
TCPSocket proxy monkey patch
# Usage:
#
# TCPSocket.socks_server = "socks-proxy.example.net"
# TCPSocket.socks_port = 8888
require 'socket'
class TCPSocket
alias :direct_to :initialize
class << self
attr_accessor :socks_server, :socks_port
end
def initialize(host, port, local_host = nil, local_port = nil)
socks_server = self.class.socks_server
socks_port = self.class.socks_port
if socks_server && socks_port
direct socks_server, socks_port
authenticate
proxy_to(host, port)
else
direct_to host, port, local_host, local_port
end
end
def authenticate
# no authentication
write "\005\001\000"
recv(2)
end
def proxy_to(host, port)
["\005", "\001", "\000"].map {|b| write b }
if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
write "\001"
write [$1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("CCCC")
elsif host =~ /^[:0-9a-f]+$/
raise "TCP/IPv6 is not supported via SOCKS"
else
write "\003" + [host.size].pack("C") + host
end
write [port].pack('n')
receive_via_proxy
end
def receive_via_proxy
reply = recv(4)
raise "SOCKS version #{reply[0..0]} is not supported" if reply[0..0] != "\005"
raise "SOCKS error: #{reply.bytes.to_a.inspect}" if reply[1..1] != "\000"
bind_addr_len = case reply[3..3]
when "\001"
4
when "\003"
recv(1).bytes.first
when "\004"
16
else
raise "SOCKS error: #{reply.bytes.to_a.inspect}"
end
bind_addr_s = recv(bind_addr_len)
bind_addr = case reply[3..3]
when "\001"
bind_addr_s.bytes.to_a.join(".")
when "\003"
bind_addr_s
end
[bind_addr, recv(bind_addr_len + 2).unpack("n")]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment