|
25 | 25 | class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass |
26 | 26 | class Socks5Server(SocketServer.StreamRequestHandler): |
27 | 27 | def handle_tcp(self, sock, remote): |
28 | | - fdset = [sock, remote] |
29 | | - self.marked = False |
30 | | - self.sent = False |
31 | | - self.reqtype = None |
32 | | - self.cbuf = None |
33 | | - |
| 28 | + fdset = [sock, remote] |
| 29 | + self.marked = False |
| 30 | + self.sent = False |
| 31 | + self.reqtype = None |
| 32 | + self.cbuf = None |
| 33 | + |
34 | 34 | # Basic Loop for contents passing. |
35 | | - while True: |
36 | | - r, w, e = select.select(fdset, [], []) |
37 | | - if sock in r: |
38 | | - buf = sock.recv(4096) |
39 | | - if not self.marked: |
40 | | - # 1st packet marking |
41 | | - self.marked = True |
42 | | - if len(buf) == 0: |
43 | | - break |
44 | | - if buf[0] == '\x16': |
45 | | - # TLS start |
46 | | - p = min(len(buf) / 5, 100) # Tricky Code. split by specific size or split by some... |
47 | | - self.sent = True |
48 | | - remote.send(buf[:p]) |
49 | | - if remote.send(buf[p:]) <= 0: break |
50 | | - elif buf[0].lower() >= ord('a') or buf[0].lower() <= ord('z'): |
51 | | - # Generic HTTP? |
52 | | - lp = buf.lower().find("host:") |
53 | | - if lp != -1: |
54 | | - self.sent = True |
55 | | - remote.send(buf[:lp+4]) |
56 | | - if remote.send(buf[lp+4:]) <= 0: break |
57 | | - if not self.sent: |
58 | | - self.sent = True |
59 | | - if remote.send(buf) <= 0: break |
60 | | - else: |
61 | | - if remote.send(buf) <= 0: break |
62 | | - |
63 | | - if remote in r: |
64 | | - buf = remote.recv(4096) |
65 | | - # no filtering |
| 35 | + while True: |
| 36 | + r, w, e = select.select(fdset, [], []) |
| 37 | + if sock in r: |
| 38 | + buf = sock.recv(4096) |
| 39 | + if not self.marked: |
| 40 | + # 1st packet marking |
| 41 | + self.marked = True |
| 42 | + if len(buf) == 0: |
| 43 | + break |
| 44 | + if buf[0] == '\x16': |
| 45 | + # TLS start |
| 46 | + p = min(len(buf) / 5, 100) # Tricky Code. split by specific size or split by some... |
| 47 | + self.sent = True |
| 48 | + remote.send(buf[:p]) |
| 49 | + if remote.send(buf[p:]) <= 0: break |
| 50 | + elif buf[0].lower() >= ord('a') or buf[0].lower() <= ord('z'): |
| 51 | + # Generic HTTP? |
| 52 | + lp = buf.lower().find("host:") |
| 53 | + if lp != -1: |
| 54 | + self.sent = True |
| 55 | + remote.send(buf[:lp+4]) |
| 56 | + if remote.send(buf[lp+4:]) <= 0: break |
| 57 | + if not self.sent: |
| 58 | + self.sent = True |
| 59 | + if remote.send(buf) <= 0: break |
| 60 | + elif remote.send(buf) <= 0: break |
| 61 | + if remote in r: |
| 62 | + buf = remote.recv(4096) |
| 63 | + # no filtering |
66 | 64 |
|
67 | | - if not buf: break |
68 | | - if sock.send(buf) <= 0: break |
| 65 | + if not buf: break |
| 66 | + if sock.send(buf) <= 0: break |
69 | 67 | def handle(self): |
70 | | - addr = "" |
| 68 | + addr = "" |
| 69 | + try: |
| 70 | + #>> 'socks connection from ', self.client_address |
| 71 | + sock = self.connection |
| 72 | + # 1. Version |
| 73 | + sock.recv(262) |
| 74 | + sock.send(b"\x05\x00"); |
| 75 | + # 2. Request |
| 76 | + data = self.rfile.read(4) |
| 77 | + print(">> LEN:",len(data)) |
| 78 | + hexdump.hexdump(data) |
| 79 | + if len(data) < 4: |
| 80 | + return |
| 81 | + mode = data[1] |
| 82 | + addrtype = data[3] |
| 83 | + print("> mode:", mode, " / addrtype:", addrtype) |
| 84 | + if addrtype == 1: # IPv4 |
| 85 | + addr = socket.inet_ntop(socket.AF_INET, self.rfile.read(4)) |
| 86 | + elif addrtype == 3: # Domain name |
| 87 | + addr = self.rfile.read(ord(sock.recv(1)[0])) |
| 88 | + elif addrtype == 4: # IPv6 |
| 89 | + addr = socket.inet_ntop(socket.AF_INET6, self.rfile.read(16)) |
| 90 | + print("-> IPv6:", addr) |
| 91 | + port = struct.unpack('>H', self.rfile.read(2)) |
| 92 | + reply = b"\x05\x00\x00\x01" |
71 | 93 | try: |
72 | | - #>> 'socks connection from ', self.client_address |
73 | | - sock = self.connection |
74 | | - # 1. Version |
75 | | - sock.recv(262) |
76 | | - sock.send(b"\x05\x00"); |
77 | | - # 2. Request |
78 | | - data = self.rfile.read(4) |
79 | | - print(">> LEN:",len(data)) |
80 | | - hexdump.hexdump(data) |
81 | | - if len(data) < 4: |
82 | | - return |
83 | | - mode = data[1] |
84 | | - addrtype = data[3] |
85 | | - print("> mode:", data[1]," / addrtype:", data[3]) |
86 | | - if addrtype == 1: # IPv4 |
87 | | - addr = socket.inet_ntop(socket.AF_INET, self.rfile.read(4)) |
88 | | - elif addrtype == 3: # Domain name |
89 | | - addr = self.rfile.read(ord(sock.recv(1)[0])) |
90 | | - elif addrtype == 4: # IPv6 |
91 | | - addr = socket.inet_ntop(socket.AF_INET6, self.rfile.read(16)) |
92 | | - print("-> IPv6:", addr) |
93 | | - port = struct.unpack('>H', self.rfile.read(2)) |
94 | | - reply = b"\x05\x00\x00\x01" |
95 | | - try: |
96 | | - if mode == 1: # 1. Tcp connect |
97 | | - self.addr = addr |
98 | | - self.port = port[0] |
99 | | - remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
100 | | - remote.connect((addr, port[0])) |
101 | | - print(">> 'Tcp connect to'", addr,":", port[0]) |
102 | | - else: |
103 | | - reply = b"\x05\x07\x00\x01" # Command not supported |
104 | | - local = remote.getsockname() |
105 | | - reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1]) |
106 | | - except socket.error: |
107 | | - # Connection refused |
108 | | - reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' |
109 | | - sock.send(reply) |
110 | | - # 3. Transfering |
111 | | - if reply[1] == '\x00': # Success |
112 | | - if mode == 1: # 1. Tcp connect |
113 | | - self.handle_tcp(sock, remote) |
| 94 | + if mode == 1: # 1. Tcp connect |
| 95 | + self.addr = addr |
| 96 | + self.port = port[0] |
| 97 | + remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 98 | + remote.connect((addr, port[0])) |
| 99 | + print(">> 'Tcp connect to'", addr,":", port[0]) |
| 100 | + else: |
| 101 | + reply = b"\x05\x07\x00\x01" # Command not supported |
| 102 | + local = remote.getsockname() |
| 103 | + reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1]) |
114 | 104 | except socket.error: |
115 | | - pass |
| 105 | + # Connection refused |
| 106 | + reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' |
| 107 | + sock.send(reply) |
| 108 | + # 3. Transfering |
| 109 | + if reply[1] == '\x00' and mode == 1: # 1. Tcp connect |
| 110 | + self.handle_tcp(sock, remote) |
| 111 | + except socket.error: |
| 112 | + pass |
116 | 113 | #print 'socket error' |
117 | 114 | def main(): |
118 | 115 | server = ThreadingTCPServer(('', 18080), Socks5Server) |
|
0 commit comments