Skip to content

Commit 3c11df8

Browse files
committed
docs(vscode): 补充 SSH 远程连接配置实例
1 parent 433d647 commit 3c11df8

6 files changed

Lines changed: 205 additions & 18 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"file": ".trellis/spec/guides/index.md", "reason": "检查文档/配置改动是否保持最小变量与可回滚。"}
2+
{"file": ".trellis/tasks/05-12-ssh-remoteforward-vscode-docs/research/openssh-client-options.md", "reason": "校验文档建议与 OpenSSH 选项语义一致。"}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"file": ".trellis/spec/guides/index.md", "reason": "通用修改前检查与变更边界提醒。"}
2+
{"file": ".trellis/tasks/05-12-ssh-remoteforward-vscode-docs/research/openssh-client-options.md", "reason": "OpenSSH 客户端配置选项语义依据。"}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# SSH RemoteForward 断联与 VS Code 文档优化
2+
3+
## Goal
4+
5+
排查 Windows 侧 SSH 连接 Linux 服务器时的间歇断联问题,先通过关闭常规连接里的 `RemoteForward` 来观察是否由多个客户端抢占同一个远端端口触发,同时更新 VS Code Remote SSH 文档,避免后续配置继续把代理隧道混入 VS Code 或 zellij 会话。
6+
7+
## What I already know
8+
9+
* 本机 `C:\Users\mudssky\.ssh\config` 中多个普通 Host 曾直接配置 `RemoteForward 7890 127.0.0.1:7890``RemoteForward 7890 localhost:7890`
10+
* zellij 项目 Host 使用 `RequestTTY yes``RemoteCommand ... zellij attach -c ...`
11+
* 用户确认当前不确定断联是否由 `RemoteForward` 引发,策略是先关掉观察。
12+
* 用户希望 VS Code 侧加 `ServerAliveInterval 60``ServerAliveCountMax 3``ConnectTimeout 30`,zellij 侧暂不加,避免混淆观察结果。
13+
* `docs/cheatsheet/vscode/remote/ssh-proxy.md` 已有 RemoteForward、VS Code、zellij 混用断联排查说明,但当前“VS Code 自动化配置”部分仍容易鼓励把 `RemoteForward` 放入 VS Code Host。
14+
15+
## Requirements
16+
17+
* 注释掉普通 Host 中现有 `RemoteForward 7890`,保留原配置作为可恢复记录。
18+
* 只给普通/VS Code 连接 Host 增加 `ServerAliveInterval 60``ServerAliveCountMax 3``ConnectTimeout 30`
19+
* 暂不修改 zellij Host 的保活参数,保留其原有 `RequestTTY``RemoteCommand` 行为。
20+
* 更新 VS Code Remote SSH 文档:默认建议不要让 VS Code Host 直接声明 `RemoteForward`;如需代理,优先使用独立隧道 Host 或临时 `ssh -N -R`
21+
* 文档补充本次观察法:先关闭 `RemoteForward`,仅给 VS Code Host 加保活,观察断联是否缓解。
22+
* 文档补充可直接套用的 SSH config 实例,覆盖 VS Code、zellij、独立代理隧道三种入口。
23+
24+
## Acceptance Criteria
25+
26+
* [x] 本机 SSH config 中普通 Host 不再启用 `RemoteForward 7890`
27+
* [x] 本机 SSH config 中普通/VS Code Host 具备 `ServerAliveInterval 60``ServerAliveCountMax 3``ConnectTimeout 30`
28+
* [x] zellij Host 未新增保活参数。
29+
* [x] VS Code SSH 反向代理文档不再把 `RemoteForward` 放入 VS Code Host 作为默认推荐。
30+
* [x] VS Code SSH 反向代理文档包含 VS Code、zellij、独立 tunnel 三种配置实例。
31+
* [x] 可通过 `ssh -G` 验证关键 Host 配置解析结果。
32+
33+
## Definition of Done
34+
35+
* 文档与本机配置改动完成。
36+
* 配置解析验证通过。
37+
* 仅修改文档/配置,不执行根目录 `pnpm qa`
38+
39+
## Out of Scope
40+
41+
* 不修改远端 `sshd_config`
42+
* 不调整 zellij Host 的 `RemoteCommand` 写法。
43+
* 不新增单元测试。
44+
* 不直接判定断联根因,保留观察结论。
45+
46+
## Research References
47+
48+
* [`research/openssh-client-options.md`](research/openssh-client-options.md) — OpenSSH 客户端选项语义确认。
49+
50+
## Technical Approach
51+
52+
采用最小变量实验:关闭 `RemoteForward`,只在普通/VS Code Host 上增加客户端保活与连接超时参数;zellij Host 保持原状。文档同步改为“独立隧道优先、VS Code Host 保持干净”的建议。
53+
54+
## Decision (ADR-lite)
55+
56+
**Context**: 当前断联根因未确认,`RemoteForward` 多连接冲突只是候选原因之一。
57+
58+
**Decision**: 不一次性重构全部 Host;先注释普通 Host 的 `RemoteForward` 并给 VS Code 侧增加连接参数,zellij 侧不动。
59+
60+
**Consequences**: 观察期内远端 `127.0.0.1:7890` 代理不会自动随普通连接建立;如果断联仍出现,后续再排查网络空闲超时、VS Code 重连、远端 sshd 限制或 zellij attach 生命周期。
61+
62+
## Technical Notes
63+
64+
* 涉及文件:`C:\Users\mudssky\.ssh\config``docs/cheatsheet/vscode/remote/ssh-proxy.md`
65+
* Context7 查询 OpenSSH 文档,确认 `RemoteForward``-R``ServerAliveInterval``ServerAliveCountMax``TCPKeepAlive` 等选项语义。
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# OpenSSH 客户端选项语义确认
2+
3+
## 来源
4+
5+
* Context7:`/openssh/openssh-portable`
6+
* 查询主题:`ssh_config RemoteForward ExitOnForwardFailure ServerAliveInterval ServerAliveCountMax TCPKeepAlive RequestTTY RemoteCommand VS Code Remote SSH 多连接 端口转发配置建议`
7+
8+
## 结论
9+
10+
* `RemoteForward`/`ssh -R` 用于把远端监听端口转发到客户端侧可访问的目标地址与端口。
11+
* `ServerAliveInterval``ServerAliveCountMax` 是客户端侧保活配置;例如 `60``3` 表示每 60 秒发送一次服务端保活探测,连续 3 次无响应后客户端认为连接不可用。
12+
* `ConnectTimeout` 只影响建立连接阶段,适合避免网络异常时长时间卡住,不用于保持已建立连接。
13+
* `ExitOnForwardFailure yes` 可让端口转发绑定失败时直接失败,避免进入“SSH 已连接但代理未建立”的半成功状态;本轮先关闭 `RemoteForward`,所以不作为活跃配置重点。
14+
15+
## 对本仓库任务的约束
16+
17+
* 当前目标是定位问题,不宜同时修改 zellij Host 的生命周期参数。
18+
* VS Code Remote SSH 常会建立多条连接,文档应避免把同一个 `RemoteForward 7890` 放进 VS Code Host 作为默认方案。
19+
* 如果后续需要恢复代理,优先使用专用隧道 Host 或临时 `ssh -N -R`,并配合 `ExitOnForwardFailure yes` 做显性失败。
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"id": "ssh-remoteforward-vscode-docs",
3+
"name": "ssh-remoteforward-vscode-docs",
4+
"title": "brainstorm: SSH RemoteForward 断联与 VS Code 文档优化",
5+
"description": "",
6+
"status": "in_progress",
7+
"dev_type": null,
8+
"scope": null,
9+
"package": null,
10+
"priority": "P2",
11+
"creator": "mudssky",
12+
"assignee": "mudssky",
13+
"createdAt": "2026-05-12",
14+
"completedAt": null,
15+
"branch": null,
16+
"base_branch": "master",
17+
"worktree_path": null,
18+
"commit": null,
19+
"pr_url": null,
20+
"subtasks": [],
21+
"children": [],
22+
"parent": null,
23+
"relatedFiles": [],
24+
"notes": "",
25+
"meta": {}
26+
}

