SSH 跳板机、免密登录、VS Code Remote-SSH 与远程代理转发配置指南

适用场景:Windows 本地电脑通过 SSH 登录裸金属服务器;通过跳板机访问内网机器;让远端服务器使用 Windows 本地代理;用 VS Code Remote-SSH 连接远端服务器。


0. 当前网络与目标

机器关系

名称 IP / Host 说明
Windows 本地电脑 C:\Users\24385 本地开发机,本地代理端口为 127.0.0.1:7897
跳板机 10.42.206.102 Windows 可直接 SSH 登录
目标机 10.20.2.5 / bms-25 只能经跳板机访问
其他服务器 192.168.206.112 用户 pcljgy
其他服务器 192.168.206.140 / 192.168.206.140_jgy 用户 pcljgy

目标 1:Windows 直接登录目标机:

powershell 复制代码
ssh bms-25

实际路径:

text 复制代码
Windows 本地电脑 → 10.42.206.102 → 10.20.2.5

目标 2:让远端服务器使用 Windows 本地代理:

text 复制代码
远端服务器 127.0.0.1:10240
    ↓ SSH 隧道
Windows 本地 127.0.0.1:7897

1. SSH 免密登录基础

1.1 公钥应该放在哪里

SSH 免密登录的规则是:你用哪个用户登录,服务器就去哪个用户的家目录找 authorized_keys

登录命令 服务器读取的公钥文件
ssh root@10.42.206.102 /root/.ssh/authorized_keys
ssh root@10.20.2.5 /root/.ssh/authorized_keys
ssh pcljgy@192.168.206.112 /home/pcljgy/.ssh/authorized_keys

所以不是"必须上传到 root 文件夹",而是因为你登录的是 root 用户。

1.2 //root 的区别

text 复制代码
/       是 Linux 系统根目录
/root   是 root 用户的家目录

1.3 公钥和私钥

你的 Windows 公钥是:

text 复制代码
C:\Users\24385\.ssh\id_rsa.pub

私钥是:

text 复制代码
C:\Users\24385\.ssh\id_rsa

只能上传公钥 id_rsa.pub,不要上传私钥 id_rsa


2. 通过跳板机访问内网目标机

2.1 为什么 ssh -J 失败

曾尝试:

powershell 复制代码
ssh -J root@10.42.206.102 root@10.20.2.5

报错:

text 复制代码
channel 0: open failed: administratively prohibited: open failed
stdio forwarding failed
Connection closed by UNKNOWN port 65535

含义:Windows 成功连上了跳板机,但跳板机的 SSH 服务不允许 TCP forwarding,所以 ProxyJump 被禁止。常见原因是跳板机 /etc/ssh/sshd_config 中有:

text 复制代码
AllowTcpForwarding no

或存在 PermitOpen / Match 限制。

2.2 如何查询 -J 的含义

ssh --help 不一定可用,因为 OpenSSH 通常不支持 --help

可以用:

bash 复制代码
ssh -h 2>&1 | grep -- "-J"

或:

bash 复制代码
man ssh

进入手册后输入:

text 复制代码
/-J

-JProxyJump,格式:

bash 复制代码
ssh -J 跳板机用户@跳板机IP 目标用户@目标IP

2.3 使用 ProxyCommand + nc 代替 ProxyJump

先在跳板机确认存在 nc

bash 复制代码
which nc

结果:

text 复制代码
/usr/bin/nc

测试跳板机到目标机的 22 端口:

bash 复制代码
nc -vz 10.20.2.5 22

结果:

text 复制代码
Ncat: Connected to 10.20.2.5:22.

说明:

text 复制代码
10.42.206.102 → 10.20.2.5:22 是通的

Windows 本地可以这样直接测试:

powershell 复制代码
ssh -o "ProxyCommand=ssh root@10.42.206.102 /usr/bin/nc %h %p" root@10.20.2.5

这里不要写 nc -vz,因为 -vz 只是测试端口。真正代理 SSH 流量时应该使用:

bash 复制代码
/usr/bin/nc %h %p

其中:

text 复制代码
%h = 目标 HostName,例如 10.20.2.5
%p = 目标端口,默认 22

3. 将 Windows 公钥写入内网目标机

3.1 成功的一条 PowerShell 命令

在 Windows PowerShell 中执行:

