如何使用Python打开SSH隧道?

12 投票
6 回答
43132 浏览
提问于 2025-04-16 08:06

我正在尝试使用Django连接到一个远程的MySQL数据库。
文档上说,首先需要打开一个SSH隧道才能连接到这个数据库。
请问有没有什么Python库可以在设置好某些选项后自动打开这个SSH隧道呢?

6 个回答

5

这里有一段Python3的代码示例(不过你也可以很容易地把它改成Python2)。它在一个单独的线程中运行SSH隧道;然后主线程会做一些事情,通过这个SSH隧道获取网络流量。

在这个例子中,SSH隧道把本地的2222端口转发到本地的80端口。主要的操作就是运行

curl http://localhost:2222

也就是说,从2222端口获取一个网页。

SshTunnel这个类需要4个参数来初始化,分别是本地端口、远程端口、远程用户和远程主机。它的作用就是以以下方式启动SSH:

ssh -N -L localport:remotehost:remoteport remoteuser@remotehost

为了让这个工作正常,你需要为remoteuser@remotehost设置无密码登录(通过~/.ssh/id_rsa.pub,这个文件在远程服务器上是已知的)。这样运行的SSH隧道在一个线程中;而主要的任务必须在另一个线程中。SSH隧道线程被标记为守护线程,这样一来,一旦主活动结束,它就会自动停止。

我没有提供完整的MySQL连接示例,因为这个应该是自解释的。一旦SshTunnel设置了本地TCP端口,你就可以连接到它——无论是通过你的MySQL客户端、curl,还是其他工具。

import subprocess
import time
import threading

class SshTunnel(threading.Thread):
    def __init__(self, localport, remoteport, remoteuser, remotehost):
        threading.Thread.__init__(self)
        self.localport = localport      # Local port to listen to
        self.remoteport = remoteport    # Remote port on remotehost
        self.remoteuser = remoteuser    # Remote user on remotehost
        self.remotehost = remotehost    # What host do we send traffic to
        self.daemon = True              # So that thread will exit when
                                        # main non-daemon thread finishes

    def run(self):
        if subprocess.call([
            'ssh', '-N',
                   '-L', str(self.localport) + ':' + self.remotehost + ':' + str(self.remoteport),
                   self.remoteuser + '@' + self.remotehost ]):
            raise Exception ('ssh tunnel setup failed')


if __name__ == '__main__':
    tunnel = SshTunnel(2222, 80, 'karel', 'localhost')
    tunnel.start()
    time.sleep(1)
    subprocess.call(['curl', 'http://localhost:2222'])
9

可以试试使用 sshtunnel这个工具

其实很简单:

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

说明一下:我是这个工具的作者和维护者。

11

你可以试试 paramiko转发 功能。如果想了解 paramiko 的基本情况,可以查看 这里

撰写回答