| 54 | return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % (self.cmd, self.atyp, self.addr, self.port, self.username, self.password) |
| 55 | |
| 56 | class Socks5Connection(): |
| 57 | def __init__(self, serv, conn, peer): |
| 58 | self.serv = serv |
| 59 | self.conn = conn |
| 60 | self.peer = peer |
| 61 | |
| 62 | def handle(self): |
| 63 | """Handle socks5 request according to RFC192.""" |
| 64 | try: |
| 65 | # Verify socks version |
| 66 | ver = recvall(self.conn, 1)[0] |
| 67 | if ver != 0x05: |
| 68 | raise IOError('Invalid socks version %i' % ver) |
| 69 | # Choose authentication method |
| 70 | nmethods = recvall(self.conn, 1)[0] |
| 71 | methods = bytearray(recvall(self.conn, nmethods)) |
| 72 | method = None |
| 73 | if 0x02 in methods and self.serv.conf.auth: |
| 74 | method = 0x02 # username/password |
| 75 | elif 0x00 in methods and self.serv.conf.unauth: |
| 76 | method = 0x00 # unauthenticated |
| 77 | if method is None: |
| 78 | raise IOError('No supported authentication method was offered') |
| 79 | # Send response |
| 80 | self.conn.sendall(bytearray([0x05, method])) |
| 81 | # Read authentication (optional) |
| 82 | username = None |
| 83 | password = None |
| 84 | if method == 0x02: |
| 85 | ver = recvall(self.conn, 1)[0] |
| 86 | if ver != 0x01: |
| 87 | raise IOError('Invalid auth packet version %i' % ver) |
| 88 | ulen = recvall(self.conn, 1)[0] |
| 89 | username = str(recvall(self.conn, ulen)) |
| 90 | plen = recvall(self.conn, 1)[0] |
| 91 | password = str(recvall(self.conn, plen)) |
| 92 | # Send authentication response |
| 93 | self.conn.sendall(bytearray([0x01, 0x00])) |
| 94 | |
| 95 | # Read connect request |
| 96 | ver, cmd, _, atyp = recvall(self.conn, 4) |
| 97 | if ver != 0x05: |
| 98 | raise IOError('Invalid socks version %i in connect request' % ver) |
| 99 | if cmd != Command.CONNECT: |
| 100 | raise IOError('Unhandled command %i in connect request' % cmd) |
| 101 | |
| 102 | if atyp == AddressType.IPV4: |
| 103 | addr = recvall(self.conn, 4) |
| 104 | elif atyp == AddressType.DOMAINNAME: |
| 105 | n = recvall(self.conn, 1)[0] |
| 106 | addr = recvall(self.conn, n) |
| 107 | elif atyp == AddressType.IPV6: |
| 108 | addr = recvall(self.conn, 16) |
| 109 | else: |
| 110 | raise IOError('Unknown address type %i' % atyp) |
| 111 | port_hi,port_lo = recvall(self.conn, 2) |
| 112 | port = (port_hi << 8) | port_lo |
| 113 | |