Проблема возникновения SSH-туннелей из python - PullRequest
2 голосов
/ 24 февраля 2010

Цель состоит в том, чтобы настроить n ssh-туннелей между спутниковыми серверами и централизованной базой данных реестра. Я уже настроил аутентификацию с открытым ключом между моими серверами, чтобы они просто входили в систему без запросов пароля. Что теперь ? Я пробовал Парамико. Это выглядит прилично, но становится довольно сложно просто настроить базовый туннель, хотя примеры кода будут оценены по достоинству. Я попробовал Autossh, и он умирает через 2 минуты после настройки рабочего туннеля, странно! Надеюсь, кто-нибудь может помочь мне с простым фрагментом кода, который я могу демонизировать и контролировать с помощью supervisord или monit.

Ответы [ 2 ]

5 голосов
/ 24 февраля 2010

Вот урезанная версия сценария , на которую Алекс указал вам.

Просто подключается к 192.168.0.8 и перенаправляет порт 3389 с 192.168.0.6 на локальный хост

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()
2 голосов
/ 24 февраля 2010

Есть ли особая причина не просто делать это с ssh, обычным

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

менуэт? В любом случае, этот скрипт является примером локальной переадресации портов (туннелирование AKA).

...