用 DNS-01 CNAME 委托为内网域名签发 Let's Encrypt 通配符证书
内网域名无法做 HTTP-01 验证时,可以把 _acme-challenge 记录 CNAME 到专用验证域完成 DNS-01 签发。本文给出前置条件、委托配置、签发与自动续期步骤,以及如何验证证书链和续期是否生效。
本文目录

适用场景
内网服务的域名不对外开放 80/443 端口,HTTP-01 和 TLS-ALPN-01 都走不通,只剩 DNS-01 一条路。问题是你通常不想把整个主域的 DNS API 凭证交给每台需要证书的机器——凭证权限太大,泄露风险高。
解决办法是 CNAME 委托:在主域里为 _acme-challenge.example.com 建一条 CNAME,指向一个专门用于验证的子域(比如 _acme-challenge.example.com.acme-dns.example.net),ACME 客户端只需要对这个验证子域有写权限。Let's Encrypt 验证时会沿着 CNAME 找到目标 TXT 记录,主域的 DNS 凭证完全不参与签发。
前置条件
- 一个你能控制 DNS 的域名,且其 DNS 服务商支持 API 动态更新 TXT 记录,或你有一台可自行搭建 acme-dns 服务的主机。
- 签发机器能访问 Let's Encrypt 的 ACME 接口(
https://acme-v02.api.letsencrypt.org/directory)。 - 通配符证书(
*.example.com)只能通过 DNS-01 签发,这是 CA 侧的限制,不是客户端的限制。
步骤一:配置 CNAME 委托
在主域的 DNS 控制台添加:
_acme-challenge.example.com. CNAME example-com.acme-dns.example.net.如果还要签发 *.example.com,注意通配符和裸域共用同一个 _acme-challenge.example.com 名称,但两次验证需要同时存在两个不同值的 TXT 记录——验证子域必须支持同名多条 TXT。acme-dns 和大多数 DNS 服务商都支持,自建 BIND 也没问题,但要确认你的更新脚本不是"覆盖"而是"追加再清理"。
用 dig 确认委托生效:
dig CNAME _acme-challenge.example.com +short步骤二:执行 DNS-01 签发

以委托方式签发时,ACME 客户端操作的是 CNAME 目标域的 TXT 记录。不同客户端的配置方式不同,核心参数是一致的:指定 DNS 插件或 hook、验证域的 API 凭证、要签发的域名列表。以泛化流程描述:
- 客户端向 ACME 服务器下单,拿到 DNS-01 challenge 的 token。
- 客户端通过验证子域的 API 写入 TXT 记录,等待 DNS 传播。
- 通知 ACME 服务器开始验证,验证通过后下载证书。
传播等待时间不要乱猜。先查验证子域 NS 的 TTL 和实际解析情况,用 dig TXT <目标记录> @<权威NS> 确认记录已出现在权威服务器上,再触发验证,否则容易触发 Let's Encrypt 的失败速率限制。
步骤三:部署与续期
证书签发后部署到目标服务(Nginx、CDN、负载均衡等),并配置自动续期。DNS-01 续期和首次签发走完全一样的流程,所以续期脚本必须保留同样的凭证和 hook,不能只在首次手工执行一次就完事。
在 CertbotX 中实践
这类委托流程在 CertbotX 里可以直接配置:把主域的 _acme-challenge CNAME 委托交给 CertbotX 管理的验证域后,由它完成 ACME 自动签发和到期前重新签发,签好的证书可自动部署到 Agent、EdgeOne 或其他 CDN 目标,每次签发和部署都会留下部署记录,方便排查"证书到底换没换上去"这类问题。
验证
签发完成后做三件事:
- 查证书内容:
openssl x509 -in fullchain.pem -noout -text,确认 SAN 里包含*.example.com和example.com,有效期是新的。 - 从外部探测握手:
openssl s_client -connect your-host:443 -servername your-host,看返回的证书链是否完整、是否就是刚签的那张。内网服务可以在同网段的机器上执行。 - 演习一次续期:多数 ACME 客户端支持 dry-run,确认续期路径(包括 DNS hook)能跑通,而不是等 60 天后由监控告警告诉你续期挂了。
如果 dry-run 失败,先查 CNAME 是否还在、验证子域的 API 凭证是否过期,这两处是委托方案最常见的断点。