Last active
December 11, 2021 12:17
-
-
Save renatoalencar/e6cb120554f1ef80b19f4e9ac71ffdb6 to your computer and use it in GitHub Desktop.
Socks4 and socks5
This file contains hidden or 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
type version = Socks4 | |
type command = Connect | Bind | |
type port = int | |
type request = { version: version | |
; command: command | |
; destport: port | |
; destip: string | |
; userid: string option } | |
let of_bytes bytes = | |
assert (Bytes.length bytes >= 9); | |
let version = | |
match Bytes.get bytes 0 with | |
| '\004' -> Socks4 | |
| _ -> assert false | |
in | |
let command = | |
match Bytes.get bytes 1 with | |
| '\001' -> Connect | |
| '\002' -> Bind | |
| _ -> assert false | |
in | |
let destport = | |
let h = Char.code (Bytes.get bytes 2) in | |
let l = Char.code (Bytes.get bytes 3) in | |
(h lsl 8) lor l | |
in | |
let destip = | |
let parts = [ Bytes.get bytes 4 | |
; Bytes.get bytes 5 | |
; Bytes.get bytes 6 | |
; Bytes.get bytes 7 ] in | |
parts | |
|> List.map Char.code | |
|> List.map string_of_int | |
|> String.concat "." | |
in | |
let userid = | |
let last_byte_index = ref 8 in | |
for i = 8 to (Bytes.length bytes) - 1 do | |
if Bytes.get bytes i = '\000' then | |
last_byte_index := i | |
done; | |
if !last_byte_index = 8 then | |
None | |
else | |
Some (Bytes.to_string (Bytes.sub bytes 8 !last_byte_index)) | |
in | |
{ version | |
; command | |
; destport | |
; destip | |
; userid } | |
let () = | |
let packet = Bytes.of_string "\004\001\000\x50\xc0\xa8\000\001\000" in | |
let req = of_bytes packet in | |
Printf.printf "IP: %s, port: %d, user id: %s\n" req.destip req.destport (Option.value ~default:"No user id" req.userid) |
This file contains hidden or 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
# Almost full working proof of concept in python | |
import socket | |
import codecs | |
def to_hex(b): | |
return codecs.encode(b, 'hex') | |
class Socks4: | |
def make_request_packet_ip(self, destip, destport, command): | |
version = b'\x04' | |
port = bytes([0xff & (destport >> 8), 0xff & destport]) | |
ip = socket.inet_aton(destip) | |
return version + command + port + ip + b'\0' | |
def make_request_packet_domain(self, domain, destport, command): | |
req = self.make_request_packet_ip('0.0.0.1', destport, command) | |
return req + bytes(domain, 'utf-8') + b'\0' | |
def connect(self, s, dest): | |
ip, port = dest | |
try: | |
request = self.make_request_packet_ip(ip, port, b'\1') | |
except OSError: | |
request = self.make_request_packet_domain(ip, port, b'\1') | |
print('Sending ', to_hex(request)) | |
s.send(request) | |
response = s.recv(8) | |
print('Received ', to_hex(response)) | |
assert response[0] == 0 | |
if response[1] == '\90': | |
print('Request granted') | |
elif response[1] == '\91': | |
print('Request rejected or failed') | |
elif response[1] == '\92': | |
printf('Socks cannot connect to identd') | |
elif response[1] == '\93': | |
printf('User id doesnt match') | |
connection = socket.socket() | |
connection.connect(('127.0.0.1', 9050)) | |
socks = Socks4() | |
domain = 'torchdeedp3i2jigzjdmfpn5ttjhthh5wbmda2rr3jvqjg5p77c54dqd.onion' | |
socks.connect(connection, (domain, 80)) | |
connection.send(f'''GET /search?query=socks4 HTTP/1.1\r | |
Host: {domain}\r | |
User-Agent: curl/7.79.1\r | |
Accept: */*\r | |
\r | |
'''.encode('utf-8')) | |
response = connection.recv(4096) | |
print(response.decode('utf-8')) |
This file contains hidden or 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
type version = Socks4 | Socks4a | |
type command = Connect | Bind | |
type port = int | |
type ip_address = int * int * int * int | |
type addr = IPAddress of ip_address | DomainName of string | |
type request = { version: version | |
; command: command | |
; destport: port | |
; destip: addr | |
; userid: string option } | |
let read_null_terminated_string bytes start = | |
let last_byte_index = ref start in | |
for i = start to (Bytes.length bytes) - 1 do | |
if Bytes.get bytes i = '\000' then | |
last_byte_index := i | |
done; | |
if !last_byte_index = start then | |
(String.empty, start + 1) | |
else | |
(Bytes.to_string (Bytes.sub bytes 8 !last_byte_index), !last_byte_index + 1) | |
let of_bytes bytes = | |
assert (Bytes.length bytes >= 9); | |
let command = | |
match Bytes.get bytes 1 with | |
| '\001' -> Connect | |
| '\002' -> Bind | |
| _ -> assert false | |
in | |
let destport = | |
let h = Char.code (Bytes.get bytes 2) in | |
let l = Char.code (Bytes.get bytes 3) in | |
(h lsl 8) lor l | |
in | |
let (userid, last_null_byte) = | |
match read_null_terminated_string bytes 8 with | |
| ("", x) -> (None, x) | |
| (s, x) -> (Some s, x) | |
in | |
let destip = | |
let parts = [ Bytes.get bytes 4 | |
; Bytes.get bytes 5 | |
; Bytes.get bytes 6 | |
; Bytes.get bytes 7 ] | |
|> List.map int_of_char | |
in | |
match parts with | |
| 0 :: 0 :: 0 :: x :: [] when x > 0 -> | |
let (domain_name, _) = | |
read_null_terminated_string bytes last_null_byte | |
in | |
DomainName domain_name | |
| p1 :: p2 :: p3 :: p4 :: [] -> | |
IPAddress (p1, p2, p3, p4) | |
| _ -> assert false | |
in | |
let version = | |
match (destip, Bytes.get bytes 0) with | |
| (IPAddress _, '\004') -> Socks4 | |
| (DomainName _, '\004') -> Socks4a | |
| _ -> assert false | |
in | |
{ version | |
; command | |
; destport | |
; destip | |
; userid } | |
let () = | |
let packet = Bytes.of_string "\004\001\000\x50\xc0\xa8\000\001\000" in | |
let _req = of_bytes packet in | |
() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For matching the response code