在单台服务器上给一个域名申请证书,HTTP-01 通常够用。但当环境扩展到多台服务器、内网服务、CDN、负载均衡和多个云账号时,HTTP-01 很快会暴露限制:80 端口不一定开放,挑战文件可能被反向代理改写,切换服务器后还要重新配置验证路径。
DNS-01 更适合复杂环境,而 CNAME 委托可以进一步把“业务 DNS 管理”和“ACME 挑战记录管理”分离。本文记录一套可落地的设计与排错方法。

一、DNS-01 验证解决什么问题
CA 在签发证书前,需要确认申请者控制目标域名。DNS-01 的做法是在指定位置创建 TXT 记录:
_acme-challenge.example.com TXT "challenge-token"
CA 查询到正确值后,域名验证通过。与 HTTP-01 相比,DNS-01 有几个明显优势:
- 不依赖 80 端口和 Web 服务;
- 可以签发通配符证书;
- 内网服务器不需要暴露验证端口;
- 证书签发节点和业务服务器可以完全分离。
但如果自动化程序直接持有业务 DNS 账号的完整权限,安全风险也会随之放大。CNAME 委托就是为了解决这个问题。
二、CNAME 委托的基本结构
在业务域名的 DNS 服务商中配置一次:
_acme-challenge.example.com CNAME _acme-challenge.example.validation.example.net
之后,自动化系统只在 validation.example.net 这个专用验证区域内创建 TXT 记录:
_acme-challenge.example.validation.example.net TXT "challenge-token"
CA 查询原始挑战名称时会跟随 CNAME,最终读取到验证 TXT。业务域名的 A、AAAA、MX 等记录完全不受影响。
三、为什么委托域名要单独设计
验证域名不应该只是随便找一个二级域名。生产环境至少要考虑以下几点:
1. 唯一映射
不同租户、不同域名不能写入同一个不受隔离的记录名。可以使用域名哈希或租户 ID 构造唯一挑战名称,例如:
_acme-challenge.<domain-hash>.validation.example.net
2. 最小权限
DNS API 密钥只允许修改验证区域,不能修改业务根域。即使签发 Worker 的凭据泄露,攻击范围也被限制在 ACME 挑战记录。
3. 不覆盖同名 TXT
同一域名可能同时存在多个 ACME Order,或被多个 CA 并发验证。新增 TXT 时必须执行 AddTXT,而不是先删除同名记录再写入。清理时也只能删除当前订单创建的值。
四、TXT 记录传播不能只靠 sleep
很多脚本创建 TXT 后固定等待 30 秒,然后直接通知 CA 验证。这种方式在测试环境可能正常,但生产中并不稳定。
更可靠的做法是分层检查:
伪代码如下:
deadline = now + propagation_timeout
while now < deadline:
if authoritative_dns_has(token) and recursive_dns_has(token):
return READY
sleep(backoff.next())
return PROPAGATION_TIMEOUT
退避时间应逐渐增加,避免短时间内高频请求 DNS。
五、ACME Order 要做成状态机
证书签发通常跨越多个网络步骤,不能放在一个同步 HTTP 请求中硬等结果。建议使用明确状态:
pending
→ creating_challenge
→ waiting_dns
→ validating
→ finalizing
→ issued
→ deploying
→ active
异常状态还应记录错误类型、重试次数、下次重试时间和最后一次 Worker。这样服务重启后可以恢复任务,而不是创建重复订单。
需要特别处理:
- CA Rate Limit 和 Retry-After;
- Worker 抢占与租约超时;
- 重复回调的幂等性;
- CAA 不允许目标 CA;
- DNS TXT 已存在但记录 ID 丢失;
- 签发完成后部署失败。
六、TXT 清理应该延迟执行
CA 返回验证成功后,不建议立刻删除 TXT。部分 CA 或中间流程可能再次查询挑战值,立即清理会制造偶发失败。
可以将清理任务单独入队:
cleanup_at = validation_success_at + cleanup_delay
清理失败不应让已经签发的证书失效,但必须进入告警或补偿队列,防止挑战记录长期堆积。
七、签发后还需要三层验收
“证书签出来了”只是第一层成功。完整验收应分为:
如果只看到 Agent 返回“文件写入成功”,不能宣称网站已经使用新证书。Nginx 未重载、CDN 未绑定或负载均衡仍引用旧证书时,公网仍会返回旧证书。
八、私钥与部署权限边界
证书自动化系统通常有两种私钥模式:
- 平台托管:平台生成私钥并加密保存,再向部署目标分发;
- 服务器本地生成:Agent 在目标服务器生成私钥,平台只协调订单和证书链。
如果安全要求是“私钥不离开服务器”,就必须采用本地生成模式,并确保 Agent 接口不能执行任意命令。证书替换使用同目录临时文件加原子 rename,私钥权限建议设为 0600。
九、一个可复用的落地清单
- 验证域名与业务 DNS 区域分离;
- DNS Provider 凭据遵循最小权限;
- AddTXT/DeleteTXT 不覆盖其他值;
- 权威 DNS 和递归 DNS 双重传播检查;
- ACME Order 支持幂等、锁、重试和恢复;
- TXT 延迟清理;
- 签发、部署、公网三层验收;
- 证书临期、签发失败和部署失败分别告警。
十、三类实现方式怎么选
同一套 DNS-01 与 ACME 思路,可以通过不同方式落地:
| Certbot | 单机或少量服务器 | 生态成熟,适合直接对接 Let's Encrypt 官方文档 |
| acme.sh | 脚本化和自托管 | Shell 实现,DNS Provider 丰富,可查看 acme.sh 开源项目 |
| 平台化管理 | 多域名、多服务器和云资源 | 集中管理订单、部署和告警;我当前用于验证 CNAME 委托与 Agent 链路的实例是 CertbotX |
选择工具时,不要只比较“能不能签发”,还应检查权限边界、失败恢复、部署目标、审计记录和公网验收能力。无论使用哪种方式,都建议先用测试域名跑通一次完整链路。
总结
DNS-01 CNAME 委托的价值,不只是少改几次 TXT,而是把业务 DNS 权限与证书验证权限解耦。配合可恢复的 ACME 状态机、延迟清理和三层验收,才能形成真正可长期运行的证书自动续期系统。
本文仅讨论 DNS-01、ACME 与证书部署的工程选型,不构成商业推荐。
网硕互联帮助中心



评论前必须登录!
注册