async def create_connection(self, protocol_factory, host, port, *, resolve=False, ssl=None, family=0, proto=0, flags=0): '''Set up a connection to (host, port) through the proxy. If resolve is True then host is resolved locally with getaddrinfo using family, proto and flags, otherwise the proxy is asked to resolve host. The function signature is similar to loop.create_connection() with the same result. The attribute _address is set on the protocol to the address of the successful remote connection. Additionally raises SOCKSError if something goes wrong with the proxy handshake. ''' loop = asyncio.get_event_loop() if resolve: remote_addresses = [ NetAddress(info[4][0], info[4][1]) for info in await loop.getaddrinfo(host, port, family=family, proto=proto, type=socket.SOCK_STREAM, flags=flags) ] else: remote_addresses = [NetAddress(host, port)] sock, remote_address = await self._connect(remote_addresses) def set_address(): protocol = protocol_factory() protocol._proxy = self protocol._remote_address = remote_address return protocol return await loop.create_connection( set_address, sock=sock, ssl=ssl, server_hostname=host if ssl else None)
async def _detect_proxy(self): '''Return True if it appears we can connect to a SOCKS proxy, otherwise False. ''' if self.protocol is SOCKS4a: remote_address = NetAddress('www.apple.com', 80) else: remote_address = NetAddress('8.8.8.8', 53) sock = await self._connect_one(remote_address) if isinstance(sock, socket.socket): sock.close() return True # SOCKSFailure indicates something failed, but that we are likely talking to a # proxy return isinstance(sock, SOCKSFailure)
def connection_made(self, transport): '''Called by asyncio when a connection is established.''' self._asyncio_transport = transport # If the Socks proxy was used then _proxy and _remote_address are already set if self._proxy is None: # This would throw if called on a closed SSL transport. Fixed in asyncio in # Python 3.6.1 and 3.5.4 peername = transport.get_extra_info('peername') if peername: self._remote_address = NetAddress(peername[0], peername[1]) self.session = self.session_factory(self) self._framer = self._framer or self.session.default_framer() self._process_messages_task = self.loop.create_task(self.process_messages())
def __init__(self, address, protocol, auth): '''A SOCKS proxy at a NetAddress following a SOCKS protocol. auth is an authentication method to use when connecting, or None. ''' if not isinstance(address, NetAddress): address = NetAddress.from_string(address) self.address = address self.protocol = protocol self.auth = auth # Set on each successful connection via the proxy to the # result of socket.getpeername() self.peername = None
async def auto_detect_at_host(cls, host, ports, auth): '''Try to detect a SOCKS proxy on a host on one of the ports. Calls auto_detect_address for the ports in order. Returning a SOCKSProxy does not mean it is functioning - for example, it may have no network connectivity. If no proxy is detected return None. ''' for port in ports: proxy = await cls.auto_detect_at_address(NetAddress(host, port), auth) if proxy: return proxy return None
def remote_address(self): result = self.websocket.remote_address if result: result = NetAddress(*result[:2]) return result