Cursor Remote SSH 与 SELinux

发布于

事情起因很 mundane:之前一直用 Cursor Remote SSH 连家里 Fedora 工作站写代码,某天突然连不上了。终端里 ssh jamie@wj.luchador.dev 照样能登录,就是 Cursor 卡在「Connecting…」然后报一堆 channel open failed

今天终于抽空查。各种 AI 给出的「经典解法」试了一圈,差点以为自己 sshd 配错了。最后在 Cockpit 的 SELinux 页看到拒绝日志,再对照系统更新时间和 ausearch,才把锅扣到 8 月下旬的 selinux-policy 更新上——和 Cursor 本身关系不大。

症状:SSH 能登,Cursor 不能

Cursor 日志里典型路径是:

  1. SSH 握手成功(几百毫秒)
  2. 远程 cursor-server 安装/启动成功,报告 codeListeningOn==42539 之类
  3. 本地通过 ssh -D(SOCKS)去连远程 127.0.0.1:42539 时失败
  4. 反复重试后提示:
Failed to connect to Cursor code server.
Ensure that your remote host ssh config has 'AllowTcpForwarding yes' ...
channel 3: open failed: connect failed: open failed

终端 SSH 不需要端口转发,所以 「命令行能连、Cursor 不能连」 本身就把问题范围缩小了:不是认证、不是防火墙挡 22 端口,而是转发链路断了。

AI 经典解法:试了一圈,都不是根因

下面这几条在社区里出现频率极高,我也都验证了——对你这种 Fedora 44 + Enforcing SELinux 的组合,单独做往往不够,甚至会误导。

AllowTcpForwarding

远程查注释行:

sudo grep -i AllowTcpForwarding /etc/ssh/sshd_config
#AllowTcpForwarding yes

注释掉 不等于默认拒绝。实际生效值:

sudo sshd -T | grep -i allowtcpforwarding
# allowtcpforwarding yes

日志里若是 sshd 配置拒绝,通常会写 administratively prohibited;我的是 connect failed——说明 sshd 允许转发请求,但 连目标端口时失败,方向就不在 sshd_config 了。

sshd_forward_ports

Fedora 14 时代的老 boolean,很多文章还在写:

sudo setsebool -P sshd_forward_ports 1

在 Fedora 44 上:

getsebool sshd_forward_ports
# Error getting active value for sshd_forward_ports

策略里已经没这个开关了。 AI 训练语料里它出现太多,容易把人带进死胡同。

本地代理

Mac 上有 Clash 一类代理时,有时会影响 Remote SSH。我这次 ssh -v 里是直连 wj.luchador.dev:22(IPv6),没有 ProxyCommand;且 纯终端 ssh -D 在 Enforcing 下同样失败,所以本地代理不是主因。

Mac 上 ssh -D 自测(决定性)

终端 1:

ssh -N -D 1080 jamie@wj.luchador.dev

终端 2:

nc -zv -X 5 -x 127.0.0.1:1080 127.0.0.1 22
nc -zv -X 5 -x 127.0.0.1:1080 127.0.0.1 5432

Enforcing 下:Broken pipe / channel open failed
这和 Cursor 用的是同一条机制——Cursor 没坏,转发层坏了。

真正根因:SELinux + 8 月策略更新

setenforce 0 对比

sudo setenforce 0

Mac 上再跑上面的 nc -X22 和 5432 都 succeeded。

说明:不是 postgres 没监听、不是 Cursor 安装失败,是 SELinux 在 Enforcing 下拦 sshd-sessionname_connect

Cockpit 与 AVC 日志

Cockpit → SELinux 策略页里反复出现类似拒绝(端口每次不同,Cursor 动态分配):

SELinux 正在阻止 sshd-sessionname_connect tcp_socket 进行端口 41035 访问。

ausearch 里能对上整段排查过程:

avc: denied { name_connect } for comm="sshd-session"
  dest=22        → ssh_port_t
  dest=5432      → postgresql_port_t
  dest=41035     → ephemeral_port_t    # cursor-server 监听口
  scontext=...:sshd_session_t:...
  permissive=0   # Enforcing,真拦

