Created
October 17, 2017 11:47
-
-
Save mikebaldry/44832b02d04f535dc6997e92bd5fb0ae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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