Files
opsx-vpn/docs/specs/SDD-002-desktop-wireguard-client.md

16 KiB
Raw Permalink Blame History

SDD-002:opsx-vpn 桌面客户端与 WireGuard 接入评估

字段 内容
版本 / 变更级别 0.1 / S3(未来涉及设备凭据、系统路由和隧道权限)
设计状态 Draft
实现状态 第一阶段骨架已完成;第二阶段终端用户 API、设备 Peer 登记/撤销与桌面连接代码已集成,尚待目标 OS 真实握手验收
负责人 / 日期 待指定 / 2026-10-21
关联需求 仓库根目录新增 client/,Rust + Tauri v2 桌面客户端,优先对接 WireGuard
批准状态 用户要求评估并新增客户端;后续接口契约尚待确认

1. 背景、目标与范围

  • 当前行为与证据:服务端路由的 /api/login 是管理账号登录,/api/tunnels/:id/wireguard/peers 的读写与配置下载需要 operator 以上角色;WireGuard 实现可以为管理端生成 Peer 私钥和 .conf,新增/删除 Peer 会停止再启动正在运行的隧道。节点 API /api/nodes 是管理节点信息,尚不是面向终端用户的可用线路目录。
  • 目标:参考 ../opsxshell 与 ../opsxapi 的桌面项目形态,在 client/ 建立独立 Tauri v2 + Rust + React/TypeScript 项目;第一阶段只做可验证的真实服务健康检查和清晰的接入状态;给出后续控制面/数据面改造顺序。
  • 非目标:第一阶段不使用管理员令牌给终端用户创建 Peer,不自动安装驱动、修改本机 DNS/路由或连接 VPN,不兼容飞连私有协议,不宣称飞书/LDAP 用户已经能领取 WireGuard 设备配置。
  • 保留行为:现有 frontend/ 管理后台、现有 WireGuard 隧道和已经签发的 Peer 均不改变;服务端 Go 与桌面 Rust 独立构建。

2. 需求与约束

  • FR-01:桌面端可输入控制面 HTTP 或 HTTPS 根地址,使用 Rust 命令调用现有 /api/health 并显示真实结果;HTTP 允许用户保存和检测,但显著提示明文传输风险。
  • FR-02:界面将“服务已可达”与“用户已登录/隧道已连接”分开显示;尚无客户端 API 时连接控制不可触发拨号,线路页必须显示不可获取状态,不得展示虚构节点或延时。
  • FR-02a:桌面端采用蓝白灰连接概览与窄侧栏;只有真实健康检查可展示控制面往返耗时,且明确不等于 VPN 节点延时。
  • FR-02b:托盘明确显示未连接,并提供打开窗口与退出;设置页只读检查本机 PATH 中是否存在 wg、wg-quick,不得把工具存在等同于可拨号或已连接。
  • FR-03(后续):专门的终端用户认证、MFA/OIDC 与短期设备令牌;区分管理员和拨号用户,过期、退出及设备撤销有可验证行为。
  • FR-04(后续):由桌面端生成并保管 WireGuard 私钥,只上传公钥;服务端按用户/设备身份分配地址、Peer、路由及 DNS,签发有限时配置并处理回收。
  • FR-05(后续):针对 Windows/macOS/Linux 的系统隧道、权限、路由/DNS 回滚和断线恢复逐平台交付;首版仅标准 WireGuard UDP。
  • FR-06(后续):终端用户在客户端登录后,客户端自动注册设备并取得该设备专属 WireGuard 参数,无需管理员或用户手动下载、导入 .conf;连接按钮只有在系统确认接口、路由、DNS 和握手时才能显示已连接。
  • NFR-01:应用不能请求广泛的 shell/filesystem 权限;客户端机密不进入前端源码、日志或仓库。桌面应用与管理 API 使用不同鉴权边界。
  • NFR-02:健康检查超时且 TLS 默认验证证书;失败时展示可读原因,不把网络失败当 VPN 连接失败。

3. 架构与取舍

React 页面 → Tauri invoke → Rust 命令/服务 → opsx-vpn 控制面 HTTPS
                                                │  登录/授权/设备与 Peer(后续)
                                                └→ 标准 WireGuard UDP 网关
