如何使用Python SSHTunnle转发多个端口

How to use Python SSHTunnle to forward multiple ports

我需要转发到服务器后面的多个端口

server1(22) -> Server2(mysql, 3360) = local 3360
            -> Server3(http, 8080)  = local 8080
            -> Server4(oracle,1234) = local 1234

我只能通过server1访问Server2、3、4。

我正在使用 Python ssltunnel 包 https://pypi.org/project/sshtunnel/

在示例1&2中,我只能指定一个远程&本地绑定地址。 不确定如何连接多个服务器(2,3,4)

示例 1

from sshtunnel import SSHTunnelForwarder

server = SSHTunnelForwarder(
    'pahaz.urfuclub.ru',
    ssh_username="pahaz",
    ssh_password="secret",
    remote_bind_address=('127.0.0.1', 8080)
)

server.start()

print(server.local_bind_port)  # show assigned local port
# work with `SECRET SERVICE` through `server.local_bind_port`.

server.stop()

示例 2

import paramiko
import sshtunnel

with sshtunnel.open_tunnel(
    (REMOTE_SERVER_IP, 443),
    ssh_username="",
    ssh_pkey="/var/ssh/rsa_key",
    ssh_private_key_password="secret",
    remote_bind_address=(PRIVATE_SERVER_IP, 22),
    local_bind_address=('0.0.0.0', 10022)
) as tunnel:
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect('127.0.0.1', 10022)
    # do some operations with client session
    client.close()

print('FINISH!')

我可以使用任何其他 Python 包来完成这项工作。

这两个示例都可以稍微修改以按照您想要的方式工作。

绑定有单数版本(local_bind_address & remote_bind_address)和绑定的复数版本(local_bind_addresses & remote_bind_addresses.

单数版本需要 tuple 包含连接变量,而复数版本需要 list 一个或多个 tuple(s)

这是您的示例 2 的修改版本:

import paramiko
import sshtunnel

tunnels = [("172.16.0.1", 80),
           ("172.16.0.2", 22)]

localPorts = [("127.0.0.1", 1180),
              ("127.0.0.1", 10022)]

with sshtunnel.open_tunnel(
    (REMOTE_SERVER_IP, 22),
    ssh_username="",
    ssh_pkey="/var/ssh/rsa_key",
    ssh_private_key_password="secret",
    remote_bind_addresses=tunnels,
    local_bind_addresses=localPorts
) as tunnel:
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect('127.0.0.1', 10022)
    # do some operations with client session
    client.close()

如果列表的长度相同,则IP地址/端口将相互对应。

在我上面的示例中,发生了以下情况:

Connection: 172.16.0.1 Port: 80, Is tunneled via: 127.0.0.1 Port: 1180

Connection: 172.16.0.2 Port: 22, Is tunneled via: 127.0.0.1 Port: 10022