Пример #1
0
async def resolve(config, request, use_proxy=True):
    config.logger.debug(str(parse_message(request)))
    remote = ExtendedSocket()
    if use_proxy:
        await remote.connect(config.proxy_addr)
        await remote.sendall(b'\x05\x01\x00')
        assert (await remote.ensure_recv(2)) == b'\x05\x00'
        await remote.sendall(b'\x05\x01\x00\x01' +
                             socket.inet_aton(config.remote_addr[0]) +
                             struct.pack("!H", config["remote_addr"][1]))
        kind = (await remote.ensure_recv(4))[3]
        if kind == 1:
            await remote.ensure_recv(4)
        elif kind == 3:
            length = (await remote.ensure_recv(1))[0]
            await remote.ensure_recv(length)
        elif kind == 4:
            await remote.ensure_recv(16)
        else:
            raise ValueError(f'Invalid ADDR type {kind}')
        await remote.ensure_recv(2)
    else:
        await remote.connect(config.direct_addr)
    await remote.sendall(struct.pack(">H", len(request)))
    await remote.sendall(request)
    length = await remote.recv_uint16be()
    resp = await remote.ensure_recv(length)
    config.logger.debug(str(parse_message(resp)))
    return resp
Пример #2
0
def pack_ipv4(addr, userid: bytes = b"\x01\x01") -> bytes:
    host, port = addr
    tail = b""
    try:
        packed = socket.inet_aton(host)
    except OSError:
        packed = b"\x00\x00\x00\x01"
        tail = host.encode() + b"\x00"
    return port.to_bytes(2, "big") + packed + userid + b"\x00" + tail
Пример #3
0
def pack_addr(addr):
    host, port = addr
    try: # IPV4
        packed = b'\x01' + socket.inet_aton(host)
    except OSError:
        try: # IPV6
            packed = b'\x04' + socket.inet_pton(socket.AF_INET6, host)
        except OSError: # hostname
            packed = host.encode('ascii')
            packed = b'\x03' + len(packed).to_bytes(1, 'big') + packed
    return packed + port.to_bytes(2, 'big')
Пример #4
0
def pack_addr(addr):
    host, port = addr
    try:  # IPV4
        packed = b"\x01" + socket.inet_aton(host)
    except OSError:
        try:  # IPV6
            packed = b"\x04" + socket.inet_pton(socket.AF_INET6, host)
        except OSError:  # hostname
            packed = host.encode("ascii")
            packed = b"\x03" + len(packed).to_bytes(1, "big") + packed
    return packed + port.to_bytes(2, "big")
Пример #5
0
def pack_addr(addr):
    host, port = addr
    try:  # IPV4
        packed = b'\x01' + socket.inet_aton(host)
    except OSError:
        try:  # IPV6
            packed = b'\x04' + socket.inet_pton(socket.AF_INET6, host)
        except OSError:  # hostname
            packed = host.encode('ascii')
            packed = b'\x03' + len(packed).to_bytes(1, 'big') + packed
    return packed + port.to_bytes(2, 'big')
Пример #6
0
    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()