async def _run(self): try: buf = self.client._socket.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16) port, host = struct.unpack("!2xH4s8x", buf) self.target_addr = (socket.inet_ntoa(host), port) except Exception: gvars.logger.exception(f"{self} isn't a redirect proxy") via_client = await self.connect_server(self.target_addr) async with via_client: await self.relay(via_client)
async def __call__(self, client, addr): SO_ORIGINAL_DST = 80 try: buf = client._socket.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16) port, host = struct.unpack('!2xH4s8x', buf) self.taddr = (socket.inet_ntoa(host), port) except Exception as e: if verbose > 0: print("It seems not been a proxy connection:", e, 'bye.') await client.close() return return (await super().__call__(client, addr))
async def __call__(self, client, addr): try: buf = client._socket.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16) port, host = struct.unpack("!2xH4s8x", buf) self.taddr = (socket.inet_ntoa(host), port) except Exception as e: if verbose > 0: print(f"{self} error: {e}") print("--> It is not a redirect proxy connection") await client.close() return return await super().__call__(client, addr)
async def read_addr(self, atyp): if atyp == 1: # IPV4 data = await self._stream.read_exactly(4) host = socket.inet_ntoa(data) elif atyp == 4: # IPV6 data = await self._stream.read_exactly(16) host = socket.inet_ntop(socket.AF_INET6, data) elif atyp == 3: # hostname data = (await self._stream.read_exactly(1)) data += await self._stream.read_exactly(data[0]) host = data[1:].decode('ascii') else: raise Exception(f'unknow atyp: {atyp}') from None data_port = await self._stream.read_exactly(2) port = int.from_bytes(data_port, 'big') return host, port, atyp.to_bytes(1, 'big') + data + data_port
async def read_addr(self): atyp = await self.read_exactly(1) if atyp == b'\x01': # IPV4 ipv4 = await self.read_exactly(4) host = socket.inet_ntoa(ipv4) elif atyp == b'\x04': # IPV6 ipv6 = await self.read_exactly(16) host = socket.inet_ntop(socket.AF_INET6, ipv6) elif atyp == b'\x03': # hostname length = (await self.read_exactly(1))[0] hostname = await self.read_exactly(length) host = hostname.decode('ascii') else: raise Exception(f'unknow atyp: {atyp}') from None port = int.from_bytes((await self.read_exactly(2)), 'big') return (host, port)
async def read_addr(self): atyp = await self._stream.read_exactly(1) if atyp == b"\x01": # IPV4 data = await self._stream.read_exactly(4) host = socket.inet_ntoa(data) elif atyp == b"\x04": # IPV6 data = await self._stream.read_exactly(16) host = socket.inet_ntop(socket.AF_INET6, data) elif atyp == b"\x03": # hostname data = await self._stream.read_exactly(1) data += await self._stream.read_exactly(data[0]) host = data[1:].decode("ascii") else: raise Exception(f"unknow atyp: {atyp}") data_port = await self._stream.read_exactly(2) port = int.from_bytes(data_port, "big") return (host, port), atyp + data + data_port
async def read_addr(self): atyp = await self._stream.read_exactly(1) if atyp == b'\x01': # IPV4 data = await self._stream.read_exactly(4) host = socket.inet_ntoa(data) elif atyp == b'\x04': # IPV6 data = await self._stream.read_exactly(16) host = socket.inet_ntop(socket.AF_INET6, data) elif atyp == b'\x03': # hostname data = await self._stream.read_exactly(1) data += await self._stream.read_exactly(data[0]) host = data[1:].decode('ascii') else: raise Exception(f'unknow atyp: {atyp}') from None data_port = await self._stream.read_exactly(2) port = int.from_bytes(data_port, 'big') return (host, port), atyp + data + data_port
def unpack_addr(data, start=0): atyp = data[start] if atyp == 1: # IPV4 end = start + 5 ipv4 = data[start+1:end] host = socket.inet_ntoa(ipv4) elif atyp == 4: # IPV6 end = start + 17 ipv6 = data[start:end] host = socket.inet_ntop(socket.AF_INET6, ipv6) elif atyp == 3: # hostname length = data[start+1] end = start + 2 + length host = data[start+2:end].decode('ascii') else: raise Exception(f'unknow atyp: {atyp}') from None port = int.from_bytes(data[end:end+2], 'big') return (host, port), data[end+2:]
def unpack_addr(data, start=0): atyp = data[start] if atyp == 1: # IPV4 end = start + 5 ipv4 = data[start + 1:end] host = socket.inet_ntoa(ipv4) elif atyp == 4: # IPV6 end = start + 17 ipv6 = data[start:end] host = socket.inet_ntop(socket.AF_INET6, ipv6) elif atyp == 3: # hostname length = data[start + 1] end = start + 2 + length host = data[start + 2:end].decode("ascii") else: raise Exception(f"unknow atyp: {atyp}") port = int.from_bytes(data[end:end + 2], "big") return (host, port), data[end + 2:]
async def handle(self, conn, addr): logging.info(f'Accepting connection from {addr}') # greeting header # read and unpack 2 bytes from a client header = await conn.recv(2) version, nmethods = struct.unpack("!BB", header) # socks 5 assert version == SOCKS_VERSION assert nmethods > 0 # get available methods methods = await self.get_available_methods(conn, nmethods) # accept only USERNAME/PASSWORD auth if 2 not in set(methods): # close connection conn.close() return # send welcome message await conn.sendall(struct.pack("!BB", SOCKS_VERSION, 2)) if not await self.verify_credentials(conn): return # request version, cmd, _, address_type = struct.unpack("!BBBB", await conn.recv(4)) assert version == SOCKS_VERSION if address_type == 1: # IPv4 address = socket.inet_ntoa(await conn.recv(4)) elif address_type == 3: # Domain name domain_length = ord(await conn.recv(1)) address = await conn.recv(domain_length) port = struct.unpack('!H', await conn.recv(2))[0] # reply try: if cmd == 1: # CONNECT remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if self.eip != '0.0.0.0': remote.bind((self.eip, 0)) await remote.connect((address, port)) bind_address = remote.getsockname() logging.info(f'Connected to {(address, port)}') else: conn.close() return addr = struct.unpack("!I", socket.inet_aton(bind_address[0]))[0] port = bind_address[1] reply = struct.pack("!BBBBIH", SOCKS_VERSION, 0, 0, 1, addr, port) except Exception as err: logging.error(err) # return connection refused error reply = self.generate_failed_reply(address_type, 5) await conn.sendall(reply) # establish data exchange if reply[1] == 0 and cmd == 1: job1 = await spawn(self.forward_tcp, conn, remote) job2 = await spawn(self.forward_tcp, remote, conn) await job1.join() await job2.join() await conn.close()
def get_origin_dst(ancdata): for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVORIGDSTADDR: family, port, ip = struct.unpack("!HH4s8x", cmsg_data) return (socket.inet_ntoa(ip), port)