powershell 复制代码
$pub = (Get-Content $env:USERPROFILE\.ssh\id_rsa.pub -Raw).Trim(); ssh -o "ProxyCommand=ssh root@10.42.206.102 /usr/bin/nc %h %p" root@10.20.2.5 "mkdir -p /root/.ssh && touch /root/.ssh/authorized_keys && grep -qxF '$pub' /root/.ssh/authorized_keys || echo '$pub' >> /root/.ssh/authorized_keys; chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys"

作用:

  1. 读取 Windows 本地 id_rsa.pub
  2. 通过 ProxyCommand + nc 连接 10.20.2.5
  3. 在目标机创建 /root/.ssh
  4. 将公钥写入 /root/.ssh/authorized_keys
  5. 如果公钥已存在,则不重复添加;
  6. 设置正确权限。

权限要求:

bash 复制代码
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys

3.2 为什么"管道传公钥 + 内层 ssh"容易失败

之前类似命令:

powershell 复制代码
Get-Content $env:USERPROFILE\.ssh\id_rsa.pub | ssh root@10.42.206.102 "ssh root@10.20.2.5 'mkdir -p /root/.ssh && cat >> /root/.ssh/authorized_keys'"

失败原因:外层 SSH 正在接收管道输入,内层 ssh root@10.20.2.5 又需要交互式输入密码,管道和交互式密码输入容易冲突。改用 ProxyCommand + nc 后,Windows 本地直接建立到目标机的 SSH 会话,所以可以正常输入密码并写入公钥。


4. Windows SSH config 推荐配置

打开配置文件:

powershell 复制代码
notepad $env:USERPROFILE\.ssh\config

推荐写法:

sshconfig 复制代码
Host bms-gateway
    HostName 10.42.206.102
    User root
    IdentityFile C:/Users/24385/.ssh/id_rsa
    IdentitiesOnly yes
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

Host bms-25
    HostName 10.20.2.5
    User root
    IdentityFile C:/Users/24385/.ssh/id_rsa
    IdentitiesOnly yes
    ProxyCommand ssh -q bms-gateway /usr/bin/nc %h %p
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

之后可以直接:

powershell 复制代码
ssh bms-25

ProxyCommand 中加 -q 的作用是减少跳板机登录 banner 等输出,避免干扰 VS Code Remote-SSH。


5. VS Code Remote-SSH 连接问题

5.1 先判断是否真的 SSH 失败

如果日志里有:

text 复制代码
Found existing installation at /root/.vscode-server...
Starting VS Code CLI...
Remote server is listening on socket /tmp/code-...

或:

text 复制代码
Found running server...
listeningOn==34713==

说明 SSH 已经连上,VS Code Server 也已启动。失败通常发生在后续 tunnel / socket 通信。

5.2 socket 模式问题

如果看到:

text 复制代码
remote.SSH.remoteServerListenOnSocket = true
Remote server is listening on socket /tmp/code-...
Exec server failed: Error: read ECONNRESET

可以先关闭 socket 模式。

打开 VS Code 用户设置:

powershell 复制代码
notepad $env:APPDATA\Code\User\settings.json

加入或合并:

json 复制代码
{
  "remote.SSH.remoteServerListenOnSocket": false,
  "remote.SSH.useExecServer": false,
  "remote.SSH.useLocalServer": false,
  "remote.SSH.showLoginTerminal": true,
  "remote.SSH.remotePlatform": {
    "bms-25": "linux"
  }
}

然后在 VS Code 中执行:

text 复制代码
Ctrl + Shift + P
Remote-SSH: Kill VS Code Server on Host...
选择 bms-25

再重新连接。

5.3 目标机禁止 TCP forwarding

如果日志里出现:

text 复制代码
channel 3: open failed: administratively prohibited: open failed

检查目标机:

bash 复制代码
sshd -T | grep -Ei "allowtcpforwarding|permitopen|allowstreamlocalforwarding"

曾出现:

text 复制代码
allowtcpforwarding no
allowstreamlocalforwarding yes
permitopen any

这说明目标机禁止 TCP forwarding。VS Code Remote-SSH 需要 SSH tunnel,因此会失败。

5.4 开启目标机 TCP forwarding

在目标机 10.20.2.5 上执行:

bash 复制代码
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d_%H%M%S)

修改或追加:

bash 复制代码
grep -qEi '^[[:space:]]*AllowTcpForwarding[[:space:]]+' /etc/ssh/sshd_config \
  && sed -i -E 's/^[[:space:]]*AllowTcpForwarding[[:space:]]+.*/AllowTcpForwarding yes/I' /etc/ssh/sshd_config \
  || echo 'AllowTcpForwarding yes' >> /etc/ssh/sshd_config

