Вот небольшой класс, который вы можете добавить в свой код:
import subprocess
import random
import tempfile
class SSHTunnel:
def __init__(self, host, user, port, key, remote_port):
self.host = host
self.user = user
self.port = port
self.key = key
self.remote_port = remote_port
# Get a temporary file name
tmpfile = tempfile.NamedTemporaryFile()
tmpfile.close()
self.socket = tmpfile.name
self.local_port = random.randint(10000, 65535)
self.local_host = '127.0.0.1'
self.open = False
def start(self):
exit_status = subprocess.call(['ssh', '-MfN',
'-S', self.socket,
'-i', self.key,
'-p', self.port,
'-l', self.user,
'-L', '{}:{}:{}'.format(self.local_port, self.local_host, self.remote_port),
'-o', 'ExitOnForwardFailure=True',
self.host
])
if exit_status != 0:
raise Exception('SSH tunnel failed with status: {}'.format(exit_status))
if self.send_control_command('check') != 0:
raise Exception('SSH tunnel failed to check')
self.open = True
def stop(self):
if self.open:
if self.send_control_command('exit') != 0:
raise Exception('SSH tunnel failed to exit')
self.open = False
def send_control_command(self, cmd):
return subprocess.check_call(['ssh', '-S', self.socket, '-O', cmd, '-l', self.user, self.host])
def __enter__(self):
self.start()
return self
def __exit__(self, type, value, traceback):
self.stop()
А вот как вы можете использовать его, например, с MySQL (обычно порт 3306):
with SSHTunnel('database.server.com', 'you', '22', '/path/to/private_key', '3306') as tunnel:
print "Connected on port {} at {}".format(tunnel.local_port, tunnel.local_host)