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

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

100 lines
10 KiB
Markdown
Raw Permalink 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-02。下述最初缺口已完成本地实现,包含设备加密存储/旧库迁移、网关 agent/回执、设备 UI 和订阅绑定。当前接续请先读 [实现与上线验收](../../WIREGUARD-DEVICES.md)。已部署 LA 应用与 njcq agent,原有两台设备只读纳管已完成;未刷新活动客户端;下方“已有能力与实现缺口”保留为实施前基线。
## 开始实现前先读
1. [完整产品与技术设计](DESIGN.md):最新需求与验收标准的唯一方案入口。
2. [可点击原型](wg-device-management.html):设备列表、详情、独立导出,以及订阅页选择设备。可直接用浏览器打开;在对话内也可交互。数据、链接、二维码与握手均为演示。
3. [既有 WG 实现与验证记录](../../WIREGUARD-LAN.md):2026-11-01 已落地的设备专用 token 模型、njcq 配置和历史验收,不代表新设备管理功能已实现。
4. 根目录 [AGENTS.md](../../../AGENTS.md):仓库修改、验证、凭据、部署与线上数据操作约定。
## 用户最终确认的交互
- 个人 macOS、iPadOS、iOS 设备统一使用支持 WireGuard 与入站的 Surge。用户同日随后已在三端全面实测 Surge + WireGuard 可工作,并要求停止 Shadowrocket WG 下发兼容;实际网络/版本/生命周期的具体证据范围仍以用户回报和实现记录为准。
- 保留设备列表、私网 IP、状态、最后活动、上下行、管理操作及独立 WireGuard `.conf` / 二维码导出。
- 去掉“使用客户端”,不按 Surge / Shadowrocket / 原生 WG 分支创建不同设备身份。
- 在订阅页选 Surge 后,增加可清除的设备下拉框,来源为设备列表。
- 未选设备:原默认 Surge URL 不变,配置只含原节点、策略组和规则,无 WG 配置项。
- 选中设备:基于同一订阅入口生成带设备分发凭证的派生 URL,原代理内容加该设备的 WG 配置。不同设备完整 URL 可以不同;它们共享节点与规则来源。
- 清除选择:恢复原默认纯代理 URL。只影响当前导出的链接,不修改其他设备的既有链接,不撤销 peer。
- 新方案不安装身份模块,也不再靠新建一条独立订阅卡片表达设备。初次迁移保留旧设备专用 token;用户同日后续要求仅保留一个订阅,生产已退休两条旧设备卡片,设备通过原主订阅附加。详见实现记录。
**选择某设备不能修改服务端全局状态或覆盖共享 token 的 wireguard 字段。** 已生成的 A 设备 URL 必须继续获取 A 身份,不能随另一个浏览器选择 B 而变化。
## 已有能力与实现缺口(实施前基线)
| 部分 | 当前代码 | 后续工作 |
|---|---|---|
| 身份存储 | `sub_tokens.wireguard` 可空 JSON,真实密钥由当前管理员 DTO 返回 | 建立独立设备实体、加密密钥存储和不含私钥的列表 DTO;迁移兼容旧 token |
| 订阅生成 | `irFor()` 附加当前 token 的身份,Surge/WG 序列化器已可用 | 将身份来源改为经过授权的设备绑定;无选择保持纯代理 |
| 自更新地址 | Surge 路由的 `selfUrl` 当前没有查询参数 | 保留经过验证的设备凭证参数,否则下一次自动刷新丢 WG |
| 独立导出 | 标准 `.conf` 与 Shadowrocket WG YAML 已有生成器 | 标准导出改为设备授权入口,复用同一身份,不再额外创建 peer |
| 设备 UI | 当前只有订阅卡片附带 WG 地址/链接 | 新增设备页、详情、状态与接入流程;订阅页新增设备下拉框 |
| 网关生命周期 | 一次性安装脚本预置两台设备 | 独立网关采集、幂等 peer 应用/撤销、运行与持久配置回执;不是只操作下载 token |
| `?wg=...` | 当前订阅路由尚未解析这一参数 | 实现高熵、不可枚举、可撤销、绑定订阅和设备的分发凭证 |
上述表格为实施前的代码基线,已由本地新实现补齐;最新路径和行为见实现记录。原“当前代码”来自本地源码核对,不是本次重新读取生产 API 或远端配置的结果。工作区有其他未提交的 FFSB、规则、生成器等变更,需保留并按文件审阅,不用整目录覆盖或回滚。
## 代码定位
| 路径 | 作用 |
|---|---|
| `shared/src/wireguard.ts` | WireguardProfile、私网/密钥/MTU 校验;当前 MTU 默认 1280、上限 1420 |
| `shared/src/dto.ts` | 当前 TokenDto 与导出 URL,后续拆分设备元数据和私密领取 |
| `server/src/db/schema.ts`、`server/src/db/index.ts` | 当前 token 身份字段与旧库补列;新增表和迁移同时更新 |
| `server/src/routes/tokens.ts` | 当前 `/api/tokens` CRUD、重复身份检查、URL 和 DTO |
| `server/src/routes/sub.ts` | token 校验、`irFor()`、标准 WG 导出、Surge 路由与 selfUrl;新增绑定鉴权的关键位置 |
| `server/src/services/ir.ts` | 原代理 IR 与可选 WG 身份类型,保留节点权限范围 |
| `server/src/services/generators/wireguard.ts` | 标准 WG、Shadowrocket WG、Surge WireGuard 段落生成 |
| `server/src/services/generators/surge.ts` | WG 代理声明、私网规则、自地址 DIRECT、托管 header 与公网组排除 |
| `server/src/routes/wireguard.test.ts` | 当前 WG token、迁移、隔离与配置行为测试,可扩展新绑定测试 |
| `web/src/pages/SubscriptionsPage.vue` | 当前 WG 仍作为 token 卡片额外导出;实现设备下拉与清除操作 |
| `web/src/App.vue`、`web/src/router.ts` | 增加“设备”导航和受鉴权页面 |
| `.claude/skills/edge-node-multi-protocol/scripts/17-install-wireguard.sh` | 既有 njcq 安装编排;目前不是通用设备地址分配器或网关 agent |
管理资源沿用 `/api/tokens`。本地已实现 `POST /api/tokens/:id/wg-bindings`,其余设备、任务、网关与导出 API 见 [实现记录](../../WIREGUARD-DEVICES.md),已发布到生产,设备侧新导入/入站仍须验收。
## njcq 与设备身份基线
最后记录的服务为 Linux 内核 WireGuard,接口 `wg-njcq`,UDP 51820,网关 `10.203.0.1/24`。正式登记为 iPad Pro `10.203.0.2`、Mac Studio `10.203.0.3`,独立 keypair/PSK,MTU 已从临时测试恢复 1280。只提供 `10.203.0.0/24` 设备互访,不做 Internet NAT。
原型中 MacBook Air、iPhone、Windows/Linux 等额外设备、速率、状态、最后活动以及示例地址均不是正式登记清单,不能拿去初始化生产。iPhone 是否已有独立 peer 须在实施前核对,不能复用 iPad 身份。
2026-11-01 已验证:Mac Surge 6.11 入站及经 hub 访问本机 VNC;iPad 官方 WG → njcq → Mac Surge 的 Apple VNC 成功。Shadowrocket 普通 VNC 可用但 Apple VNC 黑屏,具体实现根因尚未确认。MTU 1420 不是已证实修复,临时修改与监测已恢复/结束。
用户后来统一三端为 Surge,因此 Shadowrocket 后续 TUN-only 等排查留作历史材料,不是本次设备管理的实现前提。Surge 三端安装后的自动更新、入站与 Apple VNC 仍需单独记录实际验收,不能用普通握手代替媒体可用性验证。
## 私有资料在哪里
仅列路径,不复制凭据。真实内容仍留在本机 Git 忽略的 `edge-nodes/private/njcq-edge-node-docs/`:
- `README.md`:真实交付入口、订阅地址和备份说明。
- `subscriptions.json`:既有两个设备 token、WG 身份与 URL 的交付记录,实施迁移前应与线上重新比对。
- `import/njcq-ipad.conf`、`import/njcq-ipad-qr.png`:原生客户端的成功对照产物。
- `import/export-summary.json`:导出摘要。
上述真实配置/订阅文件已核对存在、权限 600;父目录应维持 700。不得把真实订阅 URL、私钥、PSK、二维码或完整配置放入公共设计文档、普通日志或 Git。新克隆只携带公共源码和方案,不会自动携带这些私有交付记录。
njcq 远端配置在 `/etc/wireguard/`,备份索引见 [WG 记录](../../WIREGUARD-LAN.md)。需要操作生产时按仓库技能重新读取、备份和验证,不以历史交付数据覆盖最新配置。
## 实现时必须守住的边界
1. 设备凭证不能是裸 ID/IP;普通共享订阅 token 不得通过枚举设备获得私钥。绑定校验订阅、设备、用途和撤销状态,密钥响应 no-store,日志与缓存按敏感数据处理。
2. `#!MANAGED-CONFIG` 使用完整带设备参数的自身 URL,仅保留受支持且已验证的参数。无设备时继续原 URL。
3. 公网节点、策略组、DNS、FFSB 手动分流和其他组选择保持原范围;WG 不被 Automatic/All Nodes 等选成 Internet 出口。
4. 首次握手是连接证据,点击生成/复制/导入不是在线证据。采集过期显示未知,不使用缓存速率冒充实时值。
5. 暂停必须真正移除网关 peer 并持久化;停用分发凭证不能撤销已下载的配置。移除后旧链接拒绝,不静默降级或换身份,设备 ID/IP 不立即复用。
6. 幂等任务确认前不报成功;采用原子配置合并,保留非受管 peer 和现有 Tailscale、Docker 等共机服务。
7. 本仓库另有 [FFSB 原生 WG 试验](../../FFSB-WIREGUARD-SURGE-2026-11-02.md),是第三方服务的不同身份/网段,不能合并进 njcq 私网设备或自动激活试验配置。其当前恢复状态以该文档与 AGENTS.md 为准。
## 实施与验收顺序
先纳管现有两台设备并只读采集;再做新增/暂停/恢复和独立导出;最后实现订阅设备绑定、Surge 配置生成与三端实际导入。迁移保留现有 key、PSK、IP 和旧链接兼容,不为了新 UI 重建所有 peer。
测试应覆盖默认无 WG、各设备私钥隔离、非法/跨订阅凭证、selfUrl 保留设备参数、设备暂停/归档、旧库迁移、失败幂等重试、采集失联、真实撤销以及节点范围/FINAL 不变。含密钥的 fixture 使用占位值,数据库验证在模块加载前设置隔离 DATA_DIR,不能测试真实 server/data。
验证命令依改动执行根目录 `AGENTS.md` 的 typecheck、相关 Vitest 与前端构建。Surge 产物先核对下载成功/结构,再用官方 CLI;CLI 通过仍需 macOS、iPadOS、iOS 的真实连接验收。生产部署和远端写入按后续用户授权执行。
本次交接保留了上一轮原型验证记录:设备选择/清除与配置结构、自更新 URL、独立导出、新增/暂停/移除、320–1024 宽度和深色外观。它们是原型验收,不是待实现功能的生产验收。