检查配置:

bash 复制代码
sshd -t

无输出表示语法正确。

重载服务:

bash 复制代码
systemctl reload sshd

如果 reload 不可用:

bash 复制代码
systemctl restart sshd

确认:

bash 复制代码
sshd -T | grep -Ei "allowtcpforwarding|permitopen|allowstreamlocalforwarding"

期望:

text 复制代码
allowtcpforwarding yes
allowstreamlocalforwarding yes
permitopen any

5.5 注意 Match 块覆盖

如果改完仍然是 allowtcpforwarding no,检查:

bash 复制代码
grep -nEi "AllowTcpForwarding|PermitOpen|AllowStreamLocalForwarding|Match" /etc/ssh/sshd_config

如果看到:

text 复制代码
Match User root
    AllowTcpForwarding no

则需要修改 Match 块内部配置。


6. 远程端口转发:让远端使用 Windows 本地代理

6.1 这是远程端口转发 -R

命令:

powershell 复制代码
ssh -N -T -R 127.0.0.1:10240:127.0.0.1:7897 bms-25

含义:

text 复制代码
bms-25 上的 127.0.0.1:10240
    ↓ SSH 隧道
Windows 本地的 127.0.0.1:7897

所以,在远端访问:

bash 复制代码
127.0.0.1:10240

实际会访问 Windows 本地:

text 复制代码
127.0.0.1:7897

6.2 临时启动代理隧道

在 Windows PowerShell 执行:

powershell 复制代码
ssh -N -T -R 127.0.0.1:10240:127.0.0.1:7897 `
  -o ServerAliveInterval=30 `
  -o ServerAliveCountMax=6 `
  -o TCPKeepAlive=yes `
  -o ExitOnForwardFailure=yes `
  -o ConnectTimeout=15 `
  bms-25

保持这个窗口不关闭。

6.3 测试远端代理

在远端执行:

bash 复制代码
curl -x http://127.0.0.1:10240 https://github.com -I

如果返回 HTTP 响应头,说明转发成功。

6.4 设置远端代理环境变量

bash 复制代码
export http_proxy=http://127.0.0.1:10240
export https_proxy=http://127.0.0.1:10240
export HTTP_PROXY=http://127.0.0.1:10240
export HTTPS_PROXY=http://127.0.0.1:10240

测试:

bash 复制代码
curl https://github.com -I

6.5 Git 代理

设置:

bash 复制代码
git config --global http.proxy http://127.0.0.1:10240
git config --global https.proxy http://127.0.0.1:10240

取消:

bash 复制代码
git config --global --unset http.proxy
git config --global --unset https.proxy

7. 将远程代理转发写进 SSH config

7.1 不建议直接写进普通 Host

可以直接写:

sshconfig 复制代码
Host 192.168.206.112
    HostName 192.168.206.112
    User pcljgy
    RemoteForward 127.0.0.1:10240 127.0.0.1:7897

但不推荐用于 VS Code,因为 VS Code Remote-SSH 会开多条 SSH 连接。每条连接都会尝试占用远端 127.0.0.1:10240,容易冲突、卡住或出现:

text 复制代码
remote port forwarding failed for listen port 10240

更稳的方式是分成两个 Host:

text 复制代码
普通 Host:给 VS Code / 普通 SSH 使用
-proxy Host:专门维持代理隧道

7.2 bms-25 推荐配置

sshconfig 复制代码
Host bms-gateway
    HostName 10.42.206.102
    User root
    IdentityFile C:/Users/24385/.ssh/id_rsa
    IdentitiesOnly yes
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

Host bms-25
    HostName 10.20.2.5
    User root
    IdentityFile C:/Users/24385/.ssh/id_rsa
    IdentitiesOnly yes
    ProxyCommand ssh -q bms-gateway /usr/bin/nc %h %p
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

Host bms-25-proxy
    HostName 10.20.2.5
    User root
    IdentityFile C:/Users/24385/.ssh/id_rsa
    IdentitiesOnly yes
    ProxyCommand ssh -q bms-gateway /usr/bin/nc %h %p
    RemoteForward 127.0.0.1:10240 127.0.0.1:7897
    ExitOnForwardFailure yes
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes
    RequestTTY no
    SessionType none

使用:

powershell 复制代码
ssh bms-25        # 普通登录 / VS Code
ssh bms-25-proxy  # 代理隧道