docs/cheatsheet/vscode/remote/ssh-proxy.md

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@ killall ssh
6161

6262
---
6363

64-
### 2. 配置文件方式 (推荐/永久生效)
64+
### 2. 配置文件方式:专用隧道 Host
6565

66-
*配置一次,以后直接 `ssh alias` 即可自动建立隧道*
66+
*配置一次,以后直接 `ssh alias` 即可建立隧道。建议把隧道放在专用 Host 中,不要和 VS Code Remote SSH 或 zellij 登录 Host 混用*
6767

6868
编辑文件:`~/.ssh/config` (Mac/Linux) 或 `%USERPROFILE%\.ssh\config` (Windows)
6969

70-
```ssh
71-
Host my-cloud-server # 别名
70+
```sshconfig
71+
Host my-cloud-server-tunnel # 专用隧道别名
7272
HostName 1.2.3.4 # 服务器公网 IP
7373
User root # 用户名
7474
Port 22 # SSH 端口
75+
ExitOnForwardFailure yes # 转发端口绑定失败时直接失败,避免半成功连接
7576
# ↓↓↓ 核心配置 ↓↓↓
7677
# 格式:RemoteForward <服务器监听端口> <本地视角的目标IP>:<目标端口>
7778
@@ -82,16 +83,34 @@ Host my-cloud-server # 别名
8283
# RemoteForward 7890 192.168.50.1:7890
8384
```
8485

86+
连接时用:
87+
88+
```bash
89+
ssh -N my-cloud-server-tunnel
90+
```
91+
92+
`-N` 表示不打开远程 Shell,只维护代理隧道。这样 VS Code、普通终端、zellij 登录都可以复用远端 `127.0.0.1:7890`,但不会各自抢占同一个远端监听端口。
93+
8594
---
8695

87-
### 3. VS Code 自动化配置 (终极方案)
96+
### 3. VS Code 配置:保持 SSH Host 干净
8897

89-
*实现:连接即代理,终端自动生效环境变量*
98+
*目标:VS Code 连接稳定,远程终端按需使用已存在的代理端口*
9099

91-
#### 第一步:配置隧道 (同上)
100+
#### 第一步:VS Code Host 只放连接稳定性配置
92101

93-
确保你的 SSH Config 文件中已经添加了 `RemoteForward` (参考第 2 点)。
94-
*VS Code 会自动读取这个 SSH 配置建立连接。*
102+
VS Code Remote SSH 通常会建立多条 SSH 连接。如果这些连接都带同一个 `RemoteForward 7890`,后续连接可能绑定失败,甚至让排查断联时难以判断根因。建议 VS Code 使用不带 `RemoteForward``RemoteCommand``RequestTTY` 的 Host:
103+
104+
```sshconfig
105+
Host my-cloud-server-vscode
106+
HostName 1.2.3.4
107+
User root
108+
ServerAliveInterval 60
109+
ServerAliveCountMax 3
110+
ConnectTimeout 30
111+
```
112+
113+
如果正在排查十几分钟后断联的问题,可以先注释掉普通 Host 中的 `RemoteForward`,只保留上面三个 VS Code 侧参数观察一段时间。这样能把“代理端口冲突”和“连接空闲/网络抖动”拆开看。
95114

96115
#### 第二步:配置终端自动注入变量
97116

@@ -112,6 +131,54 @@ Host my-cloud-server # 别名
112131
}
113132
```
114133

