内网或不开放 80 端口的服务器,该选 HTTP-01 还是 CNAME 委托的 DNS-01?
当服务器不对外开放 80 端口时,HTTP-01 验证无法完成,DNS-01 成为主要选择。本文在“证书签发者无法直接操作主域 DNS”的场景下,比较直接 DNS-01 与 CNAME 委托 DNS-01 的取舍,并给出自动化部署建议。

很多内部服务、API 网关或防火墙后的站点只对外暴露 443,甚至完全不对公网开放。这时想用 Let's Encrypt 这类 ACME CA 签发证书,HTTP-01 验证会走不通——CA 必须能通过 80 端口访问到 /.well-known/acme-challenge/ 下的挑战文件。于是问题变成:DNS-01 怎么做,直接改主域 DNS,还是通过 CNAME 把验证委托出去?
两种方案都能完成签发,差别在运维成本和自动化能力上。

直接在主域上跑 DNS-01。 签发时在主域的 _acme-challenge.example.com 下写 TXT 记录,验证后删除。做法本身没有问题,但它要求 ACME 客户端持有主域 DNS 的 API 凭证。现实里这经常是个障碍:主域 DNS 可能托管在公司统一的账号下,权限审批严格,或者多个团队共用一个 DNS 账号,给出有写权限的密钥意味着证书客户端理论上能改动任何记录。每次续期都要调用一次 DNS API,密钥轮换、权限收敛都成了额外工作。另外,TXT 记录传播有延迟,签发脚本需要等待生效,偶尔会因为 TTL 或权威服务器同步慢而超时。
CNAME 委托的 DNS-01。 在主域加一条静态 CNAME,把 _acme-challenge.example.com 指向一个专门用于验证的子域(比如 _acme-challenge.example.com.acme-dns.internal),ACME 客户端只需要操作那个验证域。委托只需配置一次,之后续期只动验证域的记录,主域 DNS 的凭证完全不需要交给证书机器。攻击面小了很多:即使验证域的密钥泄露,也影响不到主域的 A 记录或 MX 记录。这个方案对团队协作友好——证书运维和 DNS 管理可以是不同的人,各自持有各自域的权限。

取舍主要集中在这几点:
- 场景简单、主域 DNS 本来就在自己手里:直接 DNS-01 更省事,少一层配置,排错也直接。
- 主域不归你管、权限敏感、或要给很多子域反复签证书:CNAME 委托值得搭,一次配置换来长期的自动化和权限隔离。
- 需要泛域名证书:两种方案都可以,HTTP-01 则完全不行——ACME 协议不允许用 HTTP-01 签发通配符证书。
- 服务器根本无公网可达性:只有 DNS-01 这条路,因为 CA 验证的是 DNS 记录,不需要回连你的服务器。

在 CertbotX 中实践:可以直接配置 DNS-01 CNAME 委托,把验证记录写到一个专用的验证域,主域 DNS 凭证无需下发到证书机器;ACME 自动签发后,CertbotX 会在到期前自动重新签发,并支持把新证书自动部署到 Agent、EdgeOne 或 CDN,部署记录可审计,续期失败或部署异常时有据可查。这对需要长期无人值守续期的内网服务比较实用。
验证流程是否符合预期,可以参考 ACME 协议规范本身,以及 Let's Encrypt 对各验证方式的官方说明:

- Let's Encrypt 验证方式文档——说明 HTTP-01 与 DNS-01 的适用条件及通配符证书的限制。
- RFC 8555: ACME 协议规范——challenge 验证流程的权威定义,排错时可对照。
结论很简单:没有 80 端口就用 DNS-01;DNS 权限不在自己手里,或者要管一批证书的续期,就再多走一步做 CNAME 委托。一次性配置的成本,通常会很快在后续的自动续期里省回来。