Files
opsx-vpn/docs/specs/SDD-004-nginx-acme-entry.md
T

41 lines
6.2 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:Nginx 公网认证入口与 HTTP-01
| 字段 | 内容 |
|---|---|
| 级别 | S3(公网暴露面、系统服务、证书私钥) |
| 状态 | 2026-10-22 已部署:`test-link.appx365.com` 经 Nginx 监听 80/443,Certbot 签发并通过模拟续签;独立 OpenVPN 认证域名仍待接入 |
| 已有实现 | SDD-003 的 Go `autocert` 单域名监听已在本地完成,尚未上线 |
| 目标 | 管理员从页面设置域名并查看证书;可选地由 Nginx 承担 80/443、HTTP-01 和认证反代,未知管理站点路径直接断开 |
## 现状与决定
管理平台在 `:18080`,`openvpn-auth-oauth2` 按专线监听 `127.0.0.1:19090+`。2026-10-21 服务器未安装 Nginx/Certbot、80/443 未监听;公网证书尚未签发。Go `autocert` 与 Nginx 不能同时绑定 80/443,必须将入口模式明确区分。服务器的 `/.well-known/openid-configuration` 属于身份提供方的 issuer,并非本项目的 ACME 站点;不能放行所有 `/.well-known/` 子路径,只需 `/.well-known/acme-challenge/`。
推荐的 Nginx 模式:Certbot `--webroot` 签发,Nginx 提供 HTTP-01 和 HTTPS;Certbot 的系统定时器自动续期,并在证书更新后 reload Nginx。Go 保留 `:18080` 但不监听 80/443。管理站点域名(如 `test-link.appx365.com`)只放行现有 SPA 路由、前端静态资源和 Gin 已注册的 API 路由;其他路径 `return 444`。认证入口应使用独立域名(尚未提供真实域名),反代**所有**认证组件路由到其对应的回环端口;只放行 `/oauth2/callback` 会截断登录发起、状态及错误处理。认证组件的路由清单应在安装具体版本后核对,不能预先硬编码。
## 部署与回退
首次引导增量:设置页将通用网络检查(root、默认出口、IPv4 转发)与可选的 Nginx 入口准备分开;只有管理员点击通用修复时才启用 IPv4 转发。各协议专属依赖仍在“创建专线”按所选协议单独检测、安装。Nginx 卡片只读检测 `/etc/os-release`、root、软件可用性;点击准备后以 POST 流接收逐条进度。服务端只执行 Ubuntu 的 `apt-get` 或 TencentOS Server 4 的 `dnf` 固定安装参数,创建 ACME webroot,不接受客户端命令、路径或包名。单次仅一项任务、各命令有超时;浏览器离开不取消已开始的系统包操作。不会写已有 Nginx 站点配置,也不会假称证书已签出。安装完成后须按下述步骤启用 HTTP 站点并签发。初始化失败保留软件包状态,重新检测后可重试,不删除已有配置。
1. 由管理员核对域名、云安全组 TCP 80/443、站点冲突、Nginx/Certbot 软件包和 Certbot 续期定时器;先保存 `nginx` 模式并重启服务,避免 Go 占用 80/443。页面启用操作会检查现有启用站点及监听端口;拒绝覆盖非发行版默认站点或其他自定义站点。
2. 生成最小 HTTP 站点,仅让指定域名的 `/.well-known/acme-challenge/` 从固定 webroot 读取令牌;其他请求关闭。检查 `nginx -t` 后启动 Nginx,用 Certbot `--webroot` 首次签发。发行版默认站点软链接移动至 `/etc/nginx/opsx-vpn-default.disabled`,失败时原路径恢复;签发失败保留 HTTP 验证站点供重试。
3. 证书签出后添加 443 站点;Nginx 配置要精确匹配管理站点路由,TLS 默认主机拒绝握手,认证入口仅以独立 Host 转发到 `127.0.0.1:19090+`。`nginx -t` 通过后 reload,再验证合法 API、SPA 深链接、未知路径、HTTP-01、证书域名和到期日。管理员 API 的 NDJSON 输出在页面实时展示;证书公钥元数据从 Certbot 路径读取,私钥不返回。
4. 验证续期的 `certbot renew --dry-run` 与 deploy hook;证书更新后通过固定钩子校验、重载 Nginx。HTTP 站点安装失败时恢复原配置;证书签发失败保留 HTTP 验证站点;HTTPS 配置校验失败时退回 HTTP 站点。保留 `data/` 和证书缓存。Nginx 模式不把签发结果宣称为 Go `autocert` 的缓存证书。当前 Certbot 注册不提供邮箱,续签异常须主动监控。
## 验收
| 编号 | 验证 | 预期 | 状态 |
|---|---|---|---|
| NG-01 | 非法 Host、未知管理路径、任意 `/.well-known/` 路径 | 不转发,关闭连接;ACME 路径独立可访问 | 已实测未知 `/.well-known/openid-configuration` 和 HTTP `/settings` 断连、ACME 缺失令牌返回 404;非法 Host 待测 |
| NG-02 | 登录、MFA、SPA 深链接、管理 API 和静态资源 | 正常访问,仍由平台做身份与权限校验 | 已实测 HTTPS 登录页、`/settings`、`/tunnels`、JS/CSS 静态资源、健康检查和管理员证书状态接口;MFA 待测 |
| NG-03 | 认证域名打开登录、回调和认证组件所需路径 | 全流程可达,组件只监听回环 | 待真实认证域名与组件 |
| NG-04 | 首次签发与续期 dry-run | 证书有效、续期后 Nginx 重载 | 2026-10-22 首次签发成功,到期日 2027-01-19;模拟续签成功,deploy hook 执行、Nginx 保持 active(证书验证 stderr 在 Certbot 日志显示为非致命警告) |
| NG-05 | Ubuntu / TencentOS 4 首次引导 | 匹配各自包管理器、实时显示输出、并发重复请求拒绝;不覆盖已有站点 | Ubuntu 24.04 实机安装完成;TencentOS 4 仅单测 |
## 边界
`return 444` 是 Nginx 的断连响应,不是权限控制;合法接口仍必须由 Gin 鉴权。Go `autocert` 模式不会提供 `return 444`。不能用路径白名单阻断 ACME 续期、MFA 或 WebAuth。认证域名与管理域名若合并,需要重新设计路径分发及 Cookie 隔离,不能直接套用独立域名配置。认证域名接入仍待独立域名和真实发行者信息;Certbot 续签 dry-run 与公网联调以实际执行记录为准。
当前 `:18080` 仍监听公网,旧客户端以 HTTP 直连会绕过 Nginx 的 444 白名单;迁移客户端服务地址至 HTTPS 后应单独收紧 18080。2026-10-22 本机对域名的第二轮公网探测出现连接重置/DNS 波动,服务器回环直连 HTTPS `/settings` 和管理健康检查正常;持续公网可用性需结合实际用户网络观察。
设置页面显示这一直接端口暴露状态,防止管理员仅依据已签出的证书误认为外部访问都经过 Nginx。