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

使用ssh2建立SSH连接后端口转发失效问题排查

问题描述

建立SSH连接后,希望将其转发到指定端口,再通过代理传输全部数据流量。目前SSH连接已成功建立,但转发端口无法正常工作,无法传输流量,以下是我的代码:

const conn = new Client();
const sshConfig: ConnectConfig = {
  host: sshIp,
  port: sshPort,
  username: sshUsername,
  password: sshPassword,
};

const StaticIP = "127.0.0.1";

conn.on("ready", () => {
  console.log("ssh connected!");

  conn.forwardOut(StaticIP, 4567, sshIp, sshPort, (err, stream) => {
    if (err) {
      return;
    }

    connectToProxy(StaticIP, 4567);

    stream.on("data", (data) => {
      console.log(`received data: ${data}`);
    });

    stream.on("close", () => {
      console.log("connection is closed!");
    });
  });
});
console.log("ssh connecting..");
conn.connect(sshConfig);

问题排查与修复方案

1. forwardOut 参数逻辑错误

forwardOut 的作用是创建从本地经SSH隧道到远程目标服务的连接,你的参数填错了:

  • 第三个、第四个参数你填了SSH服务器的sshIp和sshPort,相当于把流量又发回SSH服务器,这不是代理流量的正确逻辑,应该替换成你实际要访问的目标服务地址和端口。
  • 第二个参数(本地发起请求的端口)填0即可,不需要指定固定值,系统会分配随机端口。

2. 缺少本地端口监听与双向数据转发

你没有在本地监听4567端口,也没建立本地端口和SSH隧道之间的双向数据通道——这是流量无法传输的核心问题。目前代码只创建了SSH流,但没有把本地端口的请求流量导入流,也没把流返回的数据回传给本地连接。

3. connectToProxy 调用时机错误

你在拿到SSH流后直接调用connectToProxy,但此时本地4567端口没有被监听,连接请求会直接失败,必须等本地端口监听成功后再调用。

修复后的示例代码

const conn = new Client();
const sshConfig: ConnectConfig = {
  host: sshIp,
  port: sshPort,
  username: sshUsername,
  password: sshPassword,
};

const LOCAL_PROXY_PORT = 4567;
// 替换成你实际要访问的目标服务地址和端口
const TARGET_SERVICE_HOST = "目标服务IP/域名";
const TARGET_SERVICE_PORT = 80;

conn.on("ready", () => {
  console.log("ssh connected!");

  // 监听本地4567端口,接收代理请求
  const localProxyServer = require('net').createServer((localSocket) => {
    // 通过SSH隧道连接到目标服务
    conn.forwardOut(
      '127.0.0.1',
      0,
      TARGET_SERVICE_HOST,
      TARGET_SERVICE_PORT,
      (err, sshStream) => {
        if (err) {
          console.error("SSH隧道创建失败:", err);
          localSocket.end();
          return;
        }

        // 双向转发数据:本地请求 ↔ SSH隧道
        localSocket.pipe(sshStream);
        sshStream.pipe(localSocket);
      }
    );
  });

  // 启动本地代理端口
  localProxyServer.listen(LOCAL_PROXY_PORT, '127.0.0.1', () => {
    console.log(`本地代理已启动:127.0.0.1:${LOCAL_PROXY_PORT}`);
    // 此时再发起代理连接
    connectToProxy('127.0.0.1', LOCAL_PROXY_PORT);
  });
});

console.log("ssh connecting..");
conn.connect(sshConfig);

关键说明

  • 用net.createServer监听本地4567端口,每收到一个本地连接,就创建对应的SSH隧道到目标服务。
  • 通过pipe方法实现本地socket和SSH流的双向数据转发,这是流量能正常传输的核心。
  • 确保forwardOut指向正确的目标服务,而非SSH服务器本身。
  • 等本地端口监听成功后再调用connectToProxy,保证连接能被正常接收。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:25:14