From f364b283e68e40e747674f3b99c111e6b8554a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Mon, 18 Jan 2021 06:45:50 +0100 Subject: [PATCH] added tunnel check --- client-py3/full/src/uds/tunnel.py | 76 +++++++++++-------- .../transports/RDP/scripts/linux/tunnel.py | 4 + .../RDP/scripts/linux/tunnel.py.signature | 2 +- tunnel-server/src/forwarder/udstunnel.py | 76 +++++++++++-------- 4 files changed, 93 insertions(+), 65 deletions(-) diff --git a/client-py3/full/src/uds/tunnel.py b/client-py3/full/src/uds/tunnel.py index 31ed1eaf..086679bc 100644 --- a/client-py3/full/src/uds/tunnel.py +++ b/client-py3/full/src/uds/tunnel.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2020 Virtual Cable S.L.U. +# Copyright (c) 2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -72,8 +72,7 @@ class ForwardServer(socketserver.ThreadingTCPServer): check_certificate: bool = True, ) -> None: - if local_port == 0: - local_port = random.randrange(33000, 53000) + local_port = local_port or random.randrange(33000, 53000) super().__init__( server_address=(LISTEN_ADDRESS, local_port), RequestHandlerClass=Handler @@ -104,6 +103,36 @@ class ForwardServer(socketserver.ThreadingTCPServer): self.timer = None self.shutdown() + def connect(self) -> ssl.SSLSocket: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket: + logger.info('CONNECT to %s', self.remote) + + rsocket.connect(self.remote) + + context = ssl.create_default_context() + + # If ignore remote certificate + if self.check_certificate is False: + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + logger.warning('Certificate checking is disabled!') + + return context.wrap_socket(rsocket, server_hostname=self.remote[0]) + + def check(self) -> bool: + try: + with self.connect() as ssl_socket: + ssl_socket.sendall(HANDSHAKE_V1 + b'TEST') + resp = ssl_socket.recv(2) + if resp != b'OK': + raise Exception({'Invalid tunnelresponse: {resp}'}) + return True + except Exception as e: + logger.error( + 'Error connecting to tunnel server %s: %s', self.server_address, e + ) + return False + @property def stoppable(self) -> bool: return self.timeout != 0 and int(time.time()) > self.timeout @@ -132,37 +161,18 @@ class Handler(socketserver.BaseRequestHandler): # Open remote connection try: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket: - logger.info('CONNECT to %s', self.server.remote) - logger.debug('Ticket %s', self.server.ticket) + logger.debug('Ticket %s', self.server.ticket) + with self.server.connect() as ssl_socket: + # Send handhshake + command + ticket + ssl_socket.sendall(HANDSHAKE_V1 + b'OPEN' + self.server.ticket.encode()) + # Check response is OK + data = ssl_socket.recv(2) + if data != b'OK': + data += ssl_socket.recv(128) + raise Exception(f'Error received: {data.decode(errors="ignore")}') # Notify error - rsocket.connect(self.server.remote) - - context = ssl.create_default_context() - - # If ignore remote certificate - if self.server.check_certificate is False: - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - logger.warning('Certificate checking is disabled!') - - with context.wrap_socket( - rsocket, server_hostname=self.server.remote[0] - ) as ssl_socket: - # Send handhshake + command + ticket - ssl_socket.sendall( - HANDSHAKE_V1 + b'OPEN' + self.server.ticket.encode() - ) - # Check response is OK - data = ssl_socket.recv(2) - if data != b'OK': - data += ssl_socket.recv(128) - raise Exception( - f'Error received: {data.decode()}' - ) # Notify error - - # All is fine, now we can tunnel data - self.process(remote=ssl_socket) + # All is fine, now we can tunnel data + self.process(remote=ssl_socket) except Exception as e: logger.error(f'Error connecting to {self.server.remote!s}: {e!s}') self.server.status = TUNNEL_ERROR diff --git a/server/src/uds/transports/RDP/scripts/linux/tunnel.py b/server/src/uds/transports/RDP/scripts/linux/tunnel.py index 7c2a885b..2cd56623 100644 --- a/server/src/uds/transports/RDP/scripts/linux/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/linux/tunnel.py @@ -43,4 +43,8 @@ else: # Open tunnel fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) + # Check that tunnel works.. + if fs.check() is False: + raise Exception('

Could not connect to tunnel server.

Please, check your network settings.

