如何使用python和paramiko创建ssh隧道?

时间:2011-11-17 15:27:58

标签: python ssh paramiko

我正在学习python。我需要隧道创建者从数据库中读取信息并关闭隧道。我使用paramiko,但我没有使用tonelem示例。请举一个简单代码创建隧道的例子。

提前致谢!

5 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:9)

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

pip install sshtunnel
python -m sshtunnel -U root -P password -L :3306 -R 127.0.0.1:3306 -p 2222 localhost

答案 2 :(得分:4)

即使这不使用paramiko,我相信它是一个非常干净的解决方案(类似于@dario's answer,但没有在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-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命令将失败,否则它将不会退出。

答案 3 :(得分:0)

我建议您尝试使用pyngrok之类的程序来为您管理ngrok隧道吗?完全公开,我是它的开发者。 SSH示例here,但就像安装pyngrok一样简单:

pip install pyngrok

并使用它:

from pyngrok import ngrok

# <NgrokTunnel: "tcp://0.tcp.ngrok.io:12345" -> "localhost:22">
ssh_tunnel = ngrok.connect(22, "tcp")

答案 4 :(得分:-3)

我使用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包含您执行的命令的输入/输出。

从这里开始,我认为你可以与数据库建立联系。

Here is some good information about paramiko