63 lines
4.8 KiB
Markdown
63 lines
4.8 KiB
Markdown
# SDD-004:公网入口协议、端口与证书上传
|
||
|
||
| 字段 | 内容 |
|
||
|---|---|
|
||
| 版本 / 变更级别 | 0.1 / S3 |
|
||
| 设计状态 | 已形成,随发布核验更新 |
|
||
| 实现状态 | 待本地与生产验证 |
|
||
| 负责人 / 日期 | 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 单测、前端构建 | 待验证 |
|
||
| AC-02 | FR-02, NFR-01 | 渲染 HTTP/HTTPS、冲突端口 | 白名单与 HTTP-01 正确,冲突被拒绝 | Go 单测、线上 nginx -t | 待验证 |
|
||
| AC-03 | FR-03 | 使用 HTTP/HTTPS 公网地址 | 发行者与回调地址一致 | Go 单测、HTTPS discovery | 待验证 |
|
||
| AC-04 | FR-04, NFR-01 | 上传匹配、不匹配和刷新失败证书 | 正常切换,异常保留旧证书与来源 | Go 单测 | 待验证 |
|
||
| AC-05 | FR-01, FR-02 | 部署后请求生产入口 | 仍为 HTTPS,健康检查成功,VPN 进程存活 | curl、nginx -t、进程检查 | 待验证 |
|
||
|
||
## 6. 发布与恢复
|
||
|
||
本地测试和构建通过后,仅提交本次相关文件,推送 `origin/master`;服务器确认工作树干净并快进拉取。备份二进制与数据库到 `/tmp/opsx-vpn-backups`,仅保留最近两份。先构建前端再构建内嵌资源的 Go 二进制,核对 PID 后停止并替换管理进程,保留 OpenVPN 进程和 `data/`。检查本地及公网健康、HTTPS 证书与发现文档、Nginx 语法和 VPN 进程。失败时恢复旧二进制并重启;不改动已有证书或数据库。无计划内不可逆操作。
|
||
|
||
## 7. 待决问题
|
||
|
||
| 问题 | 是否阻塞 | 推荐方案 |
|
||
|---|---|---|
|
||
| 是否需要将 :18080 收敛为仅回环 | 不阻塞本次发布 | 单独评估客户端迁移与防火墙后执行 |
|