7.3 KiB
根域名证书校验补充验收
结论与范围
北京时间 2026 年 9 月 21 日,在已提交并推送的 37bb937 基线上补充验收。发现并修复自动 DNS 证书的校验不一致:申请时要求根域名和泛域名,但运行时共用的域名列表遗漏根域名。正式程序没有替换,其他项目没有停止,用户原有云端测试报告没有修改。
这是一个已实机复现并修复的证书覆盖缺口,不代表真实 DNS 续期或整体验收通过。
需求与任务清单
- [✓] 自动 DNS 证书在申请、配置复验、加载和导出阶段均要求根域名与泛域名。
- [✓] 在云服务器保留整改前失败反例,再用新编译测试程序验证修复。
- [✓] 无效新证书不替换有效导出文件;热加载失败时保留尚有效的内存证书。
- [✓] 后续完整证书仍可热加载,外部证书管理模式的既有兼容测试通过。
- [✓] 云端配置证书专项 21 个顶层测试、SSL 初始化包 26 个顶层测试,均零跳过通过。
- [✓] 本地运行时校验与热加载专项竞态回归通过。
- [✓] 最新前端、插件和 Linux 程序已编译,三库空数据实机回归通过。
- [✓] 配置包静态安全复扫完成,原有七条告警未增加;扫描退出 1,不计为安全门禁通过。
- [!] 公网 DNS 挑战、自动续期、真实 CA 换证和全协议热加载仍需单独实机验收。
整改前反例
测试通过托管存储准备有效期内、密钥配对正确但仅包含 *.example.com 的测试证书,故意不在准备阶段校验域名,模拟已有文件的加载场景。没有使用正式私钥或修改正式证书。
云端目录:/var/tmp/smail-review-ssl-apex-20260921/20260921-042413-before/。
- 配置引用复验错误接受缺少根域名的证书。
- 当前及旧自动 DNS 配置的运行时加载均错误接受。
- 导出错误接受该证书,并替换已导出的有效证书包。
- 根域名加泛域名的正向用例通过;只有根域名的反例已能正确拒绝。
本轮两个顶层测试失败,零跳过,云端测试退出 1。日志完整保留在 test-log/production-remediation-20260921/ssl-apex-before/。这是一个共享校验列表缺口的多路径表现,不按断言数宣传漏洞数量。
修复和回归
backend/config/ssl_custom.go 的 validationCertificateDomains 在自动 DNS 项目托管模式明确加入根域名,继续要求泛域名及已配置的服务域名。保留既有文件安全、证书密钥匹配、有效期和强度校验,不改变手动证书入口、管理责任或 DNS 记录。
新增 backend/config/ssl_apex_test.go,覆盖配置复验、当前及旧配置加载、导出文件内容和身份保留,以及内存证书的拒绝与后续恢复。热加载测试调用实际运行时证书回调,但不是外部客户端对全部邮件协议的换证演练。
| 云端轮次 | 目录后缀 | 结果 |
|---|---|---|
| 最终配置证书专项 | 20260921-042721-final |
21 个顶层测试通过,零跳过,退出零 |
| SSL 初始化完整包 | 20260921-042935-setup-all |
26 个顶层测试通过,零跳过,退出零 |
测试使用非特权 smail、独立临时目录及私有网络,正式目录不可访问;内存上限 256 MiB、CPU 配额 50%、禁用交换空间、运行时间上限 300 秒。最终配置证书专项执行输出记录内存峰值 8.1 MiB,不据此推导生产容量。
本地命令为 node test/run.mjs backend -race -count=1 -p 1 -run '^TestProjectDNS(Runtime|Reload)' ./config,通过。日志目录 test-log/run-2026-09-20T20-28-01-801Z-38632/ 使用 UTC 文件名,不是北京时间日期。
候选产物
前端、Telegram 界面、三个 Linux 插件、Linux 主程序与管理员工具重新编译。版本为 review-apex-20260921,内嵌源码标识为 37bb937c4040ae35a9393c418b9d7679f7bd436d-dirty,不冒充已发布版本。
| 产物 | SHA-256 |
|---|---|
| 主程序 | bb451caf67f6421253c5b4edddc6fce9961ac04613c4fe3166db36a465291939 |
| 管理员工具 | e5b540a23f598f892f23b17f59e2f97c7560f8c3dca317ba6b6cdf2d67485821 |
| 最终配置测试程序 | 6d2cda0c4f3483bb05de86b8067588e27689f80043bd17b3e501e38cbbedacb4 |
| SSL 初始化测试程序 | 263126767560b5e09eccbc415eff5de4192c9c5babc6b16d90417f904a81db4d |
构建日志和摘要位于 test-log/production-remediation-20260921/build-apex.log、apex-build-manifest.json;配置目录 94 个 Go 文件的摘要记录在 apex-config-source-manifest.json。
最新候选三库实机回归
同一主程序上传至 /var/tmp/smail-review-apex-20260921/,每轮创建新的空数据隔离实例,以 192 MiB 内存限额验证直接 TLS 拓扑。
| 数据库 | 实例目录后缀 | 结果 |
|---|---|---|
| SQLite | smail-review-runtime-20260921-043114 |
通过;只有 smail.db,完整性检查正常 |
| MySQL | smail-review-runtime-20260921-043229 |
通过;配置历史与业务同库,SQLite 文件零个 |
| PostgreSQL | smail-review-runtime-20260921-043411 |
通过;配置历史与业务同库,SQLite 文件零个 |
覆盖空库初始化、中文邮件和附件、IMAP APPEND/EXPUNGE、HTTP 旧会话撤销、协议码及客户端码撤销后的旧连接拒绝、过载恢复。三轮均无 OOM、资源采集错误或清理错误;SQL 测试账号已锁定,桥接已停止。
证据为 apex-runtime-results.json、apex-runtime-evidence/ 和 apex-evidence-index.json,共十二份下载文件的摘要已经逐一复核。apex-live-final.json 再次确认六个保护服务和正式程序摘要未变,没有运行中的本轮隔离服务。该回归使用隔离域名和手动测试证书,不冒充公网域名验收、真实自动续期或新候选的 Nginx 正向复验。
静态扫描边界
Windows 主机设置 Linux/amd64、禁用 CGO,对 ./config 运行原有 gosec v2.22.10。55 个文件、11,378 行,包加载错误零,原有 nosec 为 4;七条告警均为中等级,G304 五条、G302 两条,退出码 1。逐条按规则、文件、行号和代码片段与上一轮全项目报告中的配置包比较,集合完全一致。
原始日志为 gosec-apex-config.log,完整提取的 JSON 为 gosec-apex-config.json,SHA-256 为 7c0eed5bd0cb48ab5fd926c431a8155671c5f8418aaeaa9830e49512c2ca7db9。扫描后配置目录九十四个源码文件与构建时清单一致。这里只复扫变更包,不把它说成又一次全项目扫描;上一候选全项目三十八条仍是未通过记录,其他待办没有关闭。
保留的工具失败与证据边界
首次修复后,两个测试已经退出零,但验收辅助工具无条件再次停止已被 systemd 回收的短时单元,收到退出 5,将该轮判为失败;原始记录保留在 ssl-apex-after/,没有改成通过。
后续辅助工具额外读取 LoadState、ActiveState、MainPID,仅在进程为零、状态不活动且明确 not-found 时接受该停止返回值;其他停止错误仍拒绝。新建隔离轮次重新执行后通过。失败记录没有重置,正式服务进程标识和正式主程序摘要均保持不变。
原有浏览器、凭据轮换、外部邮件最终收件、迁移进程重启、容量和异机灾备等门禁仍保留,详见 生产补充验收记录.md。