Let's Encrypt 证书申请失败,九成以上集中在三类原因:验证请求根本到不了你的服务器(域名解析不对、80/443 端口不通、CDN 或安全组拦截)、HTTP-01 验证路径 /.well-known/acme-challenge/ 被跳转或 WAF 吃掉、以及短时间反复重试触发了官方的失败验证限流。先跑一次 --dry-run 用测试环境验证,别拿生产环境试错。
Let's Encrypt 申请失败怎么快速定位是哪一环?
结论:申请失败的第一步不是改配置,而是看日志确认挑战类型和报错原文。
Certbot 的完整日志在 /var/log/letsencrypt/letsencrypt.log,加上 -v 参数能打印每次 ACME 请求。常见报错直接对应原因:Timeout during connect 是网络层不通;Invalid response from ... 404 是验证文件没放对位置或路径被改写;JWS verification error 是时间或客户端问题;too many failed authorizations recently 就是触发了限流。
定位顺序建议固定为:dig +short 你的域名 A 和 dig +short 你的域名 AAAA 看解析 → ss -lntp | grep :80 看端口是否被监听 → 本机 curl -I http://你的域名/.well-known/acme-challenge/测试文件 看返回码。这三步能筛掉大部分问题。
另外强烈建议每次改配置后先用测试环境跑:
certbot certonly --webroot -w /var/www/html -d example.com --dry-run
--dry-run 走的是 staging 环境,不消耗生产配额;用 --staging 或 --test-cert 同理。生产环境每小时失败 5 次就会被临时锁,直接拿生产试错是最常见的"自找麻烦"。
域名解析正确、端口也开着,为什么还是连不上?
结论:最常见的原因是域名存在 AAAA 记录,而服务器的 IPv6 没有真正监听 80 端口。
Let's Encrypt 的验证节点会优先走 IPv6。如果你的域名在 DNS 里有一条 AAAA 记录指向了一台没有配置 IPv6 监听、或者防火墙没放行 v6 的机器,验证请求会从 IPv6 发起并超时,而你本地用 IPv4 测试一切正常,非常容易误判。解决办法:删掉多余的 AAAA 记录,或确保 [::]:80 也在监听。
第二类原因是链路中间有设备挡住了 80 端口:云厂商安全组未放行、系统 firewalld/ufw 未放行、CDN 开启了代理(橙色云朵)导致请求打不到源站、国内服务器未备案被运营商封 80。判断方法很直接——用外部工具或手机 4G 网络访问 http://你的域名/,能打开才有资格谈证书。
HTTP-01 验证路径被拦截了怎么办?
结论:ACME 验证请求必须能拿到 200 和纯文本内容,任何 301 跳转、伪静态重写、WAF 挑战页都会导致失败。
检查三处:
- Nginx 的
location 优先级。如果站点里有 location / { try_files ... } 或全局的 rewrite,.well-known 目录可能被重写到首页。加一段显式放行:
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
default_type text/plain;
}
^~ 保证它优先于正则 location。
--webroot -w 的目录必须和 Nginx 里 root 指向的是同一个物理路径。路径写错是最常见的 404 来源。
- 站点有 301 强制跳 HTTPS、有 WAF 或宝塔的"防跨站攻击"限制时,验证文件读不到。临时关掉再申请。
自检命令:curl -I http://你的域名/.well-known/acme-challenge/test,返回 200 才合格;返回 301/403/404 都要先修。
通配符证书为什么一定要用 DNS-01?
结论:*.example.com 这类泛域名只能用 DNS-01 验证,HTTP-01 在原理上无法验证泛域名。
DNS-01 需要在 _acme-challenge.example.com 添加 TXT 记录。失败的典型原因有三个:DNS 服务商 API 密钥权限不对、TTL 太长导致记录传播慢(建议临时设 60 秒)、以及域名上已经存在一条 _acme-challenge 的 CNAME 记录与 TXT 冲突。用 acme.sh 的 DNS 模式时,先手动 dig TXT _acme-challenge.example.com 确认记录真的生效,再用 --dnssleep 120 延长等待。
触发速率限制后要等多久才能重试?
结论:Let's Encrypt 官方限制是每注册域名每周 50 张证书、同一组域名每周 5 张重复证书、每个账号对每个主机名每小时失败验证 5 次。
失败验证的限流按小时窗口滚动恢复,等 1 小时即可;重复证书超限要等 7 天。这也是为什么必须先用 --dry-run 调试。另外单账号每 3 小时最多 300 个新订单,批量签发时也要留意。
还有哪些容易被忽略的原因?
结论:系统时间偏差、客户端版本过旧、申请了不该申请的域名,都会报出看起来毫不相关的错误。
系统时间偏差超过几分钟会导致 JWS 签名校验失败,先跑 date -u 和 ntpdate 对时。客户端要用支持 ACME v2 的版本,ACME v1 早已下线,老的 --server 地址会直接报错,服务地址应为 https://acme-v02.api.letsencrypt.org/directory。域名方面,Let's Encrypt 不签发公共后缀、内网单标签域名(如 server.local),这类域名再试多少次都不会成功。
排查思路固定成一句话:先 dry-run、再看日志、然后查解析、端口、验证路径、限流四件事,按顺序走,基本不用瞎猜。真遇到日志看不懂的情况,可以把报错贴到 GJ 站长论坛的问答版块,附上 certbot --version 和完整日志,比只发一句"证书申请失败"能快得多拿到答案。