feat: 添加 WireGuard 设备管理并完善客户端分流
实现独立加密设备身份、网关 agent、持久生命周期任务和 Surge/FlClash 专属订阅凭证。 完善 Shadowrocket 规则转换与 Clash AI DNS,增加 Surge FFSB 适配、规则快照、运维工具及验收文档。
This commit is contained in:
119
docs/WIREGUARD-LAN.md
Normal file
119
docs/WIREGUARD-LAN.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 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,当前交接不要求继续此分支,也不将它写为已解决。
|
||||
Reference in New Issue
Block a user