我需要创建隧道以从数据库中读取信息。我使用 Paramiko,但我还没有使用过隧道。请提供一个创建和关闭隧道的简单代码示例。
5 回答
在工作中,我们通常会创建 ssh 隧道转发端口。我们这样做的方式是,使用标准命令ssh -L port:addr:port addr
和在单独线程中运行的子进程。我发现了这个有用的链接:https ://github.com/paramiko/paramiko/blob/master/demos/forward.py ,其中有一个使用 paramiko 进行端口转发的示例。
我用于sshtunnel
我的项目。将远程本地 MySQL 端口转发到主机本地端口的示例:
pip install sshtunnel
python -m sshtunnel -U root -P password -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
即使这不使用 paramiko,我相信这是一个非常干净的实现解决方案(类似于@dario 的答案,但没有在 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
(with -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 命令会失败,否则不会退出。
我是否可以建议尝试pyngrok
以编程ngrok
方式为您管理隧道?完全披露,我是它的开发者。这里是SSH 示例,但安装起来很简单pyngrok
:
pip install pyngrok
并使用它:
from pyngrok import ngrok
# <NgrokTunnel: "tcp://0.tcp.ngrok.io:12345" -> "localhost:22">
ssh_tunnel = ngrok.connect(22, "tcp")
我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
包含您执行的命令的输入/输出。
从这里,我认为您可以与数据库建立连接。