Example #1
0
async def open_connection(proxy_url=None, host=None, port=None, *,
                          proxy_type=ProxyType.SOCKS5,
                          proxy_host='127.0.0.1', proxy_port=1080,
                          username=None, password=None, rdns=True,
                          loop=None, **kwargs):
    if host is None or port is None:
        raise ValueError('host and port must be specified')  # pragma: no cover

    if loop is None:
        loop = asyncio.get_event_loop()

    if proxy_url is not None:
        proxy_type, proxy_host, proxy_port, username, password \
            = parse_proxy_url(proxy_url)

    proxy = Proxy.create(
        proxy_type=proxy_type,
        host=proxy_host,
        port=proxy_port,
        username=username,
        password=password,
        rdns=rdns,
        loop=loop
    )

    sock = await proxy.connect(host, port)

    # noinspection PyTypeChecker
    return await asyncio.open_connection(
        host=None,
        port=None,
        sock=sock,
        **kwargs
    )
Example #2
0
    async def _wrap_create_connection(self, protocol_factory, host, port,
                                      **kwargs):
        proxy = Proxy.create(
            proxy_type=self._proxy_type,
            host=self._proxy_host,
            port=self._proxy_port,
            username=self._proxy_username,
            password=self._proxy_password,
            rdns=self._rdns,
            loop=self._loop,
        )

        connect_timeout = None

        timeout = kwargs.get('timeout')
        if timeout is not None:
            connect_timeout = getattr(timeout, 'sock_connect', None)

        sock = await proxy.connect(host, port, timeout=connect_timeout)

        return await super()._wrap_create_connection(protocol_factory,
                                                     None,
                                                     None,
                                                     sock=sock,
                                                     **kwargs)
Example #3
0
    async def _wrap_create_connection(self, protocol_factory, host, port,
                                      **kwargs):
        proxies = []
        for info in self._proxy_infos:
            proxy = Proxy.create(proxy_type=info.proxy_type,
                                 host=info.host,
                                 port=info.port,
                                 username=info.username,
                                 password=info.password,
                                 rdns=info.rdns,
                                 loop=self._loop)
            proxies.append(proxy)

        proxy = ProxyChain(proxies)

        connect_timeout = None

        timeout = kwargs.get('timeout')
        if timeout is not None:
            connect_timeout = getattr(timeout, 'sock_connect', None)

        sock = await proxy.connect(host, port, timeout=connect_timeout)

        return await super()._wrap_create_connection(protocol_factory,
                                                     None,
                                                     None,
                                                     sock=sock,
                                                     **kwargs)
async def test_socks5_proxy_with_invalid_proxy_port(unused_tcp_port):
    proxy = Proxy.create(
        proxy_type=ProxyType.SOCKS5,
        host=SOCKS5_IPV4_HOST,
        port=unused_tcp_port,
        username=LOGIN,
        password=PASSWORD,
    )
    with pytest.raises(ProxyConnectionError):
        await make_request(proxy=proxy, url=TEST_URL)
async def test_socks5_proxy_with_connect_timeout():
    proxy = Proxy.create(
        proxy_type=ProxyType.SOCKS5,
        host=SOCKS5_IPV4_HOST,
        port=SOCKS5_IPV4_PORT,
        username=LOGIN,
        password=PASSWORD,
    )
    with pytest.raises(ProxyTimeoutError):
        await make_request(proxy=proxy, url=TEST_URL, timeout=0.0001)
async def test_socks5_proxy_with_invalid_credentials():
    proxy = Proxy.create(
        proxy_type=ProxyType.SOCKS5,
        host=SOCKS5_IPV4_HOST,
        port=SOCKS5_IPV4_PORT,
        username=LOGIN,
        password=PASSWORD + 'aaa',
    )
    with pytest.raises(ProxyError):
        await make_request(proxy=proxy, url=TEST_URL)
