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

C#通过SSH连接远程后建立TCP Socket超时问题排查

问题根因

代码的TCP连接发起位置错误:

  • 代码中ping操作通过SshCommand提交到远程SSH服务器执行,处于远程服务器的网络环境下,可以访问服务器内网的10.xx.xxx.xxx地址,因此执行成功。
  • 后续实例化的TcpClient运行在本地机器上下文,直接尝试连接10.xx.xxx.xxx:32060。该地址属于远程服务器侧的私网网段,本地机器无对应路由,连接必然超时。
  • 手动登录SSH后能在服务器内建立Socket连接,本质是TCP连接由远程服务器发起,和本地网络环境无关。
解决方案

使用SSH本地端口转发能力,通过已建立的SSH隧道把本地端口流量转发到远程服务器可访问的目标内网地址,再让本地TcpClient连接本地转发端口即可。以你使用的SSH.NET库为例,修改后的代码如下:

using (var client = new SshClient("74.xxx.xxx.xxx", 8811, "myuser", privatekey))
{
    client.Connect();
    string targetHost = "10.xx.xxx.xxx";
    int targetPort = 32060;
    // 绑定本地回环地址的空闲端口,自动转发到远程侧目标内网地址
    var forwardedPort = new ForwardedPortLocal("127.0.0.1", 0, targetHost, (uint)targetPort);
    client.AddForwardedPort(forwardedPort);
    forwardedPort.Start();

    if (client.IsConnected && forwardedPort.IsStarted)
    {
        Console.WriteLine("ssh connected, port forward started");
        // 连通性校验逻辑保持不变,在远程服务器侧执行ping
        SshCommand cmd = client.CreateCommand($"ping -c 3 {targetHost}");
        cmd.Execute();
        Console.WriteLine(cmd.Result);

        TcpClient tcpClient = new TcpClient();
        // 连接本地转发端口,流量经SSH隧道由远程服务器发起对目标地址的连接
        tcpClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), forwardedPort.BoundPort));
        Console.WriteLine("tcp connected successfully");
        // 后续直接通过tcpClient.GetStream()即可完成Socket收发,逻辑和普通TCP连接一致
    }

    // 资源清理
    forwardedPort.Stop();
    client.Disconnect();
}
注意事项
  • 不需要手动打开终端维持SSH会话,上述代码运行时会自动维持SSH隧道和转发规则,程序退出后隧道自动断开。
  • 如果需要绑定固定本地端口,把ForwardedPortLocal构造函数的第二个参数0替换为你想用的未被占用的端口号即可。
  • 请使用2020年后发布的SSH.NET稳定版本,旧版本存在端口转发功能异常的已知问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:31:05