修复 VS Code Remote SSH 提示远程主机禁用 TCP 端口转发
太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处
VS CodeRemote SSHOpenSSHsshdTCP 端口转发

修复 VS Code Remote SSH 提示远程主机禁用 TCP 端口转发

使用 VS Code 的 Remote - SSH 扩展连接远程服务器时,可能遇到下面的错误:

错误: 远程主机上似乎禁用了 TCP 端口转发。
确保 sshd_config 具有 AllowTcpForwarding yes。
如有需要,请与系统管理员联系。

这个错误通常不是 VS Code 无法登录服务器,而是 SSH 登录成功后,VS Code 建立远程通信通道时被服务端的 sshd 拒绝。Remote - SSH 需要使用 SSH 隧道连接远程 VS Code Server,因此服务器必须允许相应用户进行 TCP 端口转发。

修改前先确认权限和风险

以下操作需要远程服务器的管理员权限。若服务器由公司、学校或云平台统一管理,应先联系管理员,因为禁用端口转发可能是一项刻意设置的安全策略。

AllowTcpForwarding yes 会允许 SSH 用户创建 TCP 隧道。不要为了修复连接而同时启用 root 密码登录、关闭防火墙或修改与问题无关的 SSH 安全选项。共享服务器更适合只对指定用户或用户组开放,后文会给出配置方法。

Linux 服务器

1. 查找实际生效的配置

OpenSSH 的主配置通常位于:

/etc/ssh/sshd_config

现代系统还可能通过下面的目录加载拆分配置:

