【问题标题】:How to create a SSH tunnel using Python and Paramiko?如何使用 Python 和 Paramiko 创建 SSH 隧道?
【发布时间】:2011-12-31 11:14:37
【问题描述】:

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

【问题讨论】:

  • 您是在寻找服务器还是客户端,或者两者兼而有之?您确定在 Python 中需要它吗?使用 SSH 建立隧道怎么样?
  • 试试pip install sshtunnel

标签: python ssh paramiko ssh-tunnel


【解决方案1】:

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

【讨论】:

  • 感谢您的链接,但我无法运行此代码。他提出论据。但我输入的论点不起作用。举个例子请行发射。
  • 示例:此命令:“ssh -L 5555:machine2:55 machine1”将连接到 machine1:22,并将从您的计算机:5555 到 machine1:22 的任何连接转发到 machine2:55。假设您要将自己的 ssh 服务转发到另一个端口,执行此操作的命令是:“ssh -L 5555:localhost:22 localhost”。因此,如果您执行“ssh localhost -p 5555”,它会将您连接到您自己的 localhost:22。要使用 paramiko“forward.py”演示执行此操作,您必须以这种方式运行它:“python forward.py localhost - p 5555 -r 本地主机:22"。执行它并在另一个终端运行 ssh localhost -p 5555
  • @dario 使用 -L1、-L2、-Ln 创建多个转发?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    尽管这不使用 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命令会失败,否则不会退出。

    【讨论】:

    • 我对这个解决方案很感兴趣。连接后,如何向服务器发送命令?例如:“ifconfig”并将输出返回到我的客户端?谢谢。
    【解决方案4】:

    我是否可以建议尝试像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")
    

    【讨论】:

    • 这比 sshtunnel 有什么优势?我已经有一个付费的 ngrok 帐户了。
    【解决方案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 包含您执行的命令的输入/输出。

    从这里,我想你可以和数据库建立连接了。

    Here is some good information about paramiko.

    【讨论】:

    • 这如何回答这个问题?
    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 2020-09-14
    • 2011-05-23
    • 2015-03-10
    • 2012-03-28
    • 2021-01-25
    • 2022-01-05
    相关资源
    最近更新 更多