134+
如果远程 `127.0.0.1:7890` 没有监听,说明当前没有独立隧道在运行。此时先启动第 2 节的 `*-tunnel` Host,而不是把 `RemoteForward` 重新放回 VS Code Host。
135+
136+
#### 第三步:常用配置实例
137+
138+
下面这组配置把同一台服务器拆成三个入口:VS Code 只负责非交互开发连接,zellij 只负责人工终端会话,tunnel 只负责代理端口转发。
139+
140+
```sshconfig
141+
# VS Code Remote SSH 入口:保持非交互,不带 RemoteCommand / RequestTTY / RemoteForward。
142+
Host ai-admin-vscode
143+
HostName 192.168.27.77
144+
User administrator
145+
ServerAliveInterval 60
146+
ServerAliveCountMax 3
147+
ConnectTimeout 30
148+
149+
# zellij 人工入口:保留 TTY 与远程命令,排查期先不加保活参数。
150+
Host ai-admin-zellij
151+
HostName 192.168.27.77
152+
User administrator
153+
RequestTTY yes
154+
RemoteCommand bash -lc 'cd ~/projects/env/powershellScripts && exec /home/linuxbrew/.linuxbrew/bin/zellij attach -c powershellScripts'
155+
156+
# 独立代理入口:只在需要远端 127.0.0.1:7890 代理时手动启动。
157+
Host ai-admin-tunnel
158+
HostName 192.168.27.77
159+
User administrator
160+
ExitOnForwardFailure yes
161+
RemoteForward 7890 127.0.0.1:7890
162+
```
163+
164+
使用方式:
165+
166+
```bash
167+
# VS Code 里选择 ai-admin-vscode
168+
169+
# 终端里进入 zellij 工作区
170+
ssh ai-admin-zellij
171+
172+
# 需要代理时单独开一个窗口维持隧道
173+
ssh -N ai-admin-tunnel
174+
```
175+
176+
如果代理目标不是本机 Clash,而是局域网软路由,把 `RemoteForward` 的目标地址换成软路由 IP:
177+
178+
```sshconfig
179+
RemoteForward 7890 192.168.50.1:7890
180+
```
181+
115182
---
116183

117184
### 4. 服务器端验证与手动激活
@@ -255,32 +322,38 @@ RemoteCommand bash -lc 'cd ~/projects/ai/java/xhgj-ai-platform && exec /home/lin
255322