7.3 192.168.206.112 推荐配置

sshconfig 复制代码
Host 192.168.206.112
    HostName 192.168.206.112
    User pcljgy
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

Host 192.168.206.112-proxy
    HostName 192.168.206.112
    User pcljgy
    RemoteForward 127.0.0.1:10240 127.0.0.1:7897
    ExitOnForwardFailure yes
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes
    RequestTTY no
    SessionType none

使用:

powershell 复制代码
ssh 192.168.206.112        # 普通登录 / VS Code
ssh 192.168.206.112-proxy  # 代理隧道

7.4 192.168.206.140_jgy 推荐配置

sshconfig 复制代码
Host 192.168.206.140_jgy
    HostName 192.168.206.140
    User pcljgy
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

Host 192.168.206.140_jgy-proxy
    HostName 192.168.206.140
    User pcljgy
    RemoteForward 127.0.0.1:10240 127.0.0.1:7897
    ExitOnForwardFailure yes
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes
    RequestTTY no
    SessionType none

使用:

powershell 复制代码
ssh 192.168.206.140_jgy        # 普通登录 / VS Code
ssh 192.168.206.140_jgy-proxy  # 代理隧道

7.5 为什么 VS Code 不能连接 -proxy Host

-proxy Host 里有:

sshconfig 复制代码
RequestTTY no
SessionType none

含义是:该连接只做隧道,不启动远程 shell。

VS Code 需要远程执行脚本、安装和启动 VS Code Server,因此不适合连接 -proxy Host。

正确用法:

用途 Host
VS Code 远程开发 bms-25
bms-25 代理隧道 bms-25-proxy
VS Code 远程开发 192.168.206.112
192.168.206.112 代理隧道 192.168.206.112-proxy

7.6 如果坚持直接写进普通 Host

可以这样写,但要降低冲突影响:

sshconfig 复制代码
Host 192.168.206.112
    HostName 192.168.206.112
    User pcljgy
    RemoteForward 127.0.0.1:10240 127.0.0.1:7897
    ExitOnForwardFailure no
    ServerAliveInterval 30
    ServerAliveCountMax 6
    TCPKeepAlive yes

这里建议用:

sshconfig 复制代码
ExitOnForwardFailure no

不要用:

sshconfig 复制代码
ExitOnForwardFailure yes

否则 VS Code 多连接时,如果第二条连接发现远端 10240 已被占用,可能直接失败。


8. 后台启动代理隧道

8.1 前台启动

powershell 复制代码
ssh bms-25-proxy

或:

powershell 复制代码
ssh 192.168.206.112-proxy

窗口无输出、不进入 shell、一直挂着,是正常现象。

8.2 后台隐藏启动

powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "ssh.exe" -ArgumentList "bms-25-proxy"
powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "ssh.exe" -ArgumentList "192.168.206.112-proxy"
powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "ssh.exe" -ArgumentList "192.168.206.140_jgy-proxy"

如果 ssh.exe 不在 PATH 中:

powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "C:\Program Files (x86)\OpenSSH-Win64\ssh.exe" -ArgumentList "bms-25-proxy"

8.3 查看 SSH 进程

powershell 复制代码
Get-Process ssh

8.4 关闭所有 SSH 进程

powershell 复制代码
Stop-Process -Name ssh

注意:这会关闭所有名为 ssh 的进程,包括普通 SSH 和隧道。


9. 保活参数解释

sshconfig 复制代码
ServerAliveInterval 30
ServerAliveCountMax 6
TCPKeepAlive yes

整体含义:每 30 秒检查一次 SSH 连接;连续 6 次无响应则断开,大约 3 分钟。

9.1 ServerAliveInterval 30

如果 30 秒内没有收到服务器任何数据,SSH 客户端向服务器发送 SSH 协议层保活包。

9.2 ServerAliveCountMax 6

连续 6 次保活探测无响应后,SSH 客户端断开连接。

text 复制代码
30 秒 × 6 = 180 秒

9.3 TCPKeepAlive yes

启用操作系统 TCP 层面的 keepalive。它更底层,但检测通常更慢。

9.4 区别

参数 层级 作用
ServerAliveInterval SSH 协议层 定期发送 SSH 保活包
ServerAliveCountMax SSH 协议层 连续多少次无响应后断开
TCPKeepAlive TCP 系统层 操作系统检测 TCP 连接