') + fnc(app, fs.server_address[1]) diff --git a/server/src/uds/transports/RDP/scripts/linux/tunnel.py.signature b/server/src/uds/transports/RDP/scripts/linux/tunnel.py.signature index a5ee4992..98f4fe97 100644 --- a/server/src/uds/transports/RDP/scripts/linux/tunnel.py.signature +++ b/server/src/uds/transports/RDP/scripts/linux/tunnel.py.signature @@ -1 +1 @@ -EGqTg6L0Bu5sqIA7BEUJgNzEwlQkPXfmdXLJ4iA+mRmXx6Z7QCXTYmxdqXmalUKUy4P2x3DvYMut5sM1BTWBYs6LxlE1CbuzBxEOw4VQHXDeW10Zir6C92IOevMZctrJS2zBNIB6RMddhD7HFwQ7LQ/yorUCClXUszjhcCxaTkqjM3KdbVuA4a+R9KF6gHHKCnjGrQXHuGdXjYm2+CRBWv5GBN57htO0VBEvCIrq7ZM/NzWDjBLlsrbkyUHxUoX3Tq0vXS03F3Gu3cxCP24yfYZoJeAHF4iOzU9XqomAYHvhNFEl7bvZz3ZyAIieT+zJJ+/WtGLjxL+ek8Va7V1ZYw9bWYnY0YyEkccupfoOXBy+phCJvcT6UgsL2dRO3yJma+GwejZAzv0JuDCvRmXN/xTbuSexyjIN7fLTmwT8q3DCA+m1CXXEQxLv9D1v2rhGPQOhwvomMKNRwZP3fi1zwL9d0FkgRnS36cz6+YLSf1dyXBDWK3Ez0vqJlRmLVz4GmVuidEnQ1pigzL3HLh3X32b9bd4nqCdSAVqP4dDcZsAQuf7JWYF0k7fA91ROT8nNEVg0zyN/YZU2Qxcr16fyVq1aBTTsDuEnKe0x0GruBRgEBU6Fr1i4eirgpcD+FddlLPvGUvgyH2lfotTcub+sL/BcgOaRvG7niiysJGfCxkc= \ No newline at end of file +reSq28zy09GuLeWFzfhCRDX8AvYc8SQRBpIE7T7fjiHt1Cb4/KlA2sPaSuSDLI3SCI5vFSfXmm1QHesq/y0sDrs2xnZnz6BiVSXFjBBg4J6BM05QIs41u5deAe1lk/2RziColBt0Nnc75iSuLnHTt4SWYAFpjN7CKR3JcESD2gUZRpPJIfXXfgyfmlnOa1h6TGJBwANOlayV3qGzJv47mi0yw7VATFYcQtxtIqDCQeJI94IcC4PMvAeF/PBmBNfJAy0UArNhPYmnOrE38MkaMQQZkwVOWU1b1NuBjIPigYigcagjX8S75Vk83OniHnBRsW4MyhLJJuBy0+RG0WrBa0jT25Ggm76ORZuMWHTXK3x2ccxA060QMzplVFA4VwU+E9WcZWP0P2M6U9JuhWCogP5J1ufozHgiUUx1B6oC4qoThojNzVQgvgAhg/r/iEpOm13LP3+Yy2Cegiuf2KegPBJnAM8vB/I34YhGL8kDwgu7gWdeJUle1WkDVpndnl+eLRdqV301FBXaCaUZuh2NxA9gmFZjAYiOK0NlO9pLn7ATsqg+e8T+fli6aeIZahtfRCzGTIfYkL+ugxzZg3KnxjSnXPx6BxdeugKHsSGldwkx0iwWe2btlDBu2KO7Tws7FZMwd4nfHc4N4GHR1nWxam88X4R4VCEcUbkTIQJZsew= \ No newline at end of file diff --git a/tunnel-server/src/forwarder/udstunnel.py b/tunnel-server/src/forwarder/udstunnel.py index eaebe47c..452bfb0b 100644 --- a/tunnel-server/src/forwarder/udstunnel.py +++ b/tunnel-server/src/forwarder/udstunnel.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2020 Virtual Cable S.L.U. +# Copyright (c) 2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -103,6 +103,36 @@ class ForwardServer(socketserver.ThreadingTCPServer): self.timer = None self.shutdown() + def connect(self) -> ssl.SSLSocket: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket: + logger.info('CONNECT to %s', self.remote) + + rsocket.connect(self.remote) + + context = ssl.create_default_context() + + # If ignore remote certificate + if self.check_certificate is False: + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + logger.warning('Certificate checking is disabled!') + + return context.wrap_socket(rsocket, server_hostname=self.remote[0]) + + def check(self) -> bool: + try: + with self.connect() as ssl_socket: + ssl_socket.sendall(HANDSHAKE_V1 + b'TEST') + resp = ssl_socket.recv(2) + if resp != b'OK': + raise Exception({'Invalid tunnelresponse: {resp}'}) + return True + except Exception as e: + logger.error( + 'Error connecting to tunnel server %s: %s', self.server_address, e + ) + return False + @property def stoppable(self) -> bool: return self.timeout != 0 and int(time.time()) > self.timeout @@ -131,37 +161,18 @@ class Handler(socketserver.BaseRequestHandler): # Open remote connection try: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket: - logger.info('CONNECT to %s', self.server.remote) - logger.debug('Ticket %s', self.server.ticket) + logger.debug('Ticket %s', self.server.ticket) + with self.server.connect() as ssl_socket: + # Send handhshake + command + ticket + ssl_socket.sendall(HANDSHAKE_V1 + b'OPEN' + self.server.ticket.encode()) + # Check response is OK + data = ssl_socket.recv(2) + if data != b'OK': + data += ssl_socket.recv(128) + raise Exception(f'Error received: {data.decode(errors="ignore")}') # Notify error - rsocket.connect(self.server.remote) - - context = ssl.create_default_context() - - # If ignore remote certificate - if self.server.check_certificate is False: - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - logger.warning('Certificate checking is disabled!') - - with context.wrap_socket( - rsocket, server_hostname=self.server.remote[0] - ) as ssl_socket: - # Send handhshake + command + ticket - ssl_socket.sendall( - HANDSHAKE_V1 + b'OPEN' + self.server.ticket.encode() - ) - # Check response is OK - data = ssl_socket.recv(2) - if data != b'OK': - data += ssl_socket.recv(128) - raise Exception( - f'Error received: {data.decode()}' - ) # Notify error - - # All is fine, now we can tunnel data - self.process(remote=ssl_socket) + # All is fine, now we can tunnel data + self.process(remote=ssl_socket) except Exception as e: logger.error(f'Error connecting to {self.server.remote!s}: {e!s}') self.server.status = TUNNEL_ERROR @@ -249,3 +260,6 @@ if __name__ == "__main__": timeout=60, check_certificate=False, ) + + print(fs.check()) + fs.stop()