Rust 系统隧道适配层(后续) ← 仅在本机保存的 WireGuard 私钥
  • 客户端采用 client/src + client/src-tauri,参考同族项目的轻量 Tauri v2 壳,不复制其 SSH/HTTP 工作台或许可证逻辑。UI 使用 React + TypeScript;网络请求由 Rust 执行,避免将控制面令牌交给 WebView。
  • UI 参考用户提供的蓝白灰截图与 Clash Verge Rev 的桌面交互分层思路;Clash Verge Rev 是 GPL-3.0-only,未复制其源码和视觉资源。概览只使用已保存地址的真实健康检查;线路页在缺少终端用户线路接口时显示不可获取状态,不伪造节点、延时或连接。
  • corplink-rs、Client_UI_for_Corplink 与 PinkD 的 wireguard-go 面向飞连私有控制协议;现有 opsx-vpn 使用 Linux wg/wg-quick 和标准 WireGuard。不要引入 protocol_version 等私有扩展或假设它们兼容。SOCKS5/netstack、WireGuard over TCP 另行评估。
  • 可选的近期验证路线:由管理员在现有管理端下载独立测试 Peer 配置,再用目标 OS 的标准 WireGuard 客户端验证网关;桌面端的自动拨号必须等设备 API 和权限模型明确后再做。

Clash Verge Rev 参考范围与接入顺序

已只读核对本地 ../demo/clash-verge-rev 的 src-tauri/src/lib.rs、ipc.rs、feat/tun.rs、core/tray/、core/service.rs、core/updater.rs 与 Tauri 配置。其 Tauri IPC 类型与命令集中管理、托盘状态、服务可用性检测、配置写入失败恢复以及按平台拆分是可参考的设计方式;该项目的系统代理、Mihomo TUN/服务、订阅配置及更新地址都不能直接用于 opsx-vpn。其 GPL-3.0-only 源码、图标和界面资源不复制进当前仓库。

顺序 借鉴方向 opsx-vpn 需要自行实现或验证的前置条件
1 Rust IPC 边界、连接状态模型、线路选择、托盘显示 先有独立的终端用户身份/设备授权 API;线路和托盘只能根据实际授权、握手与系统隧道状态宣称“已连接”
2 服务可用性检查、失败恢复、跨平台权限管理 使用目标系统支持的标准 WireGuard 隧道方案,分别验证安装/卸载、DNS/路由保存与恢复、崩溃及重启行为;不以 Mihomo TUN 或系统代理开关替代 WireGuard
3 配置存储与更新流程 私钥在客户端安全存储,令牌按平台凭据库管理;普通偏好与机密分离。具备签名、可信发布地址和回滚策略后才添加自动更新

corplink-rs 仅在明确提出兼容飞连官方服务且确认私有协议、许可与长期维护成本后作为研究参考,不能作为本项目认证或隧道实现的基础。当前项目的认证对象是 opsx-vpn 自己的 LDAP/飞书用户,需由 opsx-vpn 签发客户端设备身份;飞连企业识别码、Cookie、私有 WireGuard 扩展字段不属于本项目契约。

