如何使用 Python 和 Paramiko 创建 SSH 隧道?
Posted
技术标签:
【中文标题】如何使用 Python 和 Paramiko 创建 SSH 隧道?【英文标题】:How to create a SSH tunnel using Python and Paramiko? 【发布时间】:2011-12-31 11:14:37 【问题描述】:我需要创建隧道以从数据库中读取信息。我使用 Paramiko,但我还没有使用过隧道。请提供一个创建和关闭隧道的简单代码示例。
【问题讨论】:
您是在寻找服务器还是客户端,或者两者兼而有之?您确定在 Python 中需要它吗?使用 SSH 建立隧道怎么样? 试试pip install sshtunnel
【参考方案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()
stdin
、stdout
和 sdterr
包含您执行的命令的输入/输出。
从这里,我想你可以和数据库建立连接了。
Here is some good information about paramiko.
【讨论】:
这如何回答这个问题?以上是关于如何使用 Python 和 Paramiko 创建 SSH 隧道?的主要内容,如果未能解决你的问题,请参考以下文章