如何使用Python打开SSH隧道?
我正在尝试使用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
说明一下:我是这个工具的作者和维护者。