You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CA签名密钥实现SSH端口转发:Paramiko问题及解决

如何在Paramiko中正确使用request_port_forward实现带CA签名的SSH端口转发?

我之前用sshtunnel库实现了可用的SSH隧道转发器,代码如下:

ssh_tunnel_server = {
    'ssh_address_or_host': (remote_host, 22),
    'ssh_username': ssh_user,
    'ssh_pkey': ssh_key_path,
    'remote_bind_address': ("localhost", 5900),
    'local_bind_address': ('127.0.0.1', 0),
}
tunnel = SSHTunnelForwarder(**ssh_tunnel_server)

tunnel.start()

但现在需要支持由CA签名的SSH连接。我发现直接用Paramiko可以通过将CA公钥作为key_filename参数传入,建立带CA的SSH连接,还能通过open_session()执行命令:

client.connect(ssh_host, port=ssh_port, username=ssh_user, pkey=private_key, key_filename=ssh_cert_path)

不过尝试使用transport.request_port_forward函数进行端口转发时失败了,代码如下:

transport.request_port_forward("localhost", local_port,handler(channel, "127.0.0.1",remote_port))

程序卡在chan = transport.accept(1000)处,相关代码为:

def forward_tunnel(local_port, remote_host, remote_port, transport: Transport):
    transport.request_port_forward("", local_port)
    while True:
        chan = transport.accept(1000)
        if chan is None:
            continue
        thr = threading.Thread(target=handler, args=(chan, remote_host, remote_port))
        thr.setDaemon(True)
        thr.start()

请问如何正确使用request_port_forward方法?


解决方案

感谢@Martin Prikryl的帮助。之前使用Transport.open_channel时误以为需要用forwarded-tcpip,尝试正确方法后终于成功,代码如下:

def forward_tunnel(local_port, remote_host, remote_port, transport: Transport):
    channel = transport.open_channel("direct-tcpip",(remote_host,remote_port),("127.0.0.1",local_port))

    local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    local_socket.bind(("127.0.0.1", local_port))
    local_socket.listen(1)
    conn, addr = local_socket.accept()
    timeout = 5

    try:
        while True:
            r, w, x = select.select([channel, conn], [], [], timeout)

            if channel in r:
                data = channel.recv(1024)
                if len(data) > 0:
                    conn.sendall(data)
                else:
                    break

            if conn in r:
                data = conn.recv(1024)
                if len(data) > 0:
                    channel.sendall(data)
                else:
                    break
    finally:
        channel.close()
        conn.close()
        local_socket.close()

内容的提问来源于stack exchange,提问作者domagaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:52:05