Skip to content

Instantly share code, notes, and snippets.

@mikebaldry
Created October 17, 2017 11:47
Show Gist options
  • Save mikebaldry/44832b02d04f535dc6997e92bd5fb0ae to your computer and use it in GitHub Desktop.
Save mikebaldry/44832b02d04f535dc6997e92bd5fb0ae to your computer and use it in GitHub Desktop.
require "bundler"
Bundler.require
require "addressable"
require "socket"
require "ipaddr"
proxy_address = Addressable::URI.parse("socks5://user:password@host:1080")
remote_ip = IPAddr.new(IPSocket::getaddress("icanhazip.com"))
remote_port = 80
socket = TCPSocket.new(proxy_address.host, proxy_address.port)
# version 5, 2 authentication methods, 0 (no auth) and 2 (username and password)
socket << [
5, # SOCKS version 5
2, # we support 2 authentication methods
0, # 1: no authentication
2 # 2: username/password authentication
].pack("CCCC")
version, authentication_method = socket.read(2).unpack("CC")
puts "server version #{version} and auth method chosen #{authentication_method}"
if authentication_method == 0
puts "no auth required"
elsif authentication_method == 2
puts "using username and password from uri"
username = proxy_address.user[0, 255]
password = proxy_address.password[0, 255]
socket << [
1, # authentication version 1
username.size, # size of the username
username, # username
password.size, # size of the password
password # password
].pack("CCA#{username.size}CA#{password.size}")
version, status = socket.read(2).unpack("CC")
if status == 0
puts "authenticated ok"
puts "connecting to #{remote_ip}:#{remote_port}"
socket << [
5, # SOCKS version 5
1, # open a TCP/IP stream
0, # reserved, should be 0
1, # 1 = IPv4
remote_ip.to_i, # 32-bit network order ip address
remote_port # 16-bit network order port number
].pack("CCCCNn")
version, status, _reserved, address_type = socket.read(4).unpack("CCCC")
if status != 0
puts "socks failed to connect"
exit
end
puts "server version #{version}, status: #{status}, address type #{address_type}"
if address_type == 1 # Bound to an IPv4 address
bound_ip_address = IPAddr::new_ntoh(socket.read(4))
puts "server bound to ip: #{bound_ip_address}"
elsif address_type == 0x03 # Bound to a domain name
puts "domain name"
length = socket.read(1).unpack("C").first
bound_hostname = socket.recv(length)
puts "server bound to hostname: #{bound_hostname}"
elsif address_type == 0x04 # Bound to an IPv6 address
puts "ip v6"
socket.recv(16) # can't be bothered to work out how to decode this
end
bound_port = socket.read(2).unpack("n").first
puts "server bound to port: #{bound_port}"
socket << "GET / HTTP/1.1\r\nHost: icanhazip.com\r\n\r\n"
result = ""
while !socket.eof?
result = "#{result}#{socket.gets}"
end
puts "result: #{result}"
else
puts "unknown status returned #{status}"
end
end
socket.close
puts "done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment