J'essaie de me connecter à une base de données mysql distante en utilisant django.
La documentation indique qu'il est nécessaire d'ouvrir un tunnel SSH en premier pour se connecter à la base de données.
Y at-il une bibliothèque python qui peut ouvrir un tunnel SSH lorsque certains paramètres sont définis?Comment ouvrir un tunnel SSH en utilisant python?
Répondre
Voici un extrait de code pour Python3 (mais vous devriez pouvoir le convertir en Python2 sans difficulté). Il exécute un tunnel SSH dans un thread séparé; alors le thread principal fait quelque chose pour obtenir le trafic réseau sur le tunnel SSH.
Dans cet exemple, le tunnel ssh transfère le port local 2222 vers le port 80 sur localhost. L'activité principale consiste à exécuter
curl http://localhost:2222
ie., Aller chercher une page Web, mais depuis le port 2222.
La SshTunnel de classe est initialisé avec 4 paramètres, le port local et distant, l'utilisateur distant, et la télécommande hôte. Tout ce qu'il fait, est commencer SSH de la manière suivante:
ssh -N -L localport:remotehost:remoteport [email protected]
Pour faire ce travail, vous aurez besoin d'un connexion sans mot de passe pour remoteuser @ remotehost (via ~/.ssh/id_rsa.pub qui est connu sur le serveur distant). Le tunnel ssh en cours d'exécution est sur un thread; la tâche principale doit être dans un autre. Le thread du tunnel ssh est marqué comme démon afin qu'il s'arrête automatiquement une fois l'activité principale terminée.
Je n'ai pas mis dans un exemple complet de connectivité MySQL, car il devrait être explicite. Une fois que SshTunnel a configuré un port TCP local, vous pouvez vous y connecter - que ce soit via votre client MySQL, curl ou autre.
import subprocess
import time
import threading
class SshTunnel(threading.Thread):
def __init__(self, localport, remoteport, remoteuser, remotehost):
threading.Thread.__init__(self)
self.localport = localport # Local port to listen to
self.remoteport = remoteport # Remote port on remotehost
self.remoteuser = remoteuser # Remote user on remotehost
self.remotehost = remotehost # What host do we send traffic to
self.daemon = True # So that thread will exit when
# main non-daemon thread finishes
def run(self):
if subprocess.call([
'ssh', '-N',
'-L', str(self.localport) + ':' + self.remotehost + ':' + str(self.remoteport),
self.remoteuser + '@' + self.remotehost ]):
raise Exception ('ssh tunnel setup failed')
if __name__ == '__main__':
tunnel = SshTunnel(2222, 80, 'karel', 'localhost')
tunnel.start()
time.sleep(1)
subprocess.call(['curl', 'http://localhost:2222'])
Essayez d'utiliser sshtunnel package.
est simple:
pip install sshtunnel
python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
Voici une petite classe que vous pouvez déposer dans votre code:
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()
Et voici comment vous pouvez l'utiliser, par exemple avec MySQL (port 3306 habituellement):
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)
J'ai dû utiliser '-o ExitOnForwardFailure = yes' au lieu de' -o ExitOnForwardFailure = True'. Autre que cela, une petite classe utile. Merci! –
http://stackoverflow.com/questions/953477/ssh-connection-with-python-3-0 –
essayer https://github.com/pahaz/sshtunnel – pahaz