这些参数只能检测坏连接并退出,不能自动重连。若要自动重连,可考虑 autossh、Windows 任务计划程序或 PowerShell 循环脚本。


10. 常见报错速查

10.1 unknown option -- -

命令:

bash 复制代码
ssh --help

原因:OpenSSH 通常不支持 --help

替代:

bash 复制代码
ssh -h
man ssh

10.2 channel 0: open failed: administratively prohibited

常见于:

powershell 复制代码
ssh -J root@10.42.206.102 root@10.20.2.5

原因:跳板机禁止 TCP forwarding。

解决:改用 ProxyCommand + nc,或在跳板机开启 AllowTcpForwarding yes

10.3 channel 3: open failed: administratively prohibited

常见于 VS Code Remote-SSH。

原因:目标机禁止 TCP forwarding,导致 VS Code tunnel 建立失败。

解决:在目标机开启:

text 复制代码
AllowTcpForwarding yes

10.4 VS Code 连接 -proxy Host 卡住

现象:

text 复制代码
设置 SSH 主机 192.168.206.112-proxy: 正在初始化 VS Code 服务器

原因:-proxy Host 是隧道,不适合 VS Code 远程开发。

解决:VS Code 连接普通 Host,代理隧道用 PowerShell 单独启动。

10.5 remote port forwarding failed for listen port 10240

原因:远端 127.0.0.1:10240 已被其他 SSH 隧道占用。

排查:

bash 复制代码
ss -lntp | grep 10240

解决:关闭已有隧道,或换端口,例如 10241


11. 速查命令

测试普通 SSH:

powershell 复制代码
ssh bms-25
ssh 192.168.206.112
ssh 192.168.206.140_jgy

测试 ProxyCommand:

powershell 复制代码
ssh -o "ProxyCommand=ssh -q root@10.42.206.102 /usr/bin/nc %h %p" root@10.20.2.5

启动 bms-25 代理:

powershell 复制代码
ssh bms-25-proxy

后台启动 bms-25 代理:

powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "ssh.exe" -ArgumentList "bms-25-proxy"

远端设置代理:

bash 复制代码
export http_proxy=http://127.0.0.1:10240
export https_proxy=http://127.0.0.1:10240

远端测试代理:

bash 复制代码
curl -x http://127.0.0.1:10240 https://github.com -I

检查 sshd 转发能力:

bash 复制代码
sshd -T | grep -Ei "allowtcpforwarding|permitopen|allowstreamlocalforwarding|gatewayports"

12. 安全注意事项

只上传公钥:

text 复制代码
id_rsa.pub

不要上传私钥:

text 复制代码
id_rsa

推荐远程转发只绑定远端本机:

sshconfig 复制代码
RemoteForward 127.0.0.1:10240 127.0.0.1:7897

不建议随意开放到内网:

sshconfig 复制代码
RemoteForward 0.0.0.0:10240 127.0.0.1:7897

因为这会把代理暴露给远端内网其他机器,并且需要远端 sshd 允许:

text 复制代码
GatewayPorts yes

或:

text 复制代码
GatewayPorts clientspecified

13. 最终推荐工作流

VS Code 远程开发连接普通 Host:

text 复制代码
bms-25
192.168.206.112
192.168.206.140_jgy

不要用 VS Code 连接:

text 复制代码
bms-25-proxy
192.168.206.112-proxy
192.168.206.140_jgy-proxy

代理隧道用 PowerShell 单独启动:

powershell 复制代码
ssh bms-25-proxy

或后台启动:

powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath "ssh.exe" -ArgumentList "bms-25-proxy"

远端使用代理:

bash 复制代码
export http_proxy=http://127.0.0.1:10240
export https_proxy=http://127.0.0.1:10240
curl https://github.com -I

14. 核心结论

text 复制代码
1. 公钥放在哪里,取决于你登录哪个远端用户。
2. Windows 本地只保留私钥 id_rsa,服务器只放公钥 id_rsa.pub。
3. ProxyJump 失败时,可以用 ProxyCommand + nc 代替。
4. VS Code Remote-SSH 需要目标机允许 AllowTcpForwarding yes。
5. 远程代理转发使用 -R / RemoteForward。
6. 不建议把 RemoteForward 直接写进 VS Code 使用的普通 Host。
7. 最稳方案是:普通 Host 用于 VS Code;-proxy Host 用于代理隧道。
8. ServerAliveInterval / ServerAliveCountMax / TCPKeepAlive 用于检测坏连接,但不会自动重连。