证书签发和续期
DNS problem: SERVFAIL looking up CAA:Certbot 报错怎么解决
DNS problem: SERVFAIL looking up CAA for example.com - the domain's nameservers may be malfunctioning“DNS problem: SERVFAIL looking up CAA” 的意思是:Let's Encrypt 查询你域名的 CAA 记录时没有得到答案,于是拒绝签发。 签发证书之前,CA 必须检查 CAA 记录是否允许它签发。Let's Encrypt 的解析器去查 CAA,拿到的是 SERVFAIL(DNS 服务器故障),而不是记录列表或“没有记录”的空应答。Let's Encrypt 文档说,这最常见的原因是 DNSSEC 验证失败;其次是权威 DNS 处理不了 CAA 查询。
报错原文和几种变体
这段报错由 Let's Encrypt 生成,各客户端只是转述,核心都是“SERVFAIL looking up CAA”。Certbot 会原样打印 CA 返回的错误:
Detail: While processing CAA for example.com: DNS problem: SERVFAIL looking up CAA for
example.com - the domain's nameservers may be malfunctioning
“for”后面的名字可能是上级域名(申请 www.example.com 时 CA 也会查 example.com),也可能是 CNAME 的目标。如果解析器返回了扩展 DNS 错误码,Let's Encrypt 的提示会变成另一种写法,比如 DNS problem: looking up CAA for example.com: DNSSEC: Bogus,直接指向 DNSSEC。解析器内部的一些故障会显示为 DNS problem: server failure at resolver looking up CAA for example.com。这段文字由 Let's Encrypt 服务器生成,Certbot、acme.sh、win-acme 等客户端只是转述,所以用哪个客户端看到的都一样。
CAA 是怎么查的
RFC 8659 规定,查找 CAA 记录集时从申请的域名开始沿 DNS 名称树“往上爬”,直到找到为止(不包括根)。申请 shop.www.example.com 时,CA 依次查询 shop.www.example.com、www.example.com、example.com。Let's Encrypt 文档还说明,CAA 检查和其他 DNS 查询一样会跟随 CNAME。这条路径上任何一处返回 SERVFAIL,签发都会停下。
另外,如果域名是 7 小时之前验证的,Let's Encrypt 会在最终签发时重新检查一次 CAA,所以已缓存的验证结果也挡不住这个错误。
常见原因(按出现频率排序)
CAA 查询返回 SERVFAIL,最常见的原因是 DNSSEC 配置坏了,其次是权威 DNS 拒绝 CAA 类型的查询。
1. DNSSEC 配置坏了
最典型的场景:把域名的 DNS 从注册商默认解析迁到 DNSPod、阿里云云解析或 Cloudflare 后,注册商那里还留着旧的 DS 记录,和新服务商的密钥对不上;其他情况还有签名过期、签名程序在空应答上出错。RFC 8659 提到,至少有两款实时签名的权威 DNS 软件在返回签名的空 CAA 应答时有缺陷。检查方法:
dig CAA example.com +dnssec @1.1.1.1
dig CAA example.com +cd @1.1.1.1
不加 +cd 返回 SERVFAIL、加了 +cd(关闭验证)能拿到结果,就是 DNSSEC 验证失败。1.1.1.1 访问不了的,换成你能用的其他做 DNSSEC 验证的公共 DNS。Let's Encrypt 建议第一步用 DNSViz 把整条信任链画出来看。
2. 权威 DNS 拒绝 CAA 查询
有些权威 DNS 遇到不认识的记录类型会回 NOTIMP 或 REFUSED。Let's Encrypt 指出这违反了 RFC 1035,正确的做法是返回 NOERROR 和空应答。直接问每一台权威 DNS:
dig NS example.com +short
dig CAA example.com @ns1.example-dns.net +norecurse
3. 防火墙或防 DDoS 设备丢弃查询
RFC 8659 描述了这种中间设备:它们会丢弃未知类型的 DNS 包,尤其是在认为自己正遭受攻击的时候。结果表现为超时或 SERVFAIL,而且常常时好时坏。
4. 子域委派到了内网或失效的 DNS
某个子域的 NS 记录指向内网 IP,或者指向已经不再托管这个区域的服务器(失效委派)。RFC 8659 说明 CA 在这种情况下会收到 SERVFAIL。用 dig NS sub.example.com 看委派,再逐台查询。
5. CNAME 目标的 DNS 有问题
www.example.com 用 CNAME 指向某个 CDN 或 SaaS 的域名,而对方的权威 DNS 处理不好 CAA 查询。这要由对方修复,或者你把 CNAME 改掉。
6. 临时故障
权威 DNS 宕机或过载。稍后重试,看看 DNS 服务商有没有故障公告。
怎么修
修法按原因区分:DNSSEC 问题在注册商处修 DS 记录,其他问题要让对应的 DNS 服务器正常回答 CAA 查询。
- DNSSEC: 到注册商那里把 DS 记录改成和当前 DNSKEY 匹配;如果区域已经不再签名,就把 DS 删掉。等旧 DS 记录的 TTL 过期再重试。
- NOTIMP 或 REFUSED: 让 DNS 服务商修复 CAA 查询的处理,或者把域名迁到正确支持 CAA 的服务商。
- 委派问题: 删除或修正指向内网、已下线服务器的 NS 记录。
- CNAME 目标: 反馈给对应服务商,或者把这个名字指向别处。
- 临时故障: 间隔一段时间再试,避免连续失败触发 频率限制。
查询恢复正常之后,用 CAA 检测 看看现有策略允许哪些 CA,用 CAA 记录生成器 生成记录。原理见 CAA 记录详解。用 acme.sh 的话,其他验证类报错可以看 acme.sh 验证报错。
迁移 DNS 服务商时怎么避免 SERVFAIL
DNSSEC 导致的 SERVFAIL 大多出在“换 DNS”这一步。稳妥的顺序是先删 DS、再改 NS、最后重新开启 DNSSEC:
- 迁移前,如果旧服务商开着 DNSSEC,先到注册商那里删除 DS 记录,等原 DS 记录的 TTL 过去(通常一两天)。
- 迁移时,在新服务商把所有记录配好,再到注册商修改 NS。
- 迁移后,确认解析稳定了,再在新服务商开启 DNSSEC,把新服务商给出的 DS 记录填回注册商。
反过来做,或者干脆忘了删旧的 DS,在一段时间内所有做 DNSSEC 验证的解析器都会对你的域名返回 SERVFAIL。网站访问可能因为部分用户的解析器不做验证而“看起来正常”,但 Let's Encrypt 一定会查出来。不确定域名有没有开 DNSSEC,用 dig DS example.com +short 查一下,有输出就说明注册商那里登记了 DS。
怎么确认已经修好
申请的域名、各级上级域名和 CNAME 目标的 CAA 查询都返回 NOERROR,--dry-run 也能走通,问题就解决了。
- 对申请的域名、每一级上级域名和 CNAME 目标,
dig CAA example.com @1.1.1.1和dig CAA example.com @8.8.8.8都返回status: NOERROR(有没有记录都行)。 - DNSViz 对这个区域不再显示错误。
sudo certbot renew --dry-run(或certonly --dry-run)在测试环境下能走通。
常见问题
我没设置 CAA 记录,为什么查 CAA 会失败?
Let's Encrypt 照样要查。正常的权威 DNS 会返回 NOERROR 和空应答,意思是没有限制;SERVFAIL 表示这个问题没能得到回答,CA 不能把它当成“没有 CAA”。
加一条 CAA 记录能解决吗?
只有当 DNS 服务器的问题恰好出在“空的 CAA 应答”上时才有用,这种情况不多。DNSSEC 坏了或者服务器拒绝 CAA 类型时,加记录不会有任何变化。先用 dig CAA example.com +dnssec 和 +cd 两条命令对比诊断。
一小时前还能签,现在同一个域名就失败了,为什么?
SERVFAIL 经常是间歇性的:几台权威 DNS 里有一台坏了、DNSSEC 签名过期,或者防 DDoS 设备丢弃了查询。Let's Encrypt 会从多个网络位置查询,坏一台就可能失败。把每台权威 DNS 都直接查一遍。
和“CAA record for example.com prevents issuance”有什么区别?
那个错误说明查询成功了,而且 CAA 记录只授权了别的 CA,见 CAA 记录阻止签发。SERVFAIL 是查询本身失败了。