☰
Caddy 中间证书过期排查:3 个检查点定位,两条路径一次搞定
2026/10/3 2:22:31 网站建设 项目流程

Caddy 中间证书过期排查:3 个检查点定位,两条路径一次搞定

【免费下载链接】caddyFast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS项目地址: https://gitcode.com/GitHub_Trending/ca/caddy

凌晨 2 点,值班群弹出第一条用户反馈:网页打不开,浏览器弹"您的连接不是私密连接"。你第一件事打开控制台敲openssl x509查域名证书,有效期还剩下两个月——证书明明没过期,为什么 HTTPS 全挂了?这种"叶证好好的、连接却报证书错误"的故障,大概率是Caddy 中间证书过期:服务端送出的完整证书链里,垫在中间的那一环失效了。

先别急着改配置。用下面的分诊流程,几分钟就能确认到底是不是中间证书在作妖。

3 个检查点:快速确认是不是 Caddy 中间证书过期

检查点 1:服务端叶证本身是否有效。在服务器上直连自己的站点,确认第一张证书的有效期:

openssl s_client -connect example.com:443 -servername example.com \ -showcerts 2>/dev/null | openssl x509 -noout -issuer -subject -dates

如果叶证(subject 是域名的那张)没过期,别停在这里,继续第二点。

检查点 2:看服务端实际送出了几张证书、中间那张是谁。-showcerts的输出里,Certificate chain:段应至少有两张:索引 0 是叶证,索引 1 是中间证书。把索引 1 单独拿出来看日期,或直接验证整条链:

openssl verify -CAfile 中间证书.pem 叶证书.pem

返回untrusted、certificate has expired或干脆提示拿不到签发者,基本可以锁定:中间证书过期(或链路缺环)。

检查点 3:排除本地干扰。用一台不同运营商网络(或手机热点)的机器复测。都报同样的错,说明问题在服务器送出的链路上,而不是某台客户端的根证书库太旧。

三步走完,结论无非两种:叶证本身到期(那就是常规续期问题),或者中间证书失效(本文主角)。Caddy 证书链 排查的关键就在第 2 步——多数人会漏掉"服务端到底送了几张证书"这个细节。

为什么好好的证书链会突然断:担保链与 CA 轮换

打个比方。你去找一个陌生供应商签单,他递来一份介绍信:供应商本人(服务器证书)由区域公司(中间证书)担保,区域公司再由集团总部(根证书)担保。浏览器不直接认供应商,它沿着这条担保链一路验到内置的总部名单。

这条链上任何一环失效,整个信任就断了。而CA 会定期轮换中间证书——Let's Encrypt 的中间证书(E5、E6、R10、R11……)每隔几年换代一次,旧的到点即废。如果你的服务器用的是手工配置的固定证书链文件,叶证每 90 天自动续期续得再勤,链文件里那张老中间证书照样会到期。这就是"证书没过期、HTTPS 却挂了"的根源。

Caddy 证书链 排查时,这个认知能帮你直接排除"叶证没问题就是没事"的错觉:链上最短的那块板决定水位。

两条修复路径:先止血,再断根

临时方案:手动补齐证书链(止血)

从 CA 官网下载当前有效的中间证书,把它拼到叶证后面,组成完整链文件,再让 Caddy 的tls指令指向它:

example.com { tls /etc/certs/example-chain.pem /etc/certs/example.key }

改完用caddy reload --config Caddyfile热加载,再跑一遍检查点 2 确认链完整。注意这只是止血:叶证到期会再触发同样的问题,而你的链文件下次换中间证书时还得手动改一遍。

长期方案:让 Caddy 自动维护证书链(断根)

只要不写auto_https off,Caddy 默认会对域名启用自动 HTTPS:证书签发、续期、连同中间证书在内的整条链,都由它对接 ACME 协议自动拉取和维护。CA 轮换中间证书时,下次续期拿到的自然就是新链。你只需要确认两点:

{ storage file_system /var/lib/caddy # 固定存储,避免证书随容器重建丢失 renewal_window_ratio 0.5 # 提前约一半有效期就续 }

相关逻辑集中在 modules/caddytls/,配置解析在 caddyconfig/httpcaddyfile/tlsapp.go。把renewal_window_ratio调小一点(如0.5),相当于把续期动作往前挪,给"续期失败再来一次"留出缓冲窗口。

把故障挡在门外:日志 + metrics 双保险

📋 治完一次,就该防下一次。展开两个手段就够:

  • 日志:Caddy 的 TLS 事件(签发、续期、失败)都会进日志。全局设log { level info },然后对关键词续期失败(renewal 相关报错)做日志采集告警。链问题往往在续期那一刻就埋下伏笔,而不是故障当天。
  • metrics:全局开启metrics后,Prometheus 端点里带有 TLS 证书到期时间戳。配一条规则:到期时间 - now() < 30 天就告警,中间证书这类"隐藏环"过期前 30 天就能被抓到。

两个手段选一个落地即可;有 Prometheus 的就走 metrics,没有的就把日志接进告警管道。预警的本质是让告警比用户反馈先 30 天到达。

✅ 证书链健康自查清单

  • 最近一次用openssl s_client -showcerts核过服务端实际送出的证书张数(≥2)?
  • 链中每张证书的notAfter都确认过,而不只是叶证?
  • Caddy 的证书存储路径固定且已备份(storage配置),重建机器不会丢链?
  • 手动维护的证书域,知道对应 CA 的中间证书轮换公告在哪看?
  • 自动 HTTPS 域未误开auto_https off/disable_certs?
  • 续期日志里有失败记录吗?(翻最近一次续期的日志段)
  • metrics 或日志告警已覆盖"证书 30 天内到期"这一事件?

勾完这 7 项,下次凌晨 2 点的证书告警,大概率轮不到你。

【免费下载链接】caddyFast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS项目地址: https://gitcode.com/GitHub_Trending/ca/caddy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询