2010-12-06 6 views
4

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?

+0

http://stackoverflow.com/questions/953477/ssh-connection-with-python-3-0 –

+0

essayer https://github.com/pahaz/sshtunnel – pahaz

Répondre

7

Vous pouvez essayer la fonctionnalité forward de paramiko. Pour un aperçu de paramiko, voir here.

+0

Le lien forward.py n'est pas disponible. –

5

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']) 
3

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 
2

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) 
+0

J'ai dû utiliser '-o ExitOnForwardFailure = yes' au lieu de' -o ExitOnForwardFailure = True'. Autre que cela, une petite classe utile. Merci! –

Questions connexes