Example #7
0
    async def _proxy_connect(self, timeout=None, local_addr=None):

        # Use `python-socks` library for newer Python >= 3.6
        # Use `PySocks` library for older Python <= 3.5
        if sys.version_info >= (3, 6):

            import python_socks

            # python_socks internal errors are not inherited from
            # builtin IOError (just from Exception). Instead of adding those
            # in exceptions clauses everywhere through the code, we
            # rather monkey-patch them in place.

            python_socks._errors.ProxyError = ConnectionError
            python_socks._errors.ProxyConnectionError = ConnectionError
            python_socks._errors.ProxyTimeoutError = ConnectionError

            from python_socks.async_.asyncio import Proxy

            # We expect a dict/tuple in the format of `PySocks` (for compatibility)
            # I.E.: (proxy_type, addr, port, rdns, username, password).

            if isinstance(self._proxy, (tuple, list)):
                parsed = self._parse_proxy("python-socks", *self._proxy)
            elif isinstance(self._proxy, dict):
                parsed = self._parse_proxy("python-socks", **self._proxy)
            else:
                raise TypeError("Proxy of unknown format!", type(self._proxy))

            proxy = Proxy.create(*parsed)

            # WARNING: If `local_addr` is set we use manual socket creation, because,
            # unfortunately, `Proxy.connect()` does not expose `local_addr`
            # argument, so if we want to bind socket locally, we need to manually
            # create, bind and connect socket, and then pass to `Proxy.connect()` method.

            if local_addr is None:
                sock = await proxy.connect(dest_host=self._ip,
                                           dest_port=self._port,
                                           timeout=timeout)
            else:

                # Here we start manual setup of the socket.
                # The `address` represents the proxy ip and proxy port,
                # not the destination one (!), because the socket
                # connects to the proxy server, not destination server.
                # IPv family is also checked on proxy address.

                if ':' in proxy.proxy_host:
                    mode, address = socket.AF_INET6, (proxy.proxy_host,
                                                      proxy.proxy_port, 0, 0)
                else:
                    mode, address = socket.AF_INET, (proxy.proxy_host,
                                                     proxy.proxy_port)

                # Create a non-blocking socket and bind it (if local address is specified).
                sock = socket.socket(mode, socket.SOCK_STREAM)
                sock.setblocking(False)
                sock.bind(local_addr)

                # Actual TCP connection is performed here.
                await asyncio.wait_for(asyncio.get_event_loop().sock_connect(
                    sock=sock, address=address),
                                       timeout=timeout)

                # As our socket is already created and connected,
                # this call sets the destination host/port and
                # starts protocol negotiations with the proxy server.

                sock = await proxy.connect(dest_host=self._ip,
                                           dest_port=self._port,
                                           timeout=timeout,
                                           _socket=sock)

        else:

            import socks

            # We expect a dict/tuple in the format of `PySocks`.
            # I.E.: (proxy_type, addr, port, rdns, username, password).

            if isinstance(self._proxy, (tuple, list)):
                parsed = self._parse_proxy("pysocks", *self._proxy)
            elif isinstance(self._proxy, dict):
                parsed = self._parse_proxy("pysocks", **self._proxy)
            else:
                raise TypeError("Proxy of unknown format!", type(self._proxy))

            # Here `address` represents destination address (not proxy), because of
            # the `PySocks` implementation of the connection routine.
            # IPv family is checked on proxy address, not destination address.

            if ':' in parsed[1]:
                mode, address = socket.AF_INET6, (self._ip, self._port, 0, 0)
            else:
                mode, address = socket.AF_INET, (self._ip, self._port)

            # Setup socket, proxy, timeout and bind it (if necessary).
            sock = socks.socksocket(mode, socket.SOCK_STREAM)
            sock.set_proxy(*parsed)
            sock.settimeout(timeout)

            if local_addr is not None:
                sock.bind(local_addr)

            # Actual TCP connection and negotiation performed here.
            await asyncio.wait_for(asyncio.get_event_loop().sock_connect(
                sock=sock, address=address),
                                   timeout=timeout)

            sock.setblocking(False)

        return sock