30

我需要创建隧道以从数据库中读取信息。我使用 Paramiko,但我还没有使用过隧道。请提供一个创建和关闭隧道的简单代码示例。

4

5 回答 5

15

在工作中,我们通常会创建 ssh 隧道转发端口。我们这样做的方式是,使用标准命令ssh -L port:addr:port addr和在单独线程中运行的子进程。我发现了这个有用的链接:https ://github.com/paramiko/paramiko/blob/master/demos/forward.py ,其中有一个使用 paramiko 进行端口转发的示例。

于 2011-11-17T18:47:27.507 回答
14

我用于sshtunnel我的项目。将远程本地 MySQL 端口转发到主机本地端口的示例:

pip install sshtunnel
python -m sshtunnel -U root -P password -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
于 2015-06-17T20:23:09.290 回答
9

即使这不使用 paramiko,我相信这是一个非常干净的实现解决方案(类似于@dario 的答案,但没有在 python 中管理线程)。

openssh 客户端中有一个很少提及的功能,它允许我们通过 unix 套接字控制 ssh 进程,引用man ssh

-M      Places the ssh client into “master” mode for connection sharing.  Multiple -M options places ssh
         into “master” mode with confirmation required before slave connections are accepted.  Refer to the
         description of ControlMaster in ssh_config(5) for details.
-S ctl_path
         Specifies the location of a control socket for connection sharing, or the string “none” to disable
         connection sharing.  Refer to the description of ControlPath and ControlMaster in ssh_config(5)
         for details.

因此,您可以启动ssh(with -Nf) 的后台进程,然后通过另一个ssh调用检查(或终止)它。

我在需要建立反向隧道的项目中使用它

from subprocess import call, STDOUT
import os
DEVNULL = open(os.devnull, 'wb')


CONFIG = dict(
    SSH_SERVER='ssh.server.com',
    SSH_PORT=2222,
    SSH_USER='myuser',
    SSH_KEY='/path/to/user.key',
    REMOTE_PORT=62222,
    UNIX_SOCKET='/tmp/ssh_tunnel.sock',
    KNOWN_HOSTS='/path/to/specific_known_host_to_conflicts',
)


def start():
    return call(
        [
            'ssh', CONFIG['SSH_SERVER'],
            '-Nfi', CONFIG['SSH_KEY'],
            '-MS', CONFIG['UNIX_SOCKET'],
            '-o', 'UserKnownHostsFile=%s' % CONFIG['KNOWN_HOSTS'],
            '-o', 'ExitOnForwardFailure=yes',
            '-p', str(CONFIG['SSH_PORT']),
            '-l', CONFIG['SSH_USER'],
            '-R', '%d:localhost:22' % CONFIG['REMOTE_PORT']
        ],
        stdout=DEVNULL,
        stderr=STDOUT
    ) == 0


def stop():
    return __control_ssh('exit') == 0


def status():
    return __control_ssh('check') == 0


def __control_ssh(command):
    return call(
        ['ssh', '-S', CONFIG['UNIX_SOCKET'], '-O', command, 'x'],
        stdout=DEVNULL,
        stderr=STDOUT
    )

-o ExitOnForwardFailure=yes确保隧道无法建立时 ssh 命令会失败,否则不会退出。

于 2016-03-23T16:07:23.833 回答
0

我是否可以建议尝试pyngrok以编程ngrok方式为您管理隧道?完全披露,我是它的开发者。这里是SSH 示例,但安装起来很简单pyngrok

pip install pyngrok

并使用它:

from pyngrok import ngrok

# <NgrokTunnel: "tcp://0.tcp.ngrok.io:12345" -> "localhost:22">
ssh_tunnel = ngrok.connect(22, "tcp")
于 2020-05-06T18:12:19.437 回答
-5

paramiko在一年前的某个项目中使用过,这是我与另一台计算机/服务器连接并执行一个简单的 python 文件的代码的一部分:

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='...', username='...', password='...')
stdin, stdout, stderr = ssh.exec_command('python hello.py')
ssh.close()

stdinstdoutsdterr包含您执行的命令的输入/输出。

从这里,我认为您可以与数据库建立连接。

这里有一些关于 paramiko 的好信息

于 2011-11-17T17:26:15.667 回答