@@ -7,7 +7,7 @@ __version__ = '0.1.1' | |||
__all__ = ('Socks4Protocol', 'Socks5Protocol', 'Socks4Auth', | |||
'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'SocksError', | |||
'NoAcceptableAuthMethods', 'LoginAuthenticationFailed', | |||
'NoAcceptableAuthMethods', 'LoginAuthenticationFailed', 'SocksConnectionError', | |||
'InvalidServerVersion', 'InvalidServerReply', 'create_connection') | |||
@@ -46,11 +46,19 @@ async def create_connection(protocol_factory, proxy, proxy_auth, dst, *, remote_ | |||
proxy=proxy, proxy_auth=proxy_auth, dst=dst, | |||
remote_resolve=remote_resolve, loop=loop) | |||
transport, protocol = await loop.create_connection( | |||
socks_factory, proxy.host, proxy.port, ssl=ssl, family=family, proto=proto, | |||
flags=flags, sock=sock, local_addr=local_addr, server_hostname=server_hostname) | |||
try: | |||
transport, protocol = await loop.create_connection( | |||
socks_factory, proxy.host, proxy.port, ssl=ssl, family=family, proto=proto, | |||
flags=flags, sock=sock, local_addr=local_addr, server_hostname=server_hostname) | |||
except OSError as exc: | |||
raise SocksConnectionError('[Errno %s] Can not connect to proxy %s:%d [%s]' % | |||
(exc.errno, proxy.host, proxy.port, exc.strerror)) from exc | |||
await protocol.negotiate_done() | |||
try: | |||
await protocol.negotiate_done() | |||
except SocksError as exc: | |||
raise SocksError('Can not connect to %s:%s [%s]' % | |||
(dst[0], dst[1], exc)) | |||
sock = transport.get_extra_info('socket') | |||
@@ -1,4 +1,9 @@ | |||
import socket | |||
import aiohttp | |||
import ipaddress | |||
from aiohttp.errors import ProxyConnectionError | |||
from .errors import SocksError, SocksConnectionError | |||
from . import create_connection | |||
__all__ = ('SocksConnector',) | |||
@@ -46,9 +51,14 @@ class SocksConnector(aiohttp.TCPConnector): | |||
proto=hinfo['proto'], flags=hinfo['flags'], local_addr=self._local_addr) | |||
return transp, proto | |||
except OSError as e: | |||
except (OSError, SocksError, SocksConnectionError) as e: | |||
exc = e | |||
else: | |||
raise aiohttp.ClientOSError(exc.errno, | |||
'Can not connect to %s:%s [%s]' % | |||
(req.host, req.port, exc.strerror)) from exc | |||
if isinstance(exc, SocksConnectionError): | |||
raise ProxyConnectionError(*exc.args) | |||
if isinstance(exc, SocksError): | |||
raise exc | |||
else: | |||
raise aiohttp.ClientOSError(exc.errno, | |||
'Can not connect to %s:%s [%s]' % | |||
(req.host, req.port, exc.strerror)) from exc |
@@ -16,3 +16,7 @@ class InvalidServerVersion(SocksError): | |||
class InvalidServerReply(SocksError): | |||
pass | |||
class SocksConnectionError(OSError): | |||
pass |
@@ -106,7 +106,7 @@ class Socks4Protocol(SocksProtocol): | |||
raise InvalidServerReply('SOCKS4 proxy server sent invalid data') | |||
if resp[1] != c.SOCKS4_GRANTED: | |||
error = c.SOCKS4_ERRORS.get(resp[1], 'Unknown error') | |||
raise SocksError('{0:#04x}: {1}'.format(resp[1], error)) | |||
raise SocksError('[Errno {0:#04x}]: {1}'.format(resp[1], error)) | |||
binded = socket.inet_ntoa(resp[4:]), struct.unpack('>H', resp[2:4])[0] | |||
return (host, port), binded | |||
@@ -138,7 +138,7 @@ class Socks5Protocol(SocksProtocol): | |||
chosen_auth = await self.read_response(2) | |||
if chosen_auth[0] != c.SOCKS_VER5: | |||
raise InvalidServerVersion | |||
raise InvalidServerVersion('SOCKS5 proxy server sent invalid version') | |||
if chosen_auth[1] == c.SOCKS5_AUTH_UNAME_PWD: | |||
req = [0x01, chr(len(self._auth.login)).encode(), self._auth.login, | |||
@@ -149,11 +149,11 @@ class Socks5Protocol(SocksProtocol): | |||
if auth_status[0] != 0x01: | |||
raise InvalidServerReply('SOCKS5 proxy server sent invalid data') | |||
if auth_status[1] != c.SOCKS5_GRANTED: | |||
raise LoginAuthenticationFailed | |||
raise LoginAuthenticationFailed('SOCKS5 authentication failed') | |||
# offered auth methods rejected | |||
elif chosen_auth[1] != c.SOCKS5_AUTH_ANONYMOUS: | |||
if chosen_auth[1] == c.SOCKS5_AUTH_NO_ACCEPTABLE_METHODS: | |||
raise NoAcceptableAuthMethods | |||
raise NoAcceptableAuthMethods('All offered SOCKS5 authentication methods were rejected') | |||
else: | |||
raise InvalidServerReply('SOCKS5 proxy server sent invalid data') | |||
@@ -165,10 +165,10 @@ class Socks5Protocol(SocksProtocol): | |||
resp = await self.read_response(3) | |||
if resp[0] != c.SOCKS_VER5: | |||
raise InvalidServerVersion | |||
raise InvalidServerVersion('SOCKS5 proxy server sent invalid version') | |||
if resp[1] != c.SOCKS5_GRANTED: | |||
error = c.SOCKS5_ERRORS.get(resp[1], 'Unknown error') | |||
raise SocksError('{0:#04x}: {1}'.format(resp[1], error)) | |||
raise SocksError('[Errno {0:#04x}]: {1}'.format(resp[1], error)) | |||
binded = await self.read_address() | |||