256323
#### 拆分 VS Code Host 与人工 zellij Host
257324

258-
不要让 VS Code Remote SSH 复用带 `RemoteCommand` 的 Host。VS Code 需要非交互连接,`RemoteCommand``RequestTTY``RemoteForward` 都可能干扰它的连接管理。
325+
不要让 VS Code Remote SSH 复用带 `RemoteCommand` 的 Host。VS Code 需要非交互连接,`RemoteCommand``RequestTTY``RemoteForward` 都可能干扰它的连接管理。排查期间建议只给 VS Code Host 加客户端侧保活与连接超时,zellij Host 先保持原样,避免一次改变太多变量。
259326

260327
```sshconfig
328+
# VS Code Remote SSH 入口:非交互连接,只放保活与连接超时。
261329
Host proj-xhgj-ai-platform-vscode
262330
HostName 192.168.27.77
263331
User administrator
264-
ServerAliveInterval 30
332+
ServerAliveInterval 60
265333
ServerAliveCountMax 3
266-
TCPKeepAlive yes
334+
ConnectTimeout 30
267335
336+
# zellij 人工入口:保留 TTY 与 RemoteCommand,排查期先不加保活参数。
268337
Host proj-xhgj-ai-platform-zellij
269338
HostName 192.168.27.77
270339
User administrator
271340
RequestTTY yes
272-
ServerAliveInterval 30
273-
ServerAliveCountMax 3
274-
TCPKeepAlive yes
341+
RemoteCommand bash -lc 'cd ~/projects/ai/java/xhgj-ai-platform && exec /home/linuxbrew/.linuxbrew/bin/zellij attach -c proj-xhgj-ai-platform'
342+
343+
# 独立代理入口:需要代理时用 ssh -N 启动,避免 VS Code 多连接抢端口。
344+
Host proj-xhgj-ai-platform-tunnel
345+
HostName 192.168.27.77
346+
User administrator
275347
ExitOnForwardFailure yes
276348
RemoteForward 7890 192.168.21.108:7890
277-
RemoteCommand bash -lc 'cd ~/projects/ai/java/xhgj-ai-platform && exec /home/linuxbrew/.linuxbrew/bin/zellij attach -c proj-xhgj-ai-platform'
278349
```
279350

280351
如果 VS Code 也需要代理,建议只保留一个连接负责 `RemoteForward 7890`。可以先用独立终端维持隧道:
281352

282353
```bash
283354
ssh -N -o ExitOnForwardFailure=yes -R 7890:192.168.21.108:7890 administrator@192.168.27.77
355+
# 或者使用上面的专用 Host
356+
ssh -N proj-xhgj-ai-platform-tunnel
284357
```
285358

286359
然后 VS Code Host 不再声明同一个 `RemoteForward 7890`,避免多连接抢同一端口。
@@ -296,5 +369,5 @@ ssh -N -o ExitOnForwardFailure=yes -R 7890:192.168.21.108:7890 administrator@192
296369
| **端口被占用** | 服务器上已有程序占用了 7890 | 修改 `RemoteForward` 的第一个端口号 (如 `8888 127.0.0.1:7890`) |
297370
| **Git 依然慢** | Git 有单独的配置 | 运行 `git config --global http.proxy http://127.0.0.1:7890` |
298371
| **后台隧道无法关闭** | 使用了 `-f` 参数,进程在后台运行 | `ps aux | grep "ssh -NfR"`查找进程,`kill <PID>` 关闭 |
299-
| **隧道自动断开** | SSH 连接超时或网络不稳定 | 在 SSH 配置中添加 `ServerAliveInterval 60` 保持心跳 |
300-
| **VS Code / zellij 十几分钟后断开** | 客户端主动断开、网络空闲超时、多连接抢 `RemoteForward``RemoteCommand` 退出都可能触发 | 先查近 7 天历史日志,再拆分 VS Code Host 与 zellij Host,并加 `ExitOnForwardFailure yes` |
372+
| **隧道自动断开** | SSH 连接超时或网络不稳定 | 在专用隧道 Host 中添加 `ServerAliveInterval 60` 保持心跳,或先用前台 `ssh -N` 观察日志 |
373+
| **VS Code / zellij 十几分钟后断开** | 客户端主动断开、网络空闲超时、多连接抢 `RemoteForward``RemoteCommand` 退出都可能触发 | 先查近 7 天历史日志;排查期先注释普通 Host 的 `RemoteForward`,只给 VS Code Host `ServerAliveInterval 60``ServerAliveCountMax 3``ConnectTimeout 30`,zellij Host 暂不加保活参数 |

0 commit comments

Comments
 (0)