4. 接口、数据与配置契约

  • 第一阶段复用 GET /api/health,不新增服务端 API、不改变数据库或现有 Peer 数据。
  • 桌面原生命令 get_system_readiness 返回操作系统和 PATH 中 wg、wg-quick 文件存在性;不执行这些工具、不申请特权,也不访问 VPN 凭据。托盘当前仅提供未连接静态状态、打开与退出,未来需绑定真实隧道状态机后才能展示连接状态。
  • 桌面 check_server(base_url) 只返回地址、是否可达及错误,不持久化用户口令或令牌。默认不配置公网地址;用户可填写 HTTP 或 HTTPS 根地址,成功检测后在本机保存并在概览每 30 秒复测;后续认证流程仍推荐可信 HTTPS。
  • 后续拟新增独立的客户端 /api/client/* 契约:登录/续期、可用线路、设备注册(公钥、设备标识)、设备吊销、连接配置领取及状态。响应不下发服务端私钥,客户端私钥不上传。接口形状、LDAP/飞书绑定与授权范围在实现前另行确定。
  • 自动连接的服务端先决条件:建立普通用户身份和 WireGuard 专线之间的明确授权关系,不复用管理后台 /api/login 的管理员权限;设备由客户端生成私钥并上传公钥,服务端须原子分配独立 Peer/IP、限制设备数量与授权期限,支持撤销;运行中的 Peer 应增量更新,避免重启其他用户的隧道。随后才向已授权设备提供端点、路由、DNS 与服务端公钥,密钥不得进入 WebView 或日志。
  • 首发 macOS 隧道执行层需有权限受限的原生组件,以受控方式创建/关闭隧道并恢复路由和 DNS;wg、wg-quick 出现在 PATH 不等于具备权限。Windows 和 Linux 各有单独验收,不以 shell 执行任意用户输入配置或要求客户端以管理员账户登录管理 API。
  • 配置下载目前包含由服务端保存的客户端私钥,不得将管理员下载接口直接暴露给桌面端;现有管理员 /api/login 不等价于终端用户准入。

5. 风险与验收

风险或失败场景 处理方式 可观察信号
把管理 token 当拨号凭据 另建按用户/设备授权的控制面;第一阶段仅匿名健康检查 无管理 API 调用
设备私钥从管理配置泄漏 后续客户端生成密钥、公钥注册及撤销;不直接调用管理下载接口 设备 API 与密钥审计
Peer 更新影响现有连接 后续用 wg set 等增量更新并测试掉线影响,再启用自动注册 连接连续性、审计日志
Windows/macOS/Linux 权限差异 按平台单独设计特权 helper、安装与回滚;第一阶段不创建 TUN 平台专项验收
AC 对应需求 前置与操作 预期结果 验证方式 状态
AC-01 FR-01, NFR-02 输入有效/无效及远端 HTTP 地址并点检测 真实健康结果、成功后保存、错误与拒绝行为明确 Rust 单测、UI 构建、桌面试连 Rust 测试与 UI 构建通过;浏览器手动截图显示远端健康检查可达,保存及重开验收待做
AC-02 FR-02, FR-02a, NFR-01 打开概览和线路 蓝白灰界面、真实健康检查;无授权接口时显示不可获取线路,不调用管理 API 或修改系统 UI 构建、代码检查、桌面启动 UI 构建通过;桌面手动视觉验收待做
AC-02b FR-02b, NFR-01 在桌面端打开托盘并访问设置页 托盘显示未连接,能打开/退出;本机工具存在性仅标注为 PATH 检查结果 原生构建、桌面手动检查 UI 构建及 Rust 测试通过,Tauri 开发进程已重启;托盘点击与设置页人工验收待做
AC-03 FR-03 普通用户/MFA/过期令牌/撤销设备 仅已授权设备可领取配置 后续 API 集成测试 Not Run
AC-04 FR-04 同一用户多个设备注册/注销 各设备独立密钥、Peer、地址与审计 后续真实网关联调 Not Run
AC-05 FR-05 各 OS 正常连接与异常退出 路由/DNS 可恢复,不影响已有连接 后续目标 OS 实机验收 Not Run
AC-06 FR-06 新用户首次点击连接并完成登录;退出、撤销与重装再连 自动注册并获得专属配置,无需下载文件;只在真实握手后显示连接,撤销后不能重连 客户端/服务端集成测试、macOS 实机与网关握手 Not Run

6. 发布与恢复

  • 第一阶段仅新增 client/,不修改服务器进程、不申请系统特权;构建检查与桌面手动健康检查后才能称为可运行。
  • 2026-10-21 已经管理 API 在现有服务器上创建测试专线 opsx-client-pilot(ID 4),配置与早期核验见 WireGuard API 创建记录。后续只读复核确认 wg4 已在 UDP 51820 监听,公网测试包可达,但 Peer 握手仍为零;不代表桌面客户端可以认证或连接。
  • 后续按“独立客户端身份与专线授权 API → 设备注册/增量 Peer 更新 → macOS 原生隧道实机握手 → Linux/Windows 适配”逐步交付;客户端自动领取配置,下载 .conf 仅作为管理员排障功能。2026-10-21 只读核对:试验专线 wg4 已运行,UDP 51820 可从公网抵达服务器,但尚无 Peer 握手,不能据此声称桌面客户端已连接。
  • 若后续客户端版本故障,先禁用其设备访问凭据并停用客户端,保留现有管理后台与隧道;数据迁移需独立备份和回滚方案。

7. 待决问题

问题 是否阻塞第一阶段 建议
首发 OS 与安装包签名 不阻塞骨架 先选一台真实目标 OS 验收,再扩平台
企业账号映射到 VPN 权限、MFA/OIDC 与设备配额 阻塞自动拨号 稳定用户 ID + 单独设备授权策略,不按同名邮箱猜测
会话断开是否自动注销 Peer 阻塞自动拨号 区分临时连接与已授权设备;明确租约、续期与撤销
是否需要代理模式/TCP/飞连兼容 不阻塞标准 WireGuard UDP 先证明原生 WG 客户端与当前网关互通

8. 第二阶段:终端用户自动接入(2026-10-21)

实现范围:新增 /api/client/login 及令牌保护的线路、设备登记、配置、状态、撤销接口;管理后台展示设备和撤销入口。登录按 VPNUser 的实际密码与 TOTP 验证,令牌内的授权快照绑定拨号记录 ID 和凭据指纹,后续逐次核对记录仍存在、已启用、凭据未变化。管理员禁用/删除/改密或改变 MFA 时先撤销对应 WireGuard 设备,再注销相关令牌。客户端在 Rust 生成私钥,本机按服务器和用户名隔离设备记录,支持 Linux/macOS wg-quick 一键连接;未实现 Windows 系统隧道。

账号入口与版本检测:/users 是后台管理员,/vpn-users 才是客户端拨号身份。客户端先请求匿名 /api/client/capabilities 确认服务端支持,再发送密码;旧服务端将未知 API 返回 200 HTML 时明确提示升级。oidc: false 只表示 WireGuard 客户端浏览器免密码登录尚未实现,不影响 OpenVPN 独立插件的 OIDC 模式。后续可用浏览器 Authorization Code + PKCE、稳定飞书身份与 VPNUser 授权映射、一次性设备注册授权实现免密码;openvpn-auth-oauth2 的 OpenVPN 管理接口不能直接用于 WireGuard。是否有标准 OIDC issuer、回调域名及身份映射规则需接入前确定。

持久化与兼容:AutoMigrate 新增 client_devices、client_sessions 表;现有 VPNUser、Tunnel 及老 Peer 不重写。终端令牌仅存 SHA-256 哈希,旧客户端不存在有效令牌;设备记录绑定 VPNUser ID,同名但密码不同的线路不能借授权互访。用户密码/MFA 变更前的 Peer 永久撤销,需要客户端再次登录并重新登记设备。客户端允许 HTTP 控制面地址,但明确显示明文风险;生产建议 HTTPS。

风险与恢复:设备增删先协调运行态与磁盘配置;下发失败会尝试清理部分创建的 Peer,清理失败保留设备记录及审计,管理员应核对 wg show 和管理设备页。变更前备份 SQLite 数据、WireGuard 专线目录;如迁移或启动失败,回退二进制与数据库备份,不能只回滚二进制并假定新 Peer 自动失效。关闭新客户端 API 或撤销客户端令牌不等于断开已登记 Peer,须同时撤销设备/停止对应专线。Mac 提权调用与本机路由/DNS 回滚须在目标系统实机验收;Windows 暂不支持拨号。

AC 对应需求 操作与预期 当前证据
AC-03 FR-03 同名用户两线路使用不同密码,旧令牌不得访问另一线路;修改凭据后令牌失效 后端回归测试通过,真实 LDAP/TOTP 流程待验
AC-04 FR-04 公钥登记/撤销后持久配置与运行接口一致,旧用户被禁用时撤销 Peer 后端 Peer 单测通过,运行态故障注入待验
AC-05 FR-05 Linux/macOS 授权后连接及断开,路由和 DNS 恢复 Rust 单测通过;目标系统实机未验
AC-06 FR-06 自动领取配置;握手超时显示重新连接中;更换线路不丢原设备密钥 Rust 单测和前端构建通过;真实网关握手未验