Files
opsx-vpn/docs/specs/SDD-004-client-entry-and-node-choice.md
T

64 lines
7.5 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.
# SDD-004:客户端企业入口与线路选择
| 字段 | 内容 |
|---|---|
| 版本 / 级别 | 0.2 / S3(客户端交互、认证配置安全边界与列表展示) |
| 设计状态 | 实施中 |
| 实现状态 | 客户端企业入口、能力读取、路由标签、实测隧道探测与信号格、WireGuard 认证配置边界和专线列表已实现;WireGuard 浏览器 OIDC 仍未实现 |
| 日期 | 2026-10-21 |
| 关联需求 | 企业选择、飞书登录入口、模式和节点延迟;WireGuard 认证方式与专线列表操作 |
| 批准状态 | 用户提供竞品截图并要求按现有项目继续实现 |
## 1. 背景、目标与范围
- 当前 `client/src/App.tsx` 只有服务端地址和密码表单、线路平铺列表。`backend/internal/api/api.go` 的匿名 `/api/client/capabilities` 返回 `oidc: false`;OpenVPN 的 `openvpn-auth-oauth2` 与 WireGuard 客户端会话互不兼容。`backend/internal/api/client.go` 的线路含 `endpoint`,不含节点 RTT;`client_probe` 是经 WireGuard 到固定公网 TCP 目标的诊断。
- 目标:以 OpsX 自己的品牌做企业入口、认证选择和节点选择弹窗;用户配置的服务器才是“单位”,不预填竞品单位。只给实测线路显示延迟/颜色和信号格。
- 本次不新增身份映射、全局路由覆盖或系统 DNS 修改。登录方式与网络模式必须与真实服务端/本机能力一致。保留已有 HTTP 地址支持、密码/MFA 登录、登录会话、设备私钥和连接状态语义。
## 2. 需求与约束
- FR-01:登录页标为“选择接入点”,填写服务端地址并自动带入上次使用的地址;验证真实 `/api/health` 后进入认证界面。切换接入点清除账号口令,不显示历史地址下拉。
- FR-02:根据服务端 `/api/client/capabilities` 的 `password/oidc` 能力决定展示入口;`password:false` 不呈现密码表单,`oidc:false` 不呈现飞书入口。`oidc:true` 但客户端浏览器回调未实现时明确禁用,不重定向到 OpenVPN 回调;两者均不可用时提示管理员。未来开启浏览器登录须实现授权码+PKCE、回调一次性交换与稳定 `issuer/sub` 绑定 VPNUser,禁止按邮箱自动授予线路。
- FR-03:线路选择展示服务端真实授权线路;极速/全局用线路下发的路由策略判断。未有可切换策略时模式只是当前策略标记,不保存虚构偏好或擅自修改 AllowedIPs。
- FR-04:延迟数据必须来自对应线路的实际 Go WireGuard 探针。探测失败/未登记设备时显示不可测,不得用控制面健康请求替代节点 RTT;阈值只用于实测后的色彩映射。
- NFR-01:无效授权与离线不应误报已登录、已连接或高质量节点;浏览器预览不调用原生接口。
- FR-05:WireGuard 创建和编辑页展示认证方式:现有“客户端账号 + 设备密钥”可选;第三方 OAuth2/OIDC 显示接入说明且不可选。服务端对显式提交未知模式或 oidc 拒绝保存;旧配置无字段保持原行为。静态 Peer 的已有密钥能力不受此选项保护,页面应如实提示。
- FR-06:专线列表和详情显示认证方式;列表启动/停止按钮固定可见,并依据实际运行状态切换;其他协议不臆测认证类型。
## 3. 架构与方案
前端负责向导和显示;Rust 验证服务端地址、取得 `password/oidc` 能力并调用当前已有的客户端 API;Go 组件执行真实 TCP 出口探测。按用户选择的运行中线路拨号,后端继续按 `VPNUser` 授权隔离。节点列表使用现有 `/api/client/lines`,不造地理位置/服务器名称。OpenVPN OIDC 配置不作为客户端 OIDC 能力来源。
## 4. 接口、数据与配置契约
- 匿名 `/api/client/capabilities` 既有 `password/oidc/wireguard` 布尔值;可选 `oidc_provider` 用于将飞书/Lark 与其他 OIDC 提供商区分,旧服务端缺字段按普通“第三方认证”显示。`oidc:false` 时隐藏第三方认证入口,`password:false` 时隐藏密码表单;老服务端返回 HTML 则不进入登录步骤。
- `client_probe` 在原结果基础上增加本次成功连接耗时 `latency_ms`(含隧道启动与握手);未成功时不提供延迟。前端只为对应线路显示该值,重新选择单位或重新登录后清除。可选 `latency_probe` 为 VPN 路由内的 IP:端口;未配置时用 `223.5.5.5:443`。线路接口增加由 `AllowedIPs` 推断的 `routing_mode`(`split` / `global_ipv4`);旧服务端缺字段时客户端不推断全局模式。
- 不修改 SQLite、设备配置或 WireGuard Peer 授权范围。不新增第三方 logo、虚构地区和用户协议链接。
- WireGuard 配置新增可选 `auth_mode=password`;旧记录缺失时按既有客户端账号+设备密钥行为显示。只有 WireGuard 新增服务端枚举校验,`oidc` 不能写入配置;列表从 JSON 配置读取既有 OpenVPN `auth_mode`,未知配置显示未指定。启动/停止使用原有 API。
## 5. 风险与验收
| 风险 | 防护 / 恢复 | 可观察信号 |
|---|---|---|
| 将 OpenVPN OAuth 当 WireGuard 登录 | 飞书入口根据客户端能力禁用;文案区分两者 | `oidc:false` 下无法点击浏览器授权 |
| 非法 WireGuard OIDC 配置被误认为安全登录 | 下拉禁选且后端验证拒绝;保留原设备密钥与静态 Peer 流程 | 创建/编辑传 `oidc` 返回校验错误 |
| 将 HTTP 或隧道探针误称为节点 RTT | 清楚标注“隧道 TCP 建链耗时”,未测为中性 | 无数据时没有绿色/黄色毫秒值 |
| 选择全局模式导致错误路由 | 根据专线真实 AllowedIPs 显示当前策略,未具备切换条件则不可切换 | 不更改系统路由与专线配置 |
| AC | 对应需求 | 操作与预期 | 验证方式 | 结果 |
|---|---|---|---|---|
| AC-01 | FR-01 | 新用户配置地址、检测成功、进入认证;切换单位清空表单 | 客户端 UI 构建、桌面窗口启动;真实登录需账号验收 | 构建/启动通过,真实登录待验收 |
| AC-02 | FR-02 | `oidc:false` 隐藏第三方入口;`password:false` 隐藏密码入口;`oidc_provider=feishu` 显示飞书标签但保持禁用 | 客户端 UI 构建、能力契约单测;实际账号登录待验收 | 构建与契约单测通过,实际登录待验收 |
| AC-03 | FR-03 | 运行中线路可选;全局模式不在私网路由上假激活 | 路由推断 Go 单测、客户端 UI 构建 | 通过 |
| AC-04 | FR-04 | 真实探测显示毫秒数;失败显示不可测 | Go/Rust 测试、真机试验 | 测试通过,真机延迟/线路切换待验收 |
| AC-05 | FR-05 | WireGuard 创建/编辑显示两种方式,其中 OIDC 不可选;手工请求 `auth_mode=oidc` 被拒;无字段旧配置可验证 | 后台构建、Go 单测 | 通过;界面手工验收待进行 |
| AC-06 | FR-06 | 不同协议列表认证标签正确;运行和停止状态有清晰按钮 | 后台构建、代码检查 | 构建通过;界面手工验收待进行 |
## 6. 发布与恢复
先验证 Go 服务端再发布前端及桌面客户端;本轮不修改生产网关。若需回退,恢复原服务端/前端构建与桌面客户端构建;新 `auth_mode=password` 对旧服务端为普通附加字段,旧配置仍可读取。无需迁移数据库或撤销现有授权。
## 7. 待决问题
正式飞书 OIDC 需要 HTTPS issuer、应用凭据与回调域名,以及管理员确认的飞书 `issuer/sub` 对 VPNUser 授权映射;没有这些配置不得显示可用的一键登录。全局 VPN 需后续系统隧道权限、NAT 与 DNS 恢复验收。