forked from shaba/openuds
added tunnel check
This commit is contained in:
parent
7e4975be99
commit
f364b283e6
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Virtual Cable S.L.U.
|
# Copyright (c) 2021 Virtual Cable S.L.U.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -72,8 +72,7 @@ class ForwardServer(socketserver.ThreadingTCPServer):
|
|||||||
check_certificate: bool = True,
|
check_certificate: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if local_port == 0:
|
local_port = local_port or random.randrange(33000, 53000)
|
||||||
local_port = random.randrange(33000, 53000)
|
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
server_address=(LISTEN_ADDRESS, local_port), RequestHandlerClass=Handler
|
server_address=(LISTEN_ADDRESS, local_port), RequestHandlerClass=Handler
|
||||||
@ -104,6 +103,36 @@ class ForwardServer(socketserver.ThreadingTCPServer):
|
|||||||
self.timer = None
|
self.timer = None
|
||||||
self.shutdown()
|
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
|
@property
|
||||||
def stoppable(self) -> bool:
|
def stoppable(self) -> bool:
|
||||||
return self.timeout != 0 and int(time.time()) > self.timeout
|
return self.timeout != 0 and int(time.time()) > self.timeout
|
||||||
@ -132,37 +161,18 @@ class Handler(socketserver.BaseRequestHandler):
|
|||||||
|
|
||||||
# Open remote connection
|
# Open remote connection
|
||||||
try:
|
try:
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket:
|
logger.debug('Ticket %s', self.server.ticket)
|
||||||
logger.info('CONNECT to %s', self.server.remote)
|
with self.server.connect() as ssl_socket:
|
||||||
logger.debug('Ticket %s', self.server.ticket)
|
# 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)
|
# All is fine, now we can tunnel data
|
||||||
|
self.process(remote=ssl_socket)
|
||||||
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)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error connecting to {self.server.remote!s}: {e!s}')
|
logger.error(f'Error connecting to {self.server.remote!s}: {e!s}')
|
||||||
self.server.status = TUNNEL_ERROR
|
self.server.status = TUNNEL_ERROR
|
||||||
|
@ -43,4 +43,8 @@ else:
|
|||||||
# Open tunnel
|
# Open tunnel
|
||||||
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
|
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('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
|
||||||
|
|
||||||
fnc(app, fs.server_address[1])
|
fnc(app, fs.server_address[1])
|
||||||
|
@ -1 +1 @@
|
|||||||
EGqTg6L0Bu5sqIA7BEUJgNzEwlQkPXfmdXLJ4iA+mRmXx6Z7QCXTYmxdqXmalUKUy4P2x3DvYMut5sM1BTWBYs6LxlE1CbuzBxEOw4VQHXDeW10Zir6C92IOevMZctrJS2zBNIB6RMddhD7HFwQ7LQ/yorUCClXUszjhcCxaTkqjM3KdbVuA4a+R9KF6gHHKCnjGrQXHuGdXjYm2+CRBWv5GBN57htO0VBEvCIrq7ZM/NzWDjBLlsrbkyUHxUoX3Tq0vXS03F3Gu3cxCP24yfYZoJeAHF4iOzU9XqomAYHvhNFEl7bvZz3ZyAIieT+zJJ+/WtGLjxL+ek8Va7V1ZYw9bWYnY0YyEkccupfoOXBy+phCJvcT6UgsL2dRO3yJma+GwejZAzv0JuDCvRmXN/xTbuSexyjIN7fLTmwT8q3DCA+m1CXXEQxLv9D1v2rhGPQOhwvomMKNRwZP3fi1zwL9d0FkgRnS36cz6+YLSf1dyXBDWK3Ez0vqJlRmLVz4GmVuidEnQ1pigzL3HLh3X32b9bd4nqCdSAVqP4dDcZsAQuf7JWYF0k7fA91ROT8nNEVg0zyN/YZU2Qxcr16fyVq1aBTTsDuEnKe0x0GruBRgEBU6Fr1i4eirgpcD+FddlLPvGUvgyH2lfotTcub+sL/BcgOaRvG7niiysJGfCxkc=
|
reSq28zy09GuLeWFzfhCRDX8AvYc8SQRBpIE7T7fjiHt1Cb4/KlA2sPaSuSDLI3SCI5vFSfXmm1QHesq/y0sDrs2xnZnz6BiVSXFjBBg4J6BM05QIs41u5deAe1lk/2RziColBt0Nnc75iSuLnHTt4SWYAFpjN7CKR3JcESD2gUZRpPJIfXXfgyfmlnOa1h6TGJBwANOlayV3qGzJv47mi0yw7VATFYcQtxtIqDCQeJI94IcC4PMvAeF/PBmBNfJAy0UArNhPYmnOrE38MkaMQQZkwVOWU1b1NuBjIPigYigcagjX8S75Vk83OniHnBRsW4MyhLJJuBy0+RG0WrBa0jT25Ggm76ORZuMWHTXK3x2ccxA060QMzplVFA4VwU+E9WcZWP0P2M6U9JuhWCogP5J1ufozHgiUUx1B6oC4qoThojNzVQgvgAhg/r/iEpOm13LP3+Yy2Cegiuf2KegPBJnAM8vB/I34YhGL8kDwgu7gWdeJUle1WkDVpndnl+eLRdqV301FBXaCaUZuh2NxA9gmFZjAYiOK0NlO9pLn7ATsqg+e8T+fli6aeIZahtfRCzGTIfYkL+ugxzZg3KnxjSnXPx6BxdeugKHsSGldwkx0iwWe2btlDBu2KO7Tws7FZMwd4nfHc4N4GHR1nWxam88X4R4VCEcUbkTIQJZsew=
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Virtual Cable S.L.U.
|
# Copyright (c) 2021 Virtual Cable S.L.U.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -103,6 +103,36 @@ class ForwardServer(socketserver.ThreadingTCPServer):
|
|||||||
self.timer = None
|
self.timer = None
|
||||||
self.shutdown()
|
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
|
@property
|
||||||
def stoppable(self) -> bool:
|
def stoppable(self) -> bool:
|
||||||
return self.timeout != 0 and int(time.time()) > self.timeout
|
return self.timeout != 0 and int(time.time()) > self.timeout
|
||||||
@ -131,37 +161,18 @@ class Handler(socketserver.BaseRequestHandler):
|
|||||||
|
|
||||||
# Open remote connection
|
# Open remote connection
|
||||||
try:
|
try:
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as rsocket:
|
logger.debug('Ticket %s', self.server.ticket)
|
||||||
logger.info('CONNECT to %s', self.server.remote)
|
with self.server.connect() as ssl_socket:
|
||||||
logger.debug('Ticket %s', self.server.ticket)
|
# 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)
|
# All is fine, now we can tunnel data
|
||||||
|
self.process(remote=ssl_socket)
|
||||||
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)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error connecting to {self.server.remote!s}: {e!s}')
|
logger.error(f'Error connecting to {self.server.remote!s}: {e!s}')
|
||||||
self.server.status = TUNNEL_ERROR
|
self.server.status = TUNNEL_ERROR
|
||||||
@ -249,3 +260,6 @@ if __name__ == "__main__":
|
|||||||
timeout=60,
|
timeout=60,
|
||||||
check_certificate=False,
|
check_certificate=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(fs.check())
|
||||||
|
fs.stop()
|
||||||
|
Loading…
Reference in New Issue
Block a user