Files
opsx-vpn/docs/specs/SDD-004-public-entry-scheme-port-upload.md
T

63 lines
5.1 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.1 / S3 |
| 设计状态 | 已形成,随发布核验更新 |
| 实现状态 | 已实现;本地构建/测试及生产 HTTPS 回归通过,未在线切换到 HTTP 或上传证书 |
| 负责人 / 日期 | opsx-vpn / 2026-10-26 |
| 关联需求 | 用户调整 HTTP/HTTPS 公网入口及内网相关实现,要求提交并部署 |
| 批准状态 | 用户已授权提交和部署 |
## 1. 背景、目标与范围
- 当前行为与证据:`tlsservice` 读取 `data/tls-*`,`nginxconfig` 生成托管站点,`nginxgateway` 校验并重载;`identityprovider` 和 OpenVPN OIDC 引用公网入口。生产实例为 Nginx HTTPS:443,管理服务监听 :18080,原证书为 Let's Encrypt。
- 目标:支持保存 HTTP/HTTPS 域名及自定义端口,HTTP 不申请证书;HTTPS 保留 HTTP-01 路径;证书上传验证并可安全切换;身份回调使用实际入口地址。
- 非目标:变更现有生产入口为 HTTP、修改现有证书、切换管理服务监听地址或安装 VPN 依赖。
- 保留:旧配置缺省 HTTPS:443,当前 `/id`、`/oauth2` 和管理 API 的路由及已建立的 VPN 进程。
## 2. 需求与约束
- FR-01:管理员设置协议、域名、端口,状态及预览展示准确的公网地址;旧配置维持 HTTPS:443。
- FR-02:Nginx HTTP 入口仅代理现有白名单;HTTPS 保留 80 端口供 HTTP-01,拒绝端口冲突和未知路径。
- FR-03:身份发行者和 OpenVPN OIDC 回调使用相同公网地址,避免端口或协议不一致。
- FR-04:上传证书必须匹配域名和私钥且在有效期内;成对写入,入口重载失败后恢复原证书并报告失败。
- NFR-01:私钥不可进入 Git/响应,落盘权限 0600;安全相关配置错误须阻止切换。
## 3. 架构与方案
`PUT /api/system/tls/domain` 保存协议、域名、端口;重启后 `tlsservice.Status` 为页面、身份服务和 Nginx 入口提供公网地址。Nginx 依协议生成 HTTP 或 HTTPS 站点;证书上传先写私有版本目录,再原子切换 `current` 链接并尝试重载,失败恢复前一版本及来源标记。生产部署只替换应用程序与前端资源,不自动调用入口切换接口。
## 4. 接口、数据与配置契约
- 管理接口:`PUT /api/system/tls/domain` 增加 `scheme` 与 `port`;证书上传 `POST /api/system/tls/certificate` 接收 `host`, `certificate_pem`, `private_key_pem`。认证边界沿用 `backend/internal/api/api.go`。
- 数据:新增 `data/tls-scheme`, `data/tls-port`, `data/tls-cert-source` 及 `data/tls/certs/<domain>/current`,无数据库迁移;旧文件缺失时采用 HTTPS:443。
- 环境变量 `VPN_TLS_*` 优先;身份发行者遵循公网地址。页面不回显私钥。
## 5. 风险与验收
| 风险或失败场景 | 防护 / 恢复 | 可观察信号 |
|---|---|---|
| 无效域名、占用 80 或内部端口 | 保存或渲染时拒绝 | API 错误及预览失败 |
| 证书不匹配、过期、Nginx 重载失败 | 拒绝上传或回滚原证书及来源 | API 错误、旧证书仍可用 |
| 生产重启失败 | 恢复 `/tmp` 中旧二进制 | 健康检查、进程及 Nginx 检查 |
| HTTP 传输凭据明文 | 默认保留 HTTPS:443;仅管理员显式配置 HTTP | 状态协议和公网探测 |
| AC | 对应需求 | 前置条件与操作 | 预期结果 | 验证方式 | 结果 |
|---|---|---|---|---|---|
| AC-01 | FR-01 | 旧配置及新协议端口 | 状态、页面和预览一致,旧配置为 HTTPS | Go 单测、前端构建 | 本地通过;线上保持 HTTPS:443 |
| AC-02 | FR-02, NFR-01 | 渲染 HTTP/HTTPS、冲突端口 | 白名单与 HTTP-01 正确,冲突被拒绝 | Go 单测、线上 nginx -t | 本地及线上配置检查通过;线上 HTTP 切换未执行 |
| AC-03 | FR-03 | 使用 HTTP/HTTPS 公网地址 | 发行者与回调地址一致 | Go 单测、HTTPS discovery | 本地通过,线上 HTTPS issuer 已验证;线上 HTTP 未执行 |
| AC-04 | FR-04, NFR-01 | 上传匹配、不匹配和刷新失败证书 | 正常切换,异常保留旧证书与来源 | Go 单测 | 本地通过;线上证书上传未执行 |
| AC-05 | FR-01, FR-02 | 部署后请求生产入口 | 仍为 HTTPS,健康检查成功,VPN 进程存活 | curl、nginx -t、进程检查 | 线上通过,2026-10-26 |
## 6. 发布与恢复
本地测试和构建通过后,仅提交本次相关文件,推送 `origin/master`;服务器确认工作树干净并快进拉取。备份二进制与数据库到 `/tmp/opsx-vpn-backups`,仅保留最近两份。先构建前端再构建内嵌资源的 Go 二进制,核对 PID 后停止并替换管理进程,保留 OpenVPN 进程和 `data/`。检查本地及公网健康、HTTPS 证书与发现文档、Nginx 语法和 VPN 进程。失败时恢复旧二进制并重启;不改动已有证书或数据库。无计划内不可逆操作。
## 7. 待决问题
| 问题 | 是否阻塞 | 推荐方案 |
|---|---|---|
| 是否需要将 :18080 收敛为仅回环 | 不阻塞本次发布 | 单独评估客户端迁移与防火墙后执行 |