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

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

172 lines
14 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 设备管理与 Surge 按设备订阅
状态:已确认产品设计与原型,2026-11-02。已完成本地实现,具体接口、迁移和验收见 [实现记录](../../WIREGUARD-DEVICES.md);现已部署 LA 应用与 njcq agent,未切换活动客户端;原有设备只读纳管与凭证端点已通过,用户同日随后已确认 macOS/iPadOS/iOS 的 Surge + WireGuard 全面实测可工作,停止 Shadowrocket WG 下发兼容;生命周期与长期网络场景不据此外推。
开始开发请先读 [实现交接](HANDOFF.md),其中列出已有代码、实现缺口、真实配置位置与历史验证边界。
## 产品决策
设备页独立管理 WireGuard 身份、固定 IP、状态和网络生命周期。设备模型不记录“使用客户端”,创建和导出时也不要求选择客户端。当前个人设备统一使用支持 WireGuard 与入站的 Surge,仍保留标准 WireGuard 独立配置导出。
订阅页选择 Surge 格式后,提供“附加设备 WireGuard(可选)”下拉框,数据来自设备管理列表:
| 选择 | 下发配置 | 链接行为 |
|---|---|---|
| 不附加设备 | 干净的代理节点、策略组与规则,无设备 WG 身份 | 使用原默认 Surge URL,逐字保持不变 |
| 选择某台设备 | 原代理内容 + 此设备独立 WG 身份、私网规则和入站设置 | 基于原入口生成带设备凭证的派生 URL |
| 清除选择 | 恢复纯代理配置 | 恢复原默认 URL |
**选择状态必须体现在生成链接的凭证中,不能保存在服务端的全局“当前设备”变量。** 否则 Mac 选择设备后会改变 iPad 下次刷新所得到的身份。
本方案统一的是订阅入口与节点、策略、规则来源,不承诺包含不同私钥的各设备使用逐字相同的完整 URL。设备专属链接需在对应设备导入一次,之后每次更新仍包含同一设备身份。不再需要额外身份模块、客户端选择或复制私钥。
## 信息架构
主导航沿用:节点 / 策略组 / 规则 / **设备** / **订阅** / 设置。
设备页保留现有列表与操作:名称、系统、固定私网 IP、状态、最后活动、上行/下行、详情、暂停/恢复、重置身份与移除。显示方向以设备为准,上行为设备到网关,下行为网关到设备。窄屏沿用设备条目布局。
设备详情增加两个清晰入口:“用于 Surge 订阅”和“导出独立 WireGuard 配置”。前者打开订阅页并预选此设备,后者打开独立导出页。两种方式引用同一设备身份,不另分配 IP 或密钥。
设备信息中删除客户端名称与兼容性分支。系统字段继续用于识别设备,不作为私钥领取认证凭据。
## 添加设备
1. 填写名称、系统。网关、网络、MTU、IP 和密钥自动处理。创建前展示默认设备互访范围。
2. 事务内预留唯一 IP 和独立 keypair/PSK,创建幂等网关任务。只有网关确认运行配置和持久配置生效后,才显示“待接入”。失败保留同一设备和 IP,重试不重复创建。
3. 创建完成后可选“前往 Surge 订阅”或“导出独立 WireGuard 配置”。也可稍后从设备列表继续。
4. 导入后单独检查首次握手。生成、复制链接、下载配置或点击导入均不直接变为在线。
第一版使用现有 njcq 网关、10.203.0.0/24、MTU 1280,保留现有 iPad .2 与 Mac .3。网关只转发个人私网互访,不新增 Internet 出口或 NAT。
## 订阅交互
订阅卡片保留当前节点范围与启用状态。选择格式为 Surge 后显示设备下拉框,默认“不附加设备 · 纯代理订阅”。选项包含名称、私网 IP 和当前状态;离线设备可以选择,首次未握手但网关已生效的设备也可以选择。
已暂停、正在撤销、正在恢复、配置中、配置异常的设备仍在列表显示,但不可新选择生成接入链接。采集失联不等于身份被暂停,不因遥测未知就错误撤销既有权限。
选择设备后,页面就地更新:
- 明确显示所选设备和 IP,以及该链接仅供此设备使用。
- 链接包含对应的受控设备凭证;“复制链接”和“导入 Surge”使用相同的当前 URL。
- 保留“清除设备选择”,随时返回原默认 URL。
- 提供配置结构预览,私钥/PSK 始终遮蔽,不把真实密钥放进普通 DOM、浏览器持久化状态或原型。
- 提供“检查设备连接”,回到所选设备的真实握手验证。
切换其他订阅格式时清除设备附加选择;其他格式保持原行为,不静默继承 Surge 的个人身份。清除选择只改变当前导出的链接,不撤销设备,不修改其他设备已导入的链接,也不覆盖同一订阅 token 的默认设置。
如果选择的设备随后被暂停或移除,界面明确显示不可下发,禁用复制/导入。旧设备 URL 在服务端也应拒绝,不能默默返回纯代理配置,更不能换成另一台设备身份。
## 链接、授权与生成规则
示意入口:
```text
纯代理:/sub/<原订阅 token>/surge
附加设备:/sub/<原订阅 token>/surge?wg=<不可枚举的设备分发凭证>
```
`wg` 不是裸设备 ID、名称或 IP。共享代理订阅 token 的持有者不能通过枚举 `?device=1/2/3` 获取任意设备私钥。
管理员在订阅页选择设备后,由已认证的管理 API 签发或复用绑定“订阅 + 设备 + 导出用途”的高熵分发凭证。数据库保存凭证哈希及作用域,可单独撤销。服务端校验原订阅 token 和设备凭证,确认二者绑定关系、设备仍存在且允许接入,再附加身份。
此凭证是能读取该设备私密配置的长期能力凭证,不能作为无敏感性的普通分享链接。网页不必展示内部 token 管理细节,但要说明链接只能用于所选设备。导入地址和凭证不写入公开日志、统计或 Referer;敏感响应 no-store,缓存不得跨设备串用。
首次跨设备分享可使用短期领取票据,兑换后获取该设备长期订阅链接。短期票据不直接充当托管配置的长期更新 URL,避免过期后自动刷新失效。GET 预览不消耗领取会话,由显式确认的 POST 原子绑定;并发最多一个会话成功,允许同一领取会话短时重试。
**带设备配置的 `#!MANAGED-CONFIG` 必须写入完整的带 `wg` URL。** 如果仍写原纯代理 URL,下次自动更新就会丢掉 WG 身份。原默认纯代理配置的 header 继续写原 URL。
生成流水线遵循:原订阅节点权限 → 原代理 IR → 通过授权的一个设备身份 → Surge 完整配置。用户原有公网代理选择与策略名称尽量保持不变;设备 WG 节点不进入 Automatic、All Nodes、AI 等公网代理池,只供专用私网策略引用。
纯代理响应不包含 `[WireGuard ...]`、WG 代理声明、WG 私网路由、设备地址、私钥或 PSK。附加响应只包含被授权的一台设备,不包含设备列表或其他设备身份。入站按用户当前 Surge 能力启用,具体字段与平台行为须通过目标版本验收。
## 独立 WireGuard 导出
设备详情继续提供二维码与 `.conf` 下载。配置引用同一 device keypair、PSK 和地址;导出不创建另一个 peer,不修改代理订阅,也不因生成配置就标记在线。
普通列表 DTO 不返回私钥、PSK、完整配置或长期分发凭证。导出/领取使用独立授权接口,正式二维码在本地或受控服务生成,不调用在线二维码服务。暂停或网关任务未确认时不继续签发接入配置。
原型二维码为无密钥的演示载荷,下载与导入仅显示模拟结果。
## 状态与操作
状态仍由期望生命周期、网关应用回执、连接遥测三部分计算。
| 状态 | 判定与行为 |
|---|---|
| 配置中 | 已创建身份,网关尚未确认 |
| 待接入 | peer 已生效,从未出现有效握手 |
| 近期在线 | 新鲜采样且 180 秒内有握手或流量增长 |
| 离线 | 采集正常,已连接过,但超出活跃阈值;不代表设备电源关闭 |
| 状态未知 | 采集超过 45 秒未更新,展示最后采集时间并隐藏实时速率 |
| 正在暂停 | 已请求移除 peer,尚未收到确认,可能仍可通信 |
| 已暂停 | 网关运行配置与持久配置均确认移除 peer,记录与 IP 保留 |
| 配置异常 | 网关应用失败或配置冲突,保留幂等任务重试 |
网关每 15 秒上报,页面 15 秒刷新;使用相对握手年龄和中心接收时间处理时钟偏差。计数周期重置时重新建立速率基线,不显示负流量;累计用量按纳管后的有效增量持久记录。
WireGuard 数据不直接证明 VNC 健康、端到端画面延迟或媒体丢包。地址漫游也不直接判定身份被盗用。
- 改名只修改元数据;设备凭证绑定 ID,不随名称变化失效。
- 暂停必须在网关移除 peer 并持久化;仅停用订阅链接不能撤销已导入的网络身份。
- 恢复在网关确认 peer 重新生效后允许连接。
- 重置身份先撤销旧 key 再生效新 key,IP 保留。既有未泄露的设备订阅可以继续通过刷新获取新身份,独立 `.conf` 需重新导入。若泄露的是分发链接,另行撤销并重新签发其凭证。
- 移除先撤销 peer,确认后归档、撤销所有绑定凭证。IP 不立即复用。被移除设备的旧 URL 拒绝下发,不能指向后续设备。
## 数据模型与接口
复用上一版设备生命周期实体:`wg_networks`、`wg_gateways`、`wg_devices`、`wg_jobs`、`wg_observations`、用量聚合、`wg_events`、短期 `wg_enrollments`。
设备实体包含名称、系统、固定 IP、公钥、加密存储的私钥/PSK、期望状态和应用版本,**不包含客户端选择**。增加 `wg_subscription_bindings`,保存订阅 ID、设备 ID、分发凭证哈希、用途、创建/访问/撤销时间。它是订阅与设备的受控关系,不是把个人身份写回公共订阅。
建议管理接口:
- `GET/POST /api/wg/devices`、`GET/PATCH /api/wg/devices/:id`。
- `POST /api/wg/devices/:id/actions`、`GET /api/wg/jobs/:id`。
- `GET /api/wg/gateways`。
- `POST /api/tokens/:id/wg-bindings`:沿用现有 `/api/tokens` 资源命名,校验设备权限,签发/复用当前组合凭证;选择变化时不改默认订阅。接口已部署,生产验证见实现记录。
- `POST /api/wg/devices/:id/exports`:授权领取标准配置或生成短期接入票据。
- 公开受凭证保护的拉取入口为原 `/sub/:token/surge` 加可选 `wg`;签名错误、跨订阅使用、暂停或归档明确拒绝,不降级泄露或换身份。
默认托管模式由服务端生成独立密钥、加密保存,再通过授权的 HTTPS 分发。不能声称私钥永不离开设备;若未来增加设备端生成,需要单独实现客户端公钥登记流程。
网关 agent 使用独立认证主动 HTTPS 上报,不持有全站管理员 token。受限 helper 只操作固定 WG 接口,不接受任意 shell。配置更新原子持久化、幂等重试、合并受管 peer,避免重启隧道或删除非受管设备。
## 迁移与验收
先备份,再按网关公钥与客户端公钥纳管现有 Mac/iPad,保留 key、PSK、IP、MTU 和现有连接。只读采集先行,不因平台迁移重建 peer。
现有独立 WG token/旧导出 URL 保留明确的兼容映射,避免立即中断已安装设备;默认共享 URL 保持纯代理。迁移到新方式时,在同一个订阅页选择对应设备,导入带凭证的派生 URL。默认公共地址不失效,但需要 WG 身份的设备托管地址会增加设备参数,这是本设计的明确行为。
实施顺序:只读纳管与采集 → 新增/暂停/恢复/独立导出 → 订阅设备绑定与 Surge 生成 → 三端更新、入站与跨 ISP 远程桌面验收。不因原型完成而声称全部客户端媒体能力已验收。
关键验收:
1. 未选设备时响应完全无 WG,原默认 URL 保持不变。
2. Mac、iPad、iPhone 的派生 URL 各只包含本机身份;选择 B 不改变已生成的 A 链接。
3. 没有私密设备凭证、篡改设备 ID、跨订阅复用凭证均不能读到私钥。
4. 托管 header 保留完整设备 URL,更新/重启后不丢 WG;清除网页选择不撤销已有设备链接。
5. 网关确认前不假成功,失败重试不重复创建,暂停后真实网络不可达,采集失联不显示旧在线/速率。
6. 独立导出与 Surge 引用同一身份;设备暂停、移除、重置与失效链接行为一致。
7. 现有设备不断线纳管;原公网分流行为不因附加 WG 扩大或改变。
## 可点击原型与验证
交互源文件:[wg-device-management.html](wg-device-management.html)。默认打开订阅页,可进入设备列表和详情。所有 URL、设备状态、导出、导入和握手为演示,不发生产请求。
主要体验路径:Surge 订阅 → 选择设备 → 查看带身份链接及结构 → 清除选择恢复纯代理。设备页可新增、详情查看、复制 IP、暂停/恢复、重置/移除及导出独立 WG 配置。
本次浏览器实际检查通过:
- 未选设备、选择 Mac、选择 iPad、清除选择,以及切换非 Surge 格式后的链接与配置结构变化。
- 选中 Mac 的结构仅包含 .3,选中 iPad 仅包含 .2;托管更新 header 保留当前带设备凭证的完整 URL。
- 新增设备不再出现客户端选择;创建后即出现在订阅下拉中,未握手仍为待接入;模拟握手后才显示在线。
- 从设备详情导出独立 WG 配置保留同一 IP;暂停后禁止继续生成接入链接。
- 移除已选设备后旧链接保持明确不可用,清除选择才回到纯代理;没有自动切换身份或静默降级。
- 订阅页与独立导出页在 320、360、736、1024 宽度均无横向溢出,深色外观可用。
- JavaScript 语法、片段结构与无网络请求检查通过;最终浏览器检查无控制台错误。
以上仅验证原型交互与演示结构。真实凭证授权、网关生命周期和三端订阅结果属于实施验收。
参考:[Surge WireGuard](https://manual.nssurge.com/policies/wireguard.html)、[托管配置更新](https://manual.nssurge.com/profile/managed-profile.html)、[WireGuard 工具与状态](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8)、[现有组网记录](../../WIREGUARD-LAN.md)。