2010-12-07 3 views
1

J'essaie de me connecter à un serveur MySql distant depuis mon ordinateur local. Je veux l'exécuter chaque fois que la constante DEBUG est définie sur true.Utilisation de paramiko pour tunnelliser un port MySQL lorsque django démarre

Voici le script:

import select 
import SocketServer 
import sys 
import threading 
import paramiko 

SSH_PORT = 22 
DEFAULT_PORT = 4000 

g_verbose = True 


class ForwardServer (SocketServer.ThreadingTCPServer): 
    daemon_threads = True 
    allow_reuse_address = True 


class Handler (SocketServer.BaseRequestHandler): 

    def handle(self): 
     try: 
      chan = self.ssh_transport.open_channel('direct-tcpip', 
                (self.chain_host, self.chain_port), 
                self.request.getpeername()) 
     except Exception, e: 
      verbose('Incoming request to %s:%d failed: %s' % (self.chain_host, 
                   self.chain_port, 
                   repr(e))) 
      return 
     if chan is None: 
      verbose('Incoming request to %s:%d was rejected by the SSH server.' % 
        (self.chain_host, self.chain_port)) 
      return 

     verbose('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(), 
                  chan.getpeername(), (self.chain_host, self.chain_port))) 
     while True: 
      r, w, x = select.select([self.request, chan], [], []) 
      if self.request in r: 
       data = self.request.recv(1024) 
       if len(data) == 0: 
        break 
       chan.send(data) 
      if chan in r: 
       data = chan.recv(1024) 
       if len(data) == 0: 
        break 
       self.request.send(data) 
     chan.close() 
     self.request.close() 
     verbose('Tunnel closed from %r' % (self.request.getpeername(),)) 


def forward_tunnel(local_port, remote_host, remote_port, transport): 
    # this is a little convoluted, but lets me configure things for the Handler 
    # object. (SocketServer doesn't give Handlers any way to access the outer 
    # server normally.) 
    class SubHander (Handler): 
     chain_host = remote_host 
     chain_port = remote_port 
     ssh_transport = transport 
    ForwardServer(('', local_port), SubHander).serve_forever() 


def verbose(s): 
    if g_verbose: 
     print s 


HELP = """\ 
Set up a forward tunnel across an SSH server, using paramiko. A local port 
(given with -p) is forwarded across an SSH session to an address:port from 
the SSH server. This is similar to the openssh -L option. 
""" 

def forward(): 
    client = paramiko.SSHClient() 
    client.load_system_host_keys() 
    client.set_missing_host_key_policy(paramiko.WarningPolicy()) 

    try: 
     print 'connecting' 

     client.connect('*******', username='***', password='****!') 

     print 'connected' 
    except Exception, e: 
     print '*** Failed to connect to %s:%d: %r' % ('*****', 22, e) 
     sys.exit(1) 

    try: 
     forward_tunnel(3306, '127.0.0.1', 3306, client.get_transport()) 
    except SystemExit: 
     print 'C-c: Port forwarding stopped.' 
     sys.exit(0) 

J'ai deux problèmes ici:
1) Je ne sais pas comment et quand appeler ma fonction avant quand django soulève.
2) Quand j'accède django localement et exécuter le script à partir de la console, je reçois l'exception suivante:

exception happened during processing of request from ('127.0.0.1', 41872) Traceback (most recent call last): File "/usr/lib/python2.6/SocketServer.py", line 558, in process_request_thread self.finish_request(request, client_address) File "/usr/lib/python2.6/SocketServer.py", line 320, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/lib/python2.6/SocketServer.py", line 615, in init self.handle() File "/home/omer/Aptana Studio 3 Workspace/Website/src/ssh_tunnel/tunnel.py", line 51, in handle verbose('Tunnel closed from %r' % (self.request.getpeername(),)) File "", line 1, in getpeername
File "/usr/lib/python2.6/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor

Était-ce une mauvaise idée de commencer?
Dois-je le faire manuellement à chaque fois?

+0

créer la session ssh lorsque vous lancez le serveur à la place. Utilisez un script shell. Regardez l'utilisation de l'authentification par clé hôte ssh. Cela vous permet de connecter le script à la session ssh sans demander de nom d'utilisateur et de mot de passe. – kevpie

+0

@kevpie: Pourquoi ce que j'ai fait est une mauvaise idée? –

+0

Il y a 100 lignes de code pour faire ce que @damir a écrit. Qu'est-ce qui se connecte sur le tunnel à mysql, un client admin, un serveur web développeur? – kevpie

Répondre

2

Je ne pense pas que ce soit une mauvaise idée.

Je ne pense pas que vous ayez besoin de le faire manuellement.

L'exception est un bogue dans l'échantillon de code avant de paramiko. Cela a été adressé par jhalcrow dans la demande de traction ici:

https://github.com/paramiko/paramiko/pull/36

Ce poste a un code pour le faire dans un événement plus façon conduit, par exemple, si vous vouliez l'appeler par des crochets d'événements Web dans votre Code django ou similaires:

Paramiko SSH Tunnel Shutdown Issue

1

Humm, je n'ai pas essayé, mais si vous êtes sur linux, pourriez-vous exécuter

ssh -L 3306:localhost:3306 remote.host.ip 

par appel système python quand DEBUG est réglé?

également si vous êtes sous Windows, essayez mastic avec la redirection de port

+1

Oui, mais cela a quelques problèmes: Premièrement, vous ne pouvez pas fermer la connexion, donc à chaque fois que le serveur termine cette connexion est ouverte pour toujours. Deuxièmement, lorsque vous essayez d'ouvrir à nouveau la connexion, vous obtenez une erreur car le tunnel est déjà ouvert et votre serveur django ne s'exécutera pas. –

+1

Voici la commande python pour faire ce que vous avez suggéré: 'subprocess.call (shlex.split (" ssh -L 3306: 127.0.0.1: 3306 [email protected] "))' –

+0

Est-ce des trucs de production ou voulez-vous être satisfait avec un hack? vous pouvez exécuter cette commande une fois avec def() et placer decorator devant la fonction pour vérifier l'existence de certains /tmp/.lock avant d'exécuter à nouveau le tunnel ssh. Ce que nous faisons dans ma société est de démarrer le tunnel vpn vers l'hôte distant (openvpn) et en fonction des variables d'environnement, nous utilisons différents paramètres. Je peux copier des choses ici si vous voulez – damir

Questions connexes