早期 ausearch 为空,是因为部分拒绝曾被 dontaudit 静默;后来在 Cockpit / 打开 dontaudit 调试后才看见全貌。

系统更新时间线(和「以前好用、突然不行」对齐)

家里机器上:

2026-08-22  openssh-10.2p1-14.fc44
2026-08-25  selinux-policy-targeted-44.7-1.fc44

OpenSSH 10 起,sshd 拆成 sshd-authsshd-session 等组件,日志里进程名变成 sshd-session,SELinux 域是 sshd_session_t

selinux-policy 44.6 / 44.7(8 月 14 日进 testing,25 日装到机器)changelog 里有一条关键变更:

Remove permissive setting for sshd_auth_t and sshd_session_t

含义是:以前 sshd_session_t 处于 permissive 域——违反策略只记日志、不真拦;更新后同一类操作在 Enforcing 下 直接拒绝

所以时间线很顺:

阶段 现象
更新前 Cursor Remote SSH 正常(转发违规但被 permissive 放过)
8/22–8/25 更新后 同样操作被 SELinux 执行拒绝 → Cursor / ssh -D
终端 ssh 登录 一直正常(不需要 name_connect 转发)

不是 Cursor 某版更新单独搞坏了 SSH,而是 Linux 发行版安全策略 + OpenSSH 10 架构变更叠在一起。

修复

Cockpit 对这条 AVC 的建议是启用 boolean nis_enabled(名字像 NIS,实际是策略里一组「允许连非标准端口」的宽松规则,setroubleshoot 常拿它修 name_connect):

sudo setsebool -P nis_enabled 1
getsebool nis_enabled   # --> on

或在 Cockpit SELinux 页对相应拒绝点 「采用该解决方案」

然后确认仍在 Enforcing:

getenforce   # Enforcing

Mac 上再测 ssh -D + nc,最后清一次远程 Cursor 残留并重连:

pkill -f cursor-server || true
rm -rf ~/.cursor-server

不建议长期 setenforce 0nis_enabled 比关整个 SELinux 窄得多。若介意范围太大,可以用 audit2allow 做只针对 sshd_session_t 的本地模块(Cockpit 方案 2)。

排查流程(给以后的自己)

sequenceDiagram
    participant Mac as Mac_Cursor_or_ssh_D
    participant SSH as SSH_session
    participant Remote as Fedora_sshd_session
    participant SEL as SELinux

    Mac->>SSH: ssh -D 建立隧道
    SSH->>Remote: 登录成功
    Remote->>Remote: 启动 cursor-server
    Mac->>SSH: SOCKS 连 127.0.0.1:动态端口
    SSH->>Remote: direct-tcpip 转发
    Remote->>SEL: name_connect 本机端口
    SEL--xRemote: Enforcing 拒绝
    Note over Mac,SEL: channel open failed

简表:

检查项 正常时应看到
sshd -T | grep allowtcpforwarding yes
终端 ssh 能登录
ssh -D + nc -X Enforcing 下也应通(修复后)
ausearch -m avc | grep sshd-session 修复后无新拒绝
getsebool nis_enabled on(若采用 Cockpit 方案)

参考链接(策略更新与社区讨论)

本次直接相关的 Fedora 更新

OpenSSH 10 组件拆分(为何日志里是 sshd-session)

同类问题的 Bug / 讨论(agent 转发、X11 等)

Cursor / VS Code Remote SSH 通用说明(报错文案相同,根因未必相同)

SELinux boolean 文档(nis_enabled 命名很迷惑)

后记

这次最大的教训:「终端 SSH 能连」不能推出「Remote SSH 能连」;Cursor / VS Code 在底下偷偷用了 ssh -D,碰的是 sshd 转发 + SELinux name_connect 这条更窄的路。

AI 给的 AllowTcpForwarding、sshd_forward_ports 在 2026 年的 Fedora 44 上经常 不是 答案;Cockpit / ausearch + 对照 rpm -qa --last 才把时间线和根因对齐。

发这篇主要是给以后的自己和同样「家里 Fedora + Cursor Remote」的人留个坑位记录:系统更了,策略收紧了,不是你突然不会用 SSH 了。