-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.
Host gateway1
HostName gtw1_IP_address
User gtw1_user
IdentityFile "path_to_gtw1_ssh_key"
IdentitiesOnly True
Host gateway2
User gtw2_user
Hostname gtw2_IP_address
IdentityFile "path_to_gtw2_ssh_key"
IdentitiesOnly True
# mysql
LocalForward 127.0.0.1:33306 127.0.0.1:3306
ProxyCommand ssh -W %h:%p switch-cede
下面是我在python中的重现:
from sqlalchemy import create_engine
import config
import pandas as pd
import sshtunnel
from paramiko import SSHClient
with sshtunnel.open_tunnel(
ssh_username='gtw1_user',
ssh_address_or_host=('gtw1_IP_address', 22),
remote_bind_addresses=[('gtw2_IP_address', 22), ('gtw2_IP_address', 33306)],
local_bind_addresses=[('0.0.0.0', 22), ('0.0.0.0', 33306)], #this line is optional
ssh_pkey=path_to_gtw1_ssh_key,
) as tunnel1: # tunnel1 is the tunnel between myMachine and gateway1 I believe
print('Connection to tunnel1 (86.119.30.24:22) OK...')
print(tunnel1.local_bind_ports)
with sshtunnel.open_tunnel(
ssh_address_or_host=('localhost', tunnel1.local_bind_ports[0]),
remote_bind_addresses=[('127.0.0.1', 22),('127.0.0.1', 3306)],
local_bind_addresses=[('0.0.0.0', 22), ('127.0.0.1', 33306)],
ssh_username='gtw2_user',
ssh_pkey=path_to_gtw2_ssh_key,
) as tunnel2: # tunnel2 is the tunnel between gtw1 and gtw2 I believe
print('Connection to tunnel2 (192.168.142.140:22) OK...')
print(tunnel2.local_bind_ports)
db = create_engine(
f"mysql+pymysql://{config.USER}:{config.PASSWORD}@{config.HOST}:{config.PORT}/{config.DATABASE}")
print(db)
query = "SELECT * FROM randomTable LIMIT 10;"
df = pd.read_sql(query, db)
print(df)
# note that config is a file holding the credentials to connect to the database
6条答案
按热度按时间svgewumm1#
在工作中,我们通常创建ssh隧道转发端口。我们这样做的方法是,使用标准命令
ssh -L port:addr:port addr
,子进程在一个单独的线程中运行。https://github.com/paramiko/paramiko/blob/master/demos/forward.py,其中包含使用paramiko执行端口转发的示例。wkyowqbh2#
我在项目中使用
sshtunnel
。将远程本地MySQL端口转发到主机本地端口的示例:lxkprmvk3#
尽管这没有使用paramiko,我相信这是一个非常干净的解决方案(类似于@dario的答案,但没有在python中管理线程)。
openssh客户端中有一个很少提及的特性,它允许我们通过unix套接字控制ssh进程,引用
man ssh
:因此,您可以启动
ssh
的后台进程(使用-Nf
),然后使用另一个ssh
调用检查(或终止)它。我在需要建立反向隧道的项目中使用此选项
-o ExitOnForwardFailure=yes
确保如果无法建立隧道,ssh命令将失败,否则将不退出。n3h0vuf24#
我可以建议您尝试使用
pyngrok
之类的工具来编程管理ngrok
隧道吗?完全公开,我是它的开发者。这里有SSH示例,但它和安装pyngrok
一样简单:并使用它:
6xfqseft5#
我添加此解决方案用于多个端口上的多跳:
我有这样的设置:
目标是通过在端口33306上调用我的计算机来访问数据库。这是不可能的,因为只允许gateway2与数据库对话。我们无法访问gateway2,因为只允许gateway1与它对话。
下面是相应的ssh. config文件:
下面是我在python中的重现:
swvgeqrz6#
我在一年前的某个项目中使用了
paramiko
,下面是我连接到另一台计算机/服务器并执行一个简单python文件的部分代码:stdin
、stdout
和sdterr
包含所执行命令的输入/输出。从这里,我想你可以连接到数据库。
Here is some good information about paramiko.