/etc/ssh/sshd_config.d/*.conf

先查看主配置是否使用了 Include,并搜索所有与转发有关的设置:

sudo grep -nE '^[[:space:]]*(Include|AllowTcpForwarding|DisableForwarding|PermitOpen|Match)\b' \
  /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null

需要特别留意以下情况:

  • AllowTcpForwarding no:明确禁止 TCP 端口转发。
  • DisableForwarding yes:禁止包括 TCP 转发在内的所有转发功能,其优先级不能靠 AllowTcpForwarding yes 抵消。
  • PermitOpen:可能限制客户端只能转发到指定目标。
  • Match UserMatch GroupMatch Address:后续配置可能只针对当前登录用户生效。

2. 启用 TCP 端口转发

编辑实际使用的配置文件:

sudoedit /etc/ssh/sshd_config

确保全局配置中存在:

AllowTcpForwarding yes

如果存在全局生效的 DisableForwarding yes,应删除它、注释它,或者根据安全要求调整限制。不要简单地在文件末尾追加配置:如果末尾仍处于某个 Match 块中,新配置只会应用于该匹配范围。

如果只想允许 VS Code 使用者转发,可以按用户限制。全局保持禁用,然后在文件末尾添加:

AllowTcpForwarding no

Match User TARGET_USER
    AllowTcpForwarding yes

TARGET_USER 替换为实际 SSH 用户名。也可以使用 Match Group GROUP_NAME 对用户组授权。

3. 检查语法和最终配置

修改后先检查配置语法,成功时命令通常没有输出:

sudo sshd -t

然后查看普通全局配置的解析结果:

sudo sshd -T | grep -E 'allowtcpforwarding|disableforwarding|permitopen'

若使用了 Match 条件,应模拟目标用户和连接来源,避免被全局结果误导:

sudo sshd -T \
  -C user=TARGET_USER,addr=CLIENT_IP,host=HOST \
  | grep -E 'allowtcpforwarding|disableforwarding|permitopen'

TARGET_USERCLIENT_IPHOST 替换为实际值。期望至少看到:

allowtcpforwarding yes

4. 重新加载 SSH 服务

Ubuntu、Debian 常见服务名是 ssh

sudo systemctl reload ssh

RHEL、CentOS、Rocky Linux、AlmaLinux 等系统常见服务名是 sshd

sudo systemctl reload sshd

如果不确定服务名,可以查看:

systemctl status ssh sshd --no-pager

优先使用 reload,并暂时保留当前已连接的 SSH 会话。确认新连接成功前不要关闭当前会话,以免配置错误导致自己被锁在服务器外。

飞牛 fnOS 为什么会专门关闭转发

在飞牛 fnOS 上执行前文的搜索命令,可能得到类似结果:

/etc/ssh/sshd_config:12:Include /etc/ssh/sshd_config.d/*.conf
/etc/ssh/sshd_config.d/trim_sshd.conf:1:AllowTcpForwarding no

这已经能够确认 VS Code 报错的直接原因:主配置加载了 sshd_config.d 目录,而飞牛提供的 trim_sshd.conf 明确禁止了 TCP 端口转发。

飞牛没有在公开文档中解释这个文件的具体设计目的。根据文件名、配置内容以及 NAS 的使用边界判断,它应当属于系统的 SSH 裁剪或安全加固配置。NAS 通常用于存储和运行内部服务,而不是作为通用开发服务器或 SSH 跳板机。禁用转发可以降低以下风险:

  • SSH 用户借助 NAS 访问原本无法从外部访问的内网服务。
  • 使用 SSH 隧道绕过防火墙或服务端口限制。
  • 把 NAS 作为 SOCKS 代理或跳板机使用。
  • 将只监听在服务器 127.0.0.1 上的管理服务间接暴露出去。

因此,这一行通常不是配置错误,而是飞牛选择的安全默认值。普通终端 SSH 登录不需要 TCP 转发,所以仍然可以正常登录;VS Code Remote - SSH 需要通过 SSH 隧道连接远程 VS Code Server,才会触发这个限制。

不要只在主配置末尾追加 yes

OpenSSH 对多数单值配置采用“先读取到的有效值生效”规则。飞牛的主配置在前部执行:

Include /etc/ssh/sshd_config.d/*.conf

如果 trim_sshd.conf 已经先设置了 AllowTcpForwarding no,在 /etc/ssh/sshd_config 后面简单追加 AllowTcpForwarding yes 可能不会覆盖它。最终结果必须通过 sshd -T 判断,不能只根据配置文件中的最后一行判断。

也不建议直接修改 trim_sshd.conf。这是系统提供的文件,飞牛升级、修复或重新保存 SSH 设置时可能重建它。更容易维护的做法是创建一个名称排序更靠前的本地配置文件:

echo 'AllowTcpForwarding yes' \
  | sudo tee /etc/ssh/sshd_config.d/00-local-vscode.conf

00-local-vscode.conf 会在 trim_sshd.conf 之前被读取,使本地设置先被采用。独立文件也能清楚区分用户配置和系统配置,但仍应在飞牛系统升级后重新验证,因为设备系统可能调整 SSH 配置生成逻辑。

验证飞牛上的最终配置

先检查语法,再查看 sshd 实际解析出的结果:

sudo sshd -t
sudo sshd -T | grep -i allowtcpforwarding

期望输出:

allowtcpforwarding yes

如果使用了 Match 条件,还应针对实际用户验证:

sudo sshd -T \
  -C user=TARGET_USER,addr=CLIENT_IP,host=HOST \
  | grep -E 'allowtcpforwarding|disableforwarding|permitopen'

确认语法和最终值正确后,重新加载服务:

sudo systemctl reload ssh

如果服务名不是 ssh,再尝试:

sudo systemctl reload sshd

保留当前 SSH 窗口,然后新开一个终端测试登录和端口转发。确认新连接正常后,再让 VS Code Remote - SSH 重新连接。

是否应该在飞牛上启用

如果这是个人管理的 NAS、只允许可信用户登录,并且 VS Code 通过可信局域网或 VPN 连接,可以在了解风险后启用。上述配置会为所有能够 SSH 登录且未被其他规则限制的用户开放 TCP 转发;共享设备或公网可访问的 NAS 应谨慎使用,并同时限制 SSH 登录用户、认证方式、防火墙来源和 VPN 访问范围。

如果设备由公司或其他管理员维护,不应绕过系统策略。应由管理员判断是否开放,并在系统升级后再次执行 sshd -T 检查。

Windows OpenSSH Server

如果远程服务器是 Windows,管理员应编辑:

C:\ProgramData\ssh\sshd_config

确保配置允许转发:

AllowTcpForwarding yes

在管理员 PowerShell 中检查配置并重启服务:

& "$env:WINDIR\System32\OpenSSH\sshd.exe" -t
Restart-Service sshd

同样需要检查文件中的 Match 块、DisableForwardingPermitOpen 是否对当前用户施加了额外限制。

在客户端直接验证端口转发

在重新尝试 VS Code 前,可以先从本机建立一个只用于验证的本地转发:

ssh -v -N -L 127.0.0.1:18080:127.0.0.1:22 TARGET_USER@HOST

参数含义如下:

  • -v:显示详细日志。
  • -N:不执行远程命令,只建立转发。
  • -L:让本机 127.0.0.1:18080 转发到服务器看到的 127.0.0.1:22

如果命令保持运行且日志没有出现 administratively prohibited,说明 SSH 端口转发已经可以建立。按 Ctrl+C 结束测试即可。本机的 18080 若已被占用,可以换成其他空闲端口。

然后在 VS Code 中执行:

  1. 打开命令面板。
  2. 运行 Remote-SSH: Kill VS Code Server on Host...,选择目标主机。
  3. 再运行 Remote-SSH: Connect to Host... 重新连接。

若菜单中没有清理远程 Server 的命令,也可以先直接重连;清理不是启用转发的必要步骤。

配置正确但仍然报错

修改的不是当前 sshd 使用的配置

服务器可能启动了另一个 sshd 实例,使用了 -f 指定的配置文件,或者容器内外各有一套 SSH 服务。检查进程启动参数和服务定义:

ps -ef | grep '[s]shd'
systemctl cat sshd 2>/dev/null || systemctl cat ssh 2>/dev/null

配置被 Match 块覆盖

只运行 sshd -T 看到的是普通全局结果。涉及 Match 时,应使用前文的 sshd -T -C ...,按实际用户、客户端地址和主机名计算最终值。

authorized_keys 对单个密钥禁用了转发

即使 sshd_config 允许转发,用户的 ~/.ssh/authorized_keys 仍可能在公钥前使用以下限制:

no-port-forwarding
restrict

restrict 默认也会禁用端口转发;只有在安全策略允许时,管理员才应移除限制或配合 port-forwarding 选项进行精确授权。

堡垒机或代理主机限制了转发

如果本机 SSH 配置使用了 ProxyJumpProxyCommand,需要判断报错来自最终服务器还是中间主机。可以先在终端运行:

ssh -vvv TARGET_USER@HOST

结合 VS Code 的“输出”面板,选择 Remote - SSH 日志,确认实际连接的主机、用户和 SSH 配置文件。

服务没有重新加载成功

检查服务状态和近期日志:

sudo systemctl status sshd --no-pager
sudo journalctl -u sshd -n 50 --no-pager

如果系统使用服务名 ssh,将命令中的 sshd 改为 ssh

结论

这类错误的核心是服务端 SSH 策略拒绝了 VS Code Remote - SSH 所需的 TCP 隧道。通常按下面的顺序即可定位:

  1. 搜索主配置、拆分配置和 Match 块。
  2. 确认 AllowTcpForwarding yes,同时排除 DisableForwardingPermitOpen 和密钥级限制。
  3. 使用 sshd -t 检查语法,使用 sshd -T -C 验证目标用户的最终配置。
  4. 重新加载 SSH 服务,并用命令行 ssh -L 验证后再连接 VS Code。

如果没有服务器管理员权限,客户端无法绕过服务端明确设置的转发禁令,只能请管理员按安全策略为指定用户或用户组开放所需权限。