命令行工具

error 10 at 0 depth lookup: certificate has expired 怎么办

作者: · 最后核实

报错信息error 10 at 0 depth lookup: certificate has expired

错误 10 的意思是:OpenSSL 检查时,证书链里有一张证书已经过期了。 看 depth:depth 0 是服务器自己的证书该续期了;depth 1 及以上是服务器还在发过时的中间证书;如果看起来都没过期,多半是做验证的那台机器时钟不对。

快速修复

先按 depth 找出过期的那张证书:depth 0 续期站点证书,depth 1 及以上更换中间证书。打印服务器发出的每张证书的有效期,以及当前 UTC 时间:

date -u
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
  | awk '/BEGIN CERT/{c++} {print > "cert" c ".pem"}'
for f in cert*.pem; do openssl x509 -in "$f" -noout -subject -enddate 2>/dev/null; done
  • 站点证书过期: 续期并部署,重载 Web 服务器。
  • 中间证书过期: 用 CA 当前的中间证书重新拼接证书链文件。
  • 都没过期: 修正报错那台机器的时钟。

原因

5 种原因里,前 3 种是证书真的过期了,后两种是客户端时钟或测试文件的问题。

1. 服务器证书过期(depth 0)

  • 确认: 第一张证书的 notAfter 已经过去。
  • 修复: 用 ACME 客户端或到 CA 续期,部署新证书和证书链,然后重载。磁盘上已经有新证书、对外却还是旧证书,说明服务器没重载,或者读的是另一个路径。阿里云、腾讯云的免费证书不会自动续期,到期前要重新申请和部署。

2. 证书包里有过期的中间证书(depth ≥ 1)

  • 确认: 站点证书有效,链里另一张证书的 notAfter 更早而且已过期。
  • 修复: 更换 CA 证书包;不同年份的中间证书不要不看日期就混用。SSL 检测工具会标出链中过期的证书。

3. 老版本 OpenSSL 走了过期的交叉签名路径

OpenSSL 1.0.2 及更早版本,即使存在一条经过受信任根证书的有效路径,也可能选择经过过期交叉签名证书的路径。OpenSSL 1.1.0 起默认优先使用受信任证书。

  • 确认: 只有老系统报错(比如 CentOS 6、很老的嵌入式设备),新系统验证同一台服务器正常。
  • 修复: 升级 OpenSSL;服务器端不要再发送过期的交叉签名证书。

4. 客户端时钟错误

  • 确认: date -u 与真实时间相差很多;访问许多无关网站都报错误 10 或 9。
  • 修复: 开启 NTP(timedatectl set-ntp true、chrony),国内可以使用阿里云、腾讯云提供的 NTP 服务器。从快照恢复的虚拟机、没有时钟电池的设备最容易出这个问题。

5. 验证的是旧文件

拿几个月前保存的证书文件来测试,也会报错误 10。

  • 修复: 用 s_client 验证服务器现在发出的证书,而不是本地副本。

各环境修法

避免错误 10 要做到三点:续期自动化、续期后重载、到期前告警。

Certbot / acme.sh: 手动执行 certbot renew --dry-run 或 acme.sh --cron,看输出;确认有重载钩子。

宝塔面板: 在站点 SSL 页面查看证书到期时间和续签日志,确认“自动续签”开启。

Kubernetes: 用 kubectl get secret <名称> -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -enddate 解码 TLS Secret 查看到期时间。

Java 密钥库和硬件设备: 手动导入的证书不会自动续期,用 keytool -list -v 列出,在到期前更换。

监控: 链中任何证书剩余不足 14 天就告警。2026 年 3 月 15 日起公网证书最长有效 200 天,一年至少续期两次,配置方法见自动续期证书。

不要这样做

忽略时间检查、回拨时钟、只续站点证书,都会留下过期的证书。

  • 在真实流量上用 -no_check_time 或类似的应用标志。 你会接受 CA 已经不再负责的证书。
  • 把时钟往回调,让过期证书通过验证。 其他所有依赖时间的功能都会出错。
  • 只续站点证书,证书包还用旧的。 中间证书也要检查,CA 可能已经更换过。

常见问题

怎么检查证书在某个日期是否有效?

用 -attime 加 Unix 时间戳:openssl verify -attime $(date -d 2026-12-01 +%s) -untrusted chain.pem leaf.pem(GNU date)。快速查是否快到期:openssl x509 -checkend 1209600 -noout -in leaf.pem,14 天内到期会返回非零退出码,适合写进监控脚本。

站点证书没过期,depth 1 却报错误 10,为什么?

服务器发出的中间证书过期了,通常是旧证书链文件残留。用 CA 当前的中间证书替换证书包,可以从 CA 官网获取,或用证书链补全工具生成。

能让 OpenSSL 忽略日期吗?

能,但只用于排查。-no_check_time 用于排查归档或测试数据,应用程序里也有类似的标志。不要用在真实连接上:过期证书不再受吊销服务覆盖,私钥泄露了也可能没人发现。

资料来源

  1. OpenSSL openssl-verify
  2. OpenSSL X509_STORE_CTX_get_error (verification error codes)
  3. OpenSSL openssl-verification-options (-attime)
  4. RFC 5280 section 4.1.2.5: Validity