使用sshtunnel软件包进行两步SSH本地端口转发

问题描述

我正在尝试在host1和host3之间打开一条双向隧道,中间是host2。

host1 <--> host2 <--> host3

这是我在host1上运行的(阻塞)bash命令,以转发端口51672。

ssh -g -L 51672:host2:51672 host2_username@host2 \'/tmp/sshpass -p host3_pass ssh -g -L 51672:host3:51672 host3_username@host3 \'\'"while true; do : ; sleep 5; done"\'\'\'

我有一个脚本在host3上运行,侦听端口51672。当我在host1上创建TCP套接字并连接到host2:51672时,我可以通过该主机名与hos​​t3上的脚本进行通信套接字。

在下一步中,我尝试将其移植到python中并使用sshtunnel包。我有些困惑,here中的哪个选项等效于我的情况。

这是我的第一次尝试:

import paramiko
import sshtunnel

with sshtunnel.open_tunnel(
        ssh_address_or_host=(host2,22),ssh_username=host2_username,ssh_password=host2_pass,local_bind_address=('0.0.0.0',51672),remote_bind_address=(host3,block_on_close=False
) as tunnel1:
    log.info('Tunnel to host2 is established.')
    with sshtunnel.open_tunnel(
            ssh_address_or_host=('localhost',tunnel1.local_bind_port),ssh_username=host3_username,ssh_password=host3_password,block_on_close=False
    ) as tunnel2:
        log.info('Tunnel to host3 is established.')
        while True:
            time.sleep(1)

我可以确认从host1到host2的隧道是打开的,因为以下命令在host1上返回0。

nc -z localhost 51672

但是,host2和host3之间的隧道似乎不起作用。

解决方法

第一步是建立SSH隧道。然后,您将使用自定义端口。

更简单的方法(虽然不是最佳方法)是:

  • 打开与host2的直接SSH连接。
  • 通过host1:A连接将本地host2端口转发到host3:22
  • 使用转发的端口host3打开到host1:A的SSH连接。
  • 通过host1:B将另一个本地host3端口转发到host3:51672
  • 连接到host1:B进入host3:51672

但是实际上您不需要进行第一次物理端口转发,可以使用Nested SSH using Python Paramiko中所示的sock方法。

(我相信,即使是您原来的ssh方法,由于具有两次转发功能,也不必要地变得复杂)