Problem originating SSH tunnels from python

2019-03-22 05:47发布

The object is to set up n number of ssh tunnels between satellite servers and a centralized registry database. I have already set up public key authentication between my servers so they just log right in without password prompts. Now what ? I've tried Paramiko. It seems decent but gets pretty complicated just to set up a basic tunnel, although code exmplaes would be aprreciated. I've tried Autossh and it dies 2 minutes after setting up a working tunnel, bizarre! Hopefully someone can help me with a simple code snippet that I can daemonize and monitor with supervisord or monit.

2条回答
迷人小祖宗
2楼-- · 2019-03-22 06:06

Is there a special reason not to just do it with ssh, the usual

(ssh -L <localport>:localhost:<remoteport> <remotehost>)

minuet? Anyway, this script is an example of local port forwarding (AKA tunneling).

查看更多
放荡不羁爱自由
3楼-- · 2019-03-22 06:10

Here is a cutdown version of the script that Alex pointed you to.

It simply connects to 192.168.0.8 and forwards port 3389 from 192.168.0.6 to localhost

import select
import SocketServer
import sys
import paramiko

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:
            print('Incoming request to %s:%d failed: %s' % (self.chain_host, self.chain_port, repr(e)))
            return
        if chan is None:
            print('Incoming request to %s:%d was rejected by the SSH server.' % (self.chain_host, self.chain_port))
            return

        print('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()
        print('Tunnel closed from %r' % (self.request.getpeername(),))

def main():
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.WarningPolicy())
    client.connect("192.168.0.8")

    class SubHandler(Handler):
        chain_host = "192.168.0.6"
        chain_port = 3389
        ssh_transport = client.get_transport()

    try:
        ForwardServer(('', 3389), SubHandler).serve_forever()
    except KeyboardInterrupt:
        sys.exit(0)

if __name__ == '__main__':
    main()
查看更多
登录 后发表回答