Files
proxy-station/docs/WIREGUARD-LAN.md
YANG JIANKUAN a5d980a5e9 feat: 添加 WireGuard 设备管理并完善客户端分流
实现独立加密设备身份、网关 agent、持久生命周期任务和 Surge/FlClash 专属订阅凭证。

完善 Shadowrocket 规则转换与 Clash AI DNS,增加 Surge FFSB 适配、规则快照、运维工具及验收文档。
2026-11-02 22:44:23 +08:00

120 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WireGuard 设备组网订阅
2026-11-01 增加独立 WireGuard 私网接入。njcq 固定中转设备间流量,Apple 屏幕共享和 OpenScreenSharing 保持原有协议。
## 最新客户端约定(2026-11-02 后续)
用户已在 macOS、iPadOS、iOS 实际全面验证 Surge + WireGuard 可工作,停止 Shadowrocket 的 WG 兼容。普通 Shadowrocket 节点/规则下发保留,WG 私网路由、专用 WG YAML 与导出链接已从本地代码清除,旧专用路径明确 404;尚未重新部署此清理。Surge 与标准 WG 独立导出、设备/网关管理不变,见 [清理记录](WIREGUARD-DEVICES.md#2026-11-02-停止-shadowrocket-wireguard-下发本地已清理未部署)。下文的 Shadowrocket WG 安装与排查仅是历史记录,不作为当前接入指引。
## 最新接续方向(2026-11-02)
用户已将个人 macOS、iPadOS、iOS 客户端统一为 Surge,并确认支持 WireGuard 与入站。下一阶段从 [实现交接](design/wireguard-devices/HANDOFF.md) 和 [产品设计](design/wireguard-devices/DESIGN.md) 开始:设备管理独立于订阅,保留标准 WG 导出,删除客户端选择;Surge 订阅可选附加某台设备,未选使用原默认纯代理 URL,选中生成带设备凭证的派生 URL。现已实现并部署独立设备实体、加密密钥迁移、设备页、njcq agent 和设备绑定 API/查询参数,详见 [实现与生产验收](WIREGUARD-DEVICES.md)。两个原 peer 已只读确认纳管,现有身份、IP 和旧链接保留,下面的设备 token 模型仅为历史实现记录。
下文保留 2026-11-01 的部署、测试和恢复记录;Shadowrocket 排查是历史对照,不是新设备管理的实施前提。用户统一到 Surge 是最新使用信息,本轮已读取管理 API 和 njcq 运行/持久状态完成迁移验收;未切换本机 Surge,也未完成三端新方案实际设备验收。
同日后续用户要求只保留一个订阅:生产已删除两个旧设备 token,原主订阅 URL 保留;两台 WG 身份、IP、peer 和独立配置不变,改从主订阅选择对应设备生成派生链接。旧 token 下载入口已 404,下方旧入口表仅为历史记录;备份见 [单一主订阅记录](WIREGUARD-DEVICES.md#2026-11-02-单一主订阅收拢)。
## 服务与身份
- njcq:Ubuntu 内核 WireGuard,接口 `wg-njcq`,UDP 51820,`10.203.0.1/24`,开机启动。
- iPad Pro:`10.203.0.2`;Mac Studio:`10.203.0.3`。每台设备独立私钥、公钥和预共享密钥。
- 只允许同一 WireGuard 接口内的私网转发,不提供 Internet 出口 NAT。
- 保留既有 Tailscale、Docker、面板和系统 IPv6 设置,新增 WireGuard 使用 IPv4。
- 云安全组和主机防火墙均需允许 UDP 51820。服务 active 或配置解析通过不足以证明公网可用。
安装脚本是本机 SSH 编排器:
```bash
bash .claude/skills/edge-node-multi-protocol/scripts/17-install-wireguard.sh \
<ssh-host> <public-ip-or-host> edge-nodes/private/<id>-edge-node-docs
```
脚本保留已有受管接口,不重新生成身份;目前预置本次两台设备及网段,扩容前需审阅,不能作为任意地址的自动分配器。VPS 配置和客户端身份清单在 `/etc/wireguard/`,root/600;本机交付在 Git 忽略的 `edge-nodes/private/njcq-edge-node-docs/`。
## 已有订阅模型与入口
WireGuard 是设备私网身份,不加入公网代理 `nodes` 协议枚举。`sub_tokens.wireguard` 为可空 JSON,旧库启动补列,旧共享订阅保持 null。token POST/PUT 接受经校验的 wireguard 对象,普通编辑省略该字段时保留身份。仅允许 RFC1918 私网与有效设备地址,拒绝默认/公网路由、复用私钥和同一服务器下的重复地址。
`irFor()` 只给当前 token 的 ProfileIR 附加该设备身份,生成器不再读库,不向其他订阅下发此设备密钥。
| 路径 | 内容 |
|---|---|
| `/sub/:token/wireguard.conf` | 标准配置,可导入 WireGuard / Passepartout |
| `/sub/:token/wireguard-shadowrocket` | 单个 WG 节点的 YAML 订阅 |
| `/sub/:token/surge` | 原有公网配置加该设备 WireGuard 段落和优先私网规则 |
| `/sub/:token/shadowrocket-conf` | 原有规则加私网规则,引用额外导入的 WG 节点 |
设备订阅为 `NJCQ WireGuard - iPad Pro` 和 `NJCQ WireGuard - Mac Studio`;原共享订阅保留,不能在多台同时在线的设备上复用同一身份。Shadowrocket 的原公网 URI 节点订阅不变,WG 节点需额外导入;动态公网策略组排除 `NJCQ WireGuard LAN`,避免误作 Internet 出口。Clash 原公网配置保持原行为,组网使用标准 WireGuard 配置,不声称已下发 Clash 私网适配。
Shadowrocket YAML 字段参考 [Sub-Store 的 Shadowrocket producer](https://github.com/sub-store-org/Sub-Store/blob/master/backend/src/core/proxy-utils/producers/shadowrocket.js),iPad 节点导入及普通 VNC 已通过;Apple VNC 在本次 Shadowrocket 路径未通过,原生 WireGuard 对照成功,见下文。
### Shadowrocket 首页缺少 WG 节点
若已更新“ShadowRocket iOS”的普通节点和规则,但首页看不到 `NJCQ WireGuard LAN`,还需在本设备专属订阅卡片复制 **“WG 节点 · Shadowrocket”** 链接,作为额外 Subscribe 订阅添加。普通 `/shadowrocket` 入口保持原公网 URI 节点,不包含 WG;仅刷新 `/shadowrocket-conf` 不会创建节点。保持全局路由为“配置”,OpenScreenSharing 连接 `10.203.0.3:5900`。
2026-11-01 实际排查:iPad 用户报告首页缺少该节点;HTTPS 日志只有该设备 `/shadowrocket` 与 `/shadowrocket-conf` 的 Shadowrocket 请求,没有 `/wireguard-shadowrocket` 请求;同时服务器没有 iPad peer 握手。此状态先补导入节点,不修改 Mac 屏幕共享或服务器防火墙。
## 客户端要求
- Mac Surge 接收入站需要 **6.11.0+**,通过 `accept-incoming = true` 把本设备虚拟 IP 的连接交给本机服务。6.10 CLI 接受语法不代表支持入站。
- Mac 可用独立 WireGuard / Passepartout 导入标准配置;同一身份只启用一种实现。
- iPad 使用 Shadowrocket 时需导入本设备公网节点、额外 WG 节点及规则配置;本次普通 VNC 已通过,Apple VNC 高性能模式未通过。
- iPad 使用 Apple VNC 的已验收组合:**官方 WireGuard 客户端 → njcq → Mac Surge 6.11.0 build 12660**。导入标准 `.conf` 或离线二维码,连接 `10.203.0.3:5900`;同一身份不与 Shadowrocket 同时启用。
- 不自动更换客户端活动配置或升级 Surge。WireGuard 规则只接管私网网段,原公网出口与 DNS 保持原有逻辑。
## 验证、备份和恢复
- 2026-11-01:全量类型检查、前端构建、80 项单测通过,1 项既有测试跳过。覆盖旧库迁移、设备密钥隔离、私网范围、重复身份和普通 token 编辑保留身份。
- 已下载实际 HTTPS 设备产物并通过本机 Surge 官方 CLI。候选及实际 Mac 设备产物的 49 个规则快照全部下载并通过本地快照 CLI;重试期间出现过上游偶发超时。现有 FFSB 静态遮蔽提示不作为本次组网改动处理。
- 用户放行云安全组后,临时 peer 从另一台公网 VPS 成功握手,5/5 ICMP 返回;经 njcq 到另一隔离 peer 的 TCP 转发成功。验证程序、临时 peer 和 namespace 已清理。该阶段尚未验收实际设备,后续 Mac 验收见下。
- 本机另用官方 wireguard-go netstack 发起临时接入,跨公网访问隔离 peer 的 HTTP 成功;未创建系统隧道或替换活动 Surge 配置。
- 同日实际 Mac 验收:Surge 6.11.0 (12660)。磁盘已是 Mac 专属订阅,但运行中的 original/effective 配置仍无 WireGuard,私网落到 LAN DIRECT;`managed-profile update` 返回 unchanged 且不安排重载。备份并保存组选择后执行 `surge-cli reload`,私网规则与 WireGuard 生效,原组选择保持一致。不能只检查磁盘配置或订阅刷新结果。
- Mac 到 njcq 实际握手成功,Surge WireGuard RTT 约 8 ms;njcq 经 `10.203.0.3:5900` 读到 Apple `RFB 003.889` 响应,证明 Surge 入站可用。Mac 经 WireGuard 从 hub 下载 16 MiB 完整数据,单次约 0.259 秒 / 519 Mbps;只代表这一段短时下载,不代表 iPad 到 Mac 的端到端吞吐。临时监听仅绑定 hub 私网地址,测试后已退出。
- 同日 iPad 补导入独立 WG 节点后已握手,服务器记录约 85 MiB 桌面转发,用户确认普通 VNC 连接流畅。长期运行、睡眠与换网仍未验收。
- OpenScreenSharing 的 Apple VNC 选项对应高性能媒体模式;源码在标准 RFB 控制会话外打开 UDP 媒体 socket。用户报告该模式无法显示,Mac 日志于 16:06 显示 iPad RSA-SRP 认证成功、base UDP 5900 及媒体协商消息;普通 VNC 于 16:07 再次认证成功。这是初期排查状态,后续受控抓包及原生客户端成功对照见下文。不要因此开放公网 5900/5901。
- 生产数据库在线备份:`data/backups/before-njcq-wireguard-device-subscriptions-20261101-151040.db`,root/600。VPS 安装前备份:`/root/backups/before-wireguard-*`。
- 运维脚本同时修正备份权限:新备份使用 umask 077,部署只调整应用源码/依赖属主,不递归改动 data/backups。
- 查看状态使用 `wg show wg-njcq`;不要把会输出私钥的 `wg showconf` / `wg show ... dump` 写入共享日志。
- 停用/删除订阅 token 只撤销后续下载,**不会撤销已导入的 WireGuard peer**。撤销网络身份还需在服务器删除 peer 并更新持久配置。
- 停用:`systemctl disable --now wg-quick@wg-njcq`,PostDown 只撤销该接口添加的规则;恢复:`systemctl enable --now wg-quick@wg-njcq`。保留私有配置和备份。
Surge 行为以[官方文档](https://manual.nssurge.com/policies/wireguard.html)为准。
## Apple VNC 高性能模式排查(2026-11-01)
普通 VNC 已通不代表 Apple VNC 媒体已验收。协议与实现依据:
- [Apple 高性能屏幕共享要求](https://support.apple.com/zh-cn/guide/remote-desktop/apdf8e09f5a9/mac):UDP 5900/5901/5902 双向通信;75 Mbps 是其原生单台 4K 工作流的推荐带宽,不能当作 OpenScreenSharing Internet 模式的最低门槛。
- [OpenScreenSharing 作者 issue #2](https://github.com/nekohasekai/open-screen-sharing/issues/2):需要固定 UDP 源端口 5900/5901 与正确的反向包投递,泛称“支持 UDP”不足以保证兼容。该评论针对当时版本,不能直接推导当前 Surge 永远不支持。
- [Surge 官方更新记录 426](https://t.me/s/SurgeTestFlightFeed/426) 与 [Mac beta appcast](https://sgupd.com/latest/appcast-signed-beta.xml):早期 beta 曾说明不兼容;后续移除 peer-access-passthrough 并内置 Apple Screen Sharing 特殊处理。已核对 appcast enclosure build **12660 / 6.11.0** 的说明包含此处理,与本机版本相符,不能只引用旧的“不支持”公告。旧 accept-incoming 仍兼容,运行配置规范化为 allow-peer-access;不要添加已移除的参数。
- 源码 `internal/rfb/media/socket.go`:媒体 socket 使用固定本地源端口并 connect 到对端相同端口。`media/rtcp.go` / `media/stream.go`:视频丢包统计来自成功 SRTP 解密后的 RTP 序号缺口;不是 ICMP 丢包。`media/video.go`:初始等待同步帧,损坏的 access unit 不建立画面。因此有 bitrate 仍可长期黑屏。
- `DebugInfoMonitor.swift` 的 Network 为 TCP SRTT/2,Mac 与 This iPad 指标依赖画面处理事件,不能把 Network 值单独当成端到端视频延迟。Internet 配置用 mode 5、4:2:0、单分带;Local Network 用 mode 7、4:4:4、四分带;本次降低到 Internet/30 fps 后用户仍报告黑屏、约 2 Mbps / 35% 丢包。
实际日志:账号 RSA-SRP 认证成功,UDP 5900/5901 双向包与 iPad 反馈均存在。视频 UDP 负载约 1386 字节,IP 总长 1414,MTU 1280 下发生分片;临时只改 hub 到 1420 无效,上游分片依旧;再将 Mac 设备订阅 MTU 改到 1420 后确认入站完整 IP 包约 1409 字节、无分片,但仍黑屏。用户报告码率提高、丢包降低,但不能将 MTU 认定为唯一原因。
测试已恢复:Mac 专属订阅经 API 回到 MTU 1280、Surge 已刷新;hub 运行 MTU 恢复 1280,自动恢复 timer 已停用,持久配置始终未改。iPad 订阅未改。公共节点/组/规则/settings 前后比对一致。在线备份 `data/backups/before-apple-vnc-mtu-test-20261101-161957.db` root/600;节点私有配置备份 `/root/backups/wireguard-mtu-test-20261101-161752/`。
受控抓包结果(16:32 左右,MTU 已恢复 1280):njcq 入站捕获 10,811 个 IP 包,媒体样本覆盖 16.451 秒;视频 RTP 单 SSRC 收到 4,858 个唯一序号,序号跨度也为 4,858,观察缺口 0%;4,288 组 IPv4 分片全部完整,无未完成分片组,tcpdump 内核丢包 0。视频 UDP 总负载约 6,335,778 字节,同期用户报告 iPad 仅约 200 Kbps、90% 丢包。此样本把媒体缺包定位到 njcq 之后至 iPad 应用接收之间,尚不能区分云公网/ISP/Wi-Fi 与 Shadowrocket 接收及重组。不要把该样本外推为所有网络时段绝无丢包。
### 原生 WireGuard 对照成功
同日用户在 iPad 官方 WireGuard 客户端导入 `njcq-ipad.conf` 后确认 Apple VNC 成功出画面、速度良好。客户端继续使用同一 iPad 地址/密钥、MTU 1280;服务器看到 iPad 公网出口 IP 与此前 Shadowrocket 相同,仅 UDP 源端口变化,两个正式 peer 均有近期握手。Mac 仍使用 Surge 6.11.0 build 12660,hub MTU 仍为 1280;短时抓包确认 UDP 5900/5901 音视频与反馈双向流动。
因此,本次主要故障可定位到 **iPad Shadowrocket 的 WireGuard/UDP 接入路径与 Apple VNC 的兼容性**。服务端、Mac Surge 和 MTU 1280 均在成功组合中得到保留;不应再把它们宣称为本次黑屏的已证实主因。尚未做到 Shadowrocket 实现级排查,具体是分片重组、固定源端口/反向 UDP 处理、缓冲或其他机制不能断言;也不据此宣称所有 Shadowrocket 版本都无法使用 Apple VNC。长期运行、睡眠/换网、定量吞吐与最终丢包率仍未验收。
2026-11-01 当时的成功使用方式为原生 WireGuard 承载 iPad 组网,Shadowrocket 普通代理按需切换;后续用户已统一 Surge,见本文顶部。配置只路由 `10.203.0.0/24`,不作为公网出口。
### Shadowrocket 后续配置排查
用户随后要求继续使 Shadowrocket 的 WG 连接支持 Apple VNC,原生 WireGuard 仅作为成功基线。已核实客户端 2.2.93 build 3488,UDP 转发开、禁用 STUN 关。官方站由 App Store sellerUrl 指向 https://shadowlaunch.com/,其链接指向官方 Telegram 群/公告频道;不要把搜索到的多个自称“官方手册”网站当作官方依据。
[官方 build 3488 更新](https://t.me/ShadowrocketNews/1665) 与 [2.2.93 正式版](https://t.me/ShadowrocketNews/1666) 未声明修复 Apple VNC;2.2.94 build 3490–3493 的公开说明也未见该项。历史 [build 3215](https://t.me/ShadowrocketNews/1454) 修复 raw socket MTU、[3216](https://t.me/ShadowrocketNews/1455) 调整读取长度、[3399–3400](https://t.me/ShadowrocketNews/1593) 涉及 L3 UDP fast relay,这些是实现曾变动的证据,不能据此宣称当前缺少基础 UDP 功能或已确认同一 bug。此前实际反馈包在服务器上保留了 5900/5901 源端口,不能简单断言 Shadowrocket 始终随机改写该端口。
进行了完整三端 1420 MTU 对照:两个设备 token 的 wireguard.mtu 经 API 暂改 1420,Mac effective 配置、实际 HTTPS Shadowrocket YAML 和 hub 运行 MTU 已核对;日志确认 iPad 下载过新节点订阅,iPad UI 实际字段尚未单独回报。抓包 99.311 秒、14,596 个 IP 包、0 分片,固定源端口正确。期间有多次重新连接:3 个 SSRC 的 njcq 入站序号缺口分别为 0%、4.348%、60.437%,不能混成单一成功的无丢包样本。用户最后回报仍黑屏、丢包显示 0%、bitrate 约 200 Kbps;缺少完整同步媒体样本时显示 0% 不足以证明媒体成功,需继续核对实际视频包与帧重组。
测试已由自动恢复程序回退两个 token 与 Mac Surge/hub 到原 MTU 1280,server 持久配置未动。备份 `data/backups/before-shadowrocket-complete-mtu-test-20261101-165515.db` root/600;服务器临时参数快照 `/root/backups/sr-complete-mtu-test-20261101-165519/`。原生客户端导入的成功配置文件/二维码从未覆盖。
额外干扰项:HTTPS 访问日志见一台 iPhone 也下载了 iPad 专属 WG 节点订阅,已向用户核实是否同时启用;25 秒 endpoint 观察只有一个值,尚未实证并发身份争用。不能据此解释全部早期失败。当时拟继续核对 Shadowrocket 设置→代理→代理类型,以及 TUN-only(None / compatibility-mode=3)是否影响 L3 UDP 接收路径;这一测试未完成,选项描述来自社区配置手册。用户后续统一 Surge,当前交接不要求继续此分支,也不将它写为已解决。