关于使用Python启动SSH隧道的问题

时间:2010-08-26 12:19:12

标签: python ssh

从用Python编写的HTTP RPC服务器启动SSH隧道时遇到了麻烦。

有一个基于Python的BaseHTTPServer用Python编写的简单HTTP RPC服务器。 作为其中一项服务的一部分,我想从RPC服务器启动到远程机器的SSH隧道。我使用os.system在RPC调用

调用的Python脚本中启动SSH隧道
os.system("ssh -f -n -N -L 127.0.0.1:%d:localhost:%d user@%s" % (6800, 9000, "remote.machine"))
乍一看,当隧道启动时,所有人似乎都很好,我可以使用它,但有一点我注意到了。除了侦听端口6800之外,SSH也开始侦听端口8001(运行HTTP RPC服务器的端口)。

以下是关于RPC服务器和SSH的lsof输出:

rpc.py    27763   usern    5u  IPv4 102130428       TCP 127.0.0.1:8001 (LISTEN)
ssh        1951   usern   14u  IPv4 102149728       TCP 127.0.0.1:6800 (LISTEN)
ssh        1951   usern    5u  IPv4 102130428       TCP 127.0.0.1:8001 (LISTEN)

一切正常,直到RPC服务器重启。在重新启动期间,RPC服务器被强制关闭与侦听套接字的连接,但SSH的连接仍然打开,RPC服务器无法再次在同一端口上启动。

似乎SSH隧道也以某种方式将自己与RPC服务器的侦听套接字的fd相关联。

任何人都可以提示如何从脚本设置SSH隧道,只需要监听假定的端口(本例中为6800)。

3 个答案:

答案 0 :(得分:2)

使用subprocess.Popen()并设置close_fds = True(在Python 2.4及更高版本中可用),而不是os.system()。

import subprocess    
subprocess.Popen("ssh -f -n -N -L 127.0.0.1:%d:localhost:%d user@%s" % (6800, 9000, "remote.machine"), shell=True, close_fds=True)

理论上,我相信你也应该能够在调用os.system()之前使用fcntl将侦听套接字的文件描述符设置为close-on-exec(FD_CLOEXEC)。

答案 1 :(得分:1)

您是否考虑过将paramiko用于SSH? (取决于PyCrypto,但其他纯Python)

这样可以简化管理连接,并且根据服务器处理套接字的方式,您可以设置paramiko Channel,然后让服务器将其视为任何其他侦听套接字。

(在paramiko中,传输对象代表基本的SSH2连接,并且对于每个传输,您可以创建多个Channel对象,每个对象都充当常规Python套接字的替代品)

以下是一些资源,以供您查看:

答案 2 :(得分:0)

我怀疑这与分叉有关,然后告诉ssh从调用进程(“-f”)分离。

另外,不确定这是否会有所帮助,但如果你的python足够现代,你应该真正使用子进程模块。