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

通过跳板机使用Paramiko连接目标服务器时Transport挂起的问题求助

通过跳板机使用Paramiko连接目标服务器时Transport挂起的问题求助

Hey there! Let's figure out why your target server connection is hanging. I spotted a critical mistake in your code that's almost certainly the root cause, plus a few other things to check.

核心问题:错误的通道类型

You're using a "session" type channel when opening the connection from the jump server to the target:

channel = jump_transport.open_channel("session", dest_addr, local_addr)

A session channel is designed to run commands or shells on the jump server itself, not to forward traffic to another server. To tunnel your SSH connection through the jump server to the target, you need to use a direct-tcpip channel instead. This tells the jump server to forward your traffic directly to the target's SSH port.

修复后的代码调整

Here's the fixed version of your connect_to_target function, with the channel type corrected and more robust authentication handling (since your target might also use keyboard-interactive auth like the jump server):

import paramiko, traceback
from getpass import getpass

def connect_to_target(jump_ssh, target_host, target_port, username, password):
    dest_addr = (target_host, target_port)
    local_addr = ("127.0.0.1", 0)

    try:
        jump_transport = jump_ssh.get_transport()
        # 改用direct-tcpip通道实现端口转发
        channel = jump_transport.open_channel("direct-tcpip", dest_addr, local_addr)       
        if not channel.is_active():
            print("Failed to open direct-tcpip channel to target server")
            return

        # 在转发通道上建立目标服务器的SSH连接
        target_transport = paramiko.Transport(channel)
        target_transport.start_client()

        # 复用跳板机的交互式认证逻辑(适配目标服务器的认证要求)
        def challenge_handler(title, instructions, prompt_list):
            responses = []
            for prompt in prompt_list:
                if "password" in prompt[0].lower():
                    responses.append(password)
                elif "rsa" in prompt[0].lower():
                    token = getpass(f"{prompt[0].strip()}: ")
                    responses.append(token)
                else:
                    responses.append(getpass(f"{prompt[0].strip()}: "))
            return responses

        target_transport.auth_interactive(username, handler=challenge_handler)
        
        # 绑定transport到SSHClient
        target_ssh = paramiko.SSHClient()
        target_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        target_ssh._transport = target_transport
        
        # 测试连接
        stdin, stdout, stderr = target_ssh.exec_command("hostname")
        print("Target server hostname:", stdout.read().decode().strip())
    except Exception as e:
        print(f"Error connecting to target: {e}")
        traceback.print_exc()
    finally:
        if 'target_ssh' in locals():
            target_ssh.close()
        if 'channel' in locals():
            channel.close()
        jump_ssh.close()

其他需要检查的点

  • Jump server TCP forwarding permission: Ensure your jump server's sshd_config has AllowTcpForwarding yes (this is default, but verify if it was modified).
  • Target server auth method: If your target uses plain password auth instead of keyboard-interactive, you can replace the auth step with target_transport.auth_password(username, password) for simplicity.
  • Firewall rules: Double-check that the jump server has unrestricted access to the target's port 22 (you mentioned PuTTY works, but it's worth ruling out edge cases).

日志验证

After making this change, your Paramiko logs should show the key exchange process starting for the target server connection, instead of hanging after starting the thread.

备注:内容来源于stack exchange,提问作者Ginger_Chacha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 14:49:51