certbot 一回车,屏幕上跳出 Failed authorization procedure 或 Timeout during connect,重试十几次还是失败。很多人开始怀疑人生:域名是我的、服务器是我的,为什么就是不给我发证书?其实证书机构(CA)根本不认识你,它只认一件事:你能不能证明自己控制这个域名。这个证明过程叫“挑战(challenge)”,选错挑战类型,后面全是无用功。本文先讲清两种挑战,再给排查清单。
先理解:申请证书 = 完成一次域名控制权验证
以 Let’s Encrypt 为例,ACME 协议定义了几种挑战,最常用的是两种:
- HTTP-01:CA 访问
http://你的域名/.well-known/acme-challenge/<token>,能读到正确内容即通过; - DNS-01:CA 查询
_acme-challenge.你的域名的 TXT 记录,对得上即通过。
记住这个模型,排查就有了方向:HTTP-01 失败去查 80 端口和网站路径;DNS-01 失败去查 TXT 记录和 DNS 权限。不要再无脑重试,先判断你走的是哪条路。
HTTP-01:先保证公网 80 端口是通的
HTTP-01 固定走 80 端口,这是协议规定的,改不成别的高位端口。用 webroot 模式申请最透明:
certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com
失败时逐项检查,而不是凭感觉重装:
- 域名指向对了吗?
dig +short example.com对一下 IP,是不是这台服务器; - 80 端口通吗?云安全组 / 防火墙放行 80 了吗?面板能打开不代表 80 通。用手机流量试
curl -v http://example.com/.well-known/acme-challenge/test; - 反向代理转错了吗?检查有没有把
/.well-known/转到别处,或挡在登录验证后面; - CDN 干扰?开了强制 HTTPS 或防护拦截,CA 的 HTTP 请求可能被转走或挡掉,申请期间可临时调成 DNS 验证或放行该路径。
如果是标准的 Nginx / Apache 站点,用插件模式更省事,它会自动改配置完成验证:
certbot --nginx -d example.com -d www.example.com
还有一个自查技巧:申请前先手工验证挑战路径是通的。在网站根目录下建一个测试文件 .well-known/acme-challenge/test.txt,然后用手机流量访问 http://你的域名/.well-known/acme-challenge/test.txt,能看到内容,说明 HTTP-01 的整条路是通的,certbot 失败就只可能是别的原因(比如域名指向了别的机器)。这个两分钟的测试能排除一大半“玄学失败”。
DNS-01:通配符证书的唯一选择
要签 *.example.com 这种通配符证书,只能用 DNS-01(HTTP-01 签不了通配符,这是硬性规定)。以 Cloudflare DNS 插件为例:
certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \ -d example.com -d '*.example.com'
注意两点:① 自动续期要求 certbot 能自己改 DNS,所以要配一个权限受限的 API 令牌(只给修改 DNS 的权限),别用全局 API Key,令牌文件权限设为 600;② 手工去 DNS 控制台加 TXT 记录也能签下一次,但续期还要手工再来一遍——“首次签发成功”不等于“维护完成”,生产环境一定要走自动化。
签发之后:验证整条访问链路
拿到证书只是开始,装完要验:
# 看证书覆盖的主机名和有效期 echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \ | openssl x509 -noout -subject -dates # 演练一次续期,确认链路没问题 certbot renew --dry-run
- 证书的 SAN(使用者备用名称)里必须包含你实际用的每个主机名,根域名和 www 都要;
- 检查 80 → 443 跳转是否正常,页面有没有混入 http 的图片或脚本(混合内容会导致浏览器告警);
- CDN 回源到源站的那一段如果也是 HTTPS,别为了省事长期关掉证书校验,那是在掩盖问题。
把续期当成日常维护
certbot 通常会装好 systemd timer 或 cron 自动续期,但“装了”不等于“能用”:定期跑一次 certbot renew --dry-run,确认失败时通知能发到你手上。验证失败先读日志(/var/log/letsencrypt/),再查 DNS、端口和挑战内容。证书有效期、频率限制以官方当前文档为准,不要照抄几年前的教程——这方面的规则是会变的。
建议把证书纳入你的服务器巡检清单,和系统更新、磁盘用量放在同一张表里:每季度看一次各域名的到期时间,确认自动续期 timer 处于 active 状态(systemctl list-timers | grep certbot)。很多“突然全站 HTTPS 报错”的事故,回头看都是续期在几个月前就悄悄失败了,只是没人看日志。
常见坑
把网站换到 8443 就以为能绕过 80 端口。HTTP-01 只认 80,这是协议写死的,换端口没用。
只给 www 申请,根域名裸奔。两个主机名都要出现在 -d 参数里,否则根域名访问会报证书错误。
手工加 TXT 记录签通配符,然后忘了续期。DNS-01 的手工模式没有自动续期,三个月(以当前有效期政策为准)后准时过期。生产环境务必配 API 令牌走自动化。
CDN 开了“始终 HTTPS”,HTTP-01 却失败。CA 的验证请求走的是 HTTP,被强制跳转或拦截就会失败,申请期间先放行 /.well-known/ 路径。
常见问题
HTTP-01 和 DNS-01 到底怎么选?单台服务器、标准网站选 HTTP-01,最简单;要通配符证书、或 80 端口实在打不开(比如内网服务),选 DNS-01。
报错里出现 rateLimited 怎么办?这是触发了签发频率限制,只能等窗口过去再试。先去官方文档确认当前限制,用 --dry-run 或测试环境(staging)把流程跑通再申请正式证书,别拿正式环境反复试错。
证书续期失败了网站会立刻挂吗?不会立刻,但旧证书过期那天会。把 certbot renew --dry-run 加入你的定期检查项,失败通知一定要能收到。
一张证书能覆盖多少个域名?可以把多个 -d 写进一次申请,但每个域名都要单独通过验证,其中一个失败整单失败。域名越多,越要逐个确认解析和验证路径。
内网服务没有公网 80 端口,能申请证书吗?能,用 DNS-01。只要你能改域名的 DNS 记录,就可以签发证书装到内网服务上。这是 DNS-01 除了通配符之外的另一个典型用途。
参考资料
资料核查:2026年10月8日。本文根据公开官方资料独立整理撰写;封面为 AI 生成的概念插画,不是产品实拍。



