OpenSSL报certificate chain too long:error 22与verify_depth深度排查

证书没过期,根也配对了,OpenSSL却报certificate chain too long。别急着从fullchain里删一张证书:可能不是文件太大,而是验证端允许的中间CA层数不够。本文用隔离证书链复现error 22,说明verify_depth怎样计数,以及它和CA证书里的pathlen为什么不能互相代替。

一、先看报错来自哪一个验证端

这里讨论openssl verify离线验证。若错误来自网关或双向TLS,先确认是谁验证谁:服务端验证客户端,与客户端验证服务端,是独立路径。调错一侧,日志当然不会变。

本轮环境为OpenSSL 1.1.1k FIPS、RSA 2048位和SHA-256,临时生成Root→CA-A→CA-B→leaf;CA主体各异,无交叉签名或自颁发中间证书。未改生产服务、系统信任库。其他版本需重新验证。

二、verify_depth数的是中间CA,不是PEM块

OpenSSL官方文档将-verify_depth定义为允许的中间CA数量上限;叶证书和信任锚不计入。上面的路径有四张证书,但中间CA只有两张,所以深度预算需要覆盖两层,而不是把参数写成4才安心。

错误信息里的depth又是另一回事:它描述出错证书在检查链中的位置,通常叶子为0、直接签发者为1。不要把error 22中的22、日志depth和命令退出码混成一个数字,它们分别是错误编号、位置和进程结果。

BEGIN CERTIFICATE数量不等于验证路径层数。重复材料、备用链或额外根会改变文件数量,却不一定增加中间层;成功时结合-show_chain看实际路径。

三、准备可信根和中间材料,再复现限制

在独立工作目录保留原件。leaf.pem是目标叶证书;root.pem只放经过授权确认的信任锚;intermediates.pem放CA-B与CA-A的PEM证书。ca-a.pem、ca-b.pem为分别导出的单张副本。不要把私钥放进这些包,更不要直接把对端送来的根当成可信根。

bash 复制代码
openssl version -a
openssl x509 -in leaf.pem -noout -subject -issuer
openssl x509 -in ca-a.pem -noout -text
openssl x509 -in ca-b.pem -noout -text

本例用-trusted显式提供可信材料,不额外加载默认CAfile、CApath;3.0文档还包括CAstore。这些来源选项不能混用。-untrusted只提供构链材料,不会自动获得信任。核对subject、issuer、CA用途及扩展后,运行预算为1的负例:

bash 复制代码
openssl verify -trusted root.pem -untrusted intermediates.pem \
  -purpose sslserver -verify_hostname app.example.test \
  -verify_depth 1 -show_chain leaf.pem

本轮得到error 22 at 2 depth lookup: certificate chain too long,退出2,位置对应CA-A;其他路径不一定是depth 2。保留完整输出,不只截最后一行。

四、经策略确认后调整预算,再看完整路径

如果组织允许两层中间CA,且这条链的来源、用途和约束都正确,可以在隔离验证里将预算调整为2。数字来自实际PKI设计,不是遇错就一路加到99。

bash 复制代码
openssl verify -trusted root.pem -untrusted intermediates.pem \
  -purpose sslserver -verify_hostname app.example.test \
  -verify_depth 2 -show_chain leaf.pem

本轮返回leaf.pem: OK,退出0;-show_chain列出leaf、CA-B、CA-A、Root。对照中,Root直接签发叶证书时,-verify_depth 0也可通过;只有一层中间CA的链,0失败、1通过。这说明叶子和根确实不消耗这里的中间层预算。

通过只说明本次输入、时间和选项下的离线验证成功。服务使用的库、信任配置、部署节点和握手材料可能不同;不能拿本机这一句OK替代真实客户端请求,更不能保证浏览器行为一致。

五、提高深度仍失败,区分error 22与error 25

verify_depth属于验证端策略;pathLenConstraint是CA证书basicConstraints中的签名内容。RFC 5280对后者限制的是该证书之后的非自颁发中间证书数量,最终目标不计入。不要把这条定义简单扩大到所有特殊路径。

本轮另一条链把CA-A签为pathlen:0,却仍让它经CA-B签发叶子。即使将verify_depth设为10,仍得到error 25 at 2 depth lookup: path length constraint exceeded,退出2。验证端给了更多预算,也不能取消CA证书已经签名的约束。

隔离条件 本轮结果 处理方向
两层中间CA,depth预算1 error 22,退出2 核对验证端预算
同一合法链,预算2 OK,退出0 继续真实服务验收
根直签叶,预算0 OK,退出0 根与叶不计入预算
CA-A违反pathlen,预算10 error 25,退出2 修正签发层级与证书
缺中间CA或验证名错误 其他验证错误 不能只调深度

改配置不会改变已签发证书。层级违反约束时应授权重设计或签发,不能手改PEM,也不能临时信任CA-A绕过原路径。

六、自动化保留退出码,别让日志盖住失败

下面的Bash片段仅用于已批准两层中间CA的场景。目录由任务身份独占写入,避免并发覆盖和不可信软链接;日志也应按内部信息处理。先保存verify结果,失败立即返回,不把printf或日志工具的成功当验证成功。

bash 复制代码
umask 077
rc=0
openssl verify -trusted root.pem -untrusted intermediates.pem \
  -purpose sslserver -verify_hostname app.example.test \
  -verify_depth 2 -show_chain leaf.pem >verify.log 2>&1 || rc=$?
[ "$rc" -eq 0 ] || exit "$rc"
printf '%s\n' '离线链检查通过,仍需实际服务验收'

本轮重放了正文四段命令:负例按预期失败,其余通过;包装器另外覆盖错误域名、缺中间CA、pathlen违规和日志路径不可写,均阻断成功消息。这里没有关闭签名、主机名或用途验证,也没有启用部分链来缩短路径。

七、修复后的验收清单

  • 记录实际执行文件、库版本、验证方和目标证书,不照搬另一进程的设置。
  • 可信根来自授权渠道,中间材料与目标叶分开,不能以文件数量代替路径。
  • 成功路径的中间层预算符合政策,CA的pathlen、用途、名称、时间仍分别有效。
  • 保留一个超深负例,确认自动化会失败关闭;输出与日志失败也要测试。
  • 按真实应用配置重新握手并验证业务响应;本文离线实验不冒充上线验收。

八、参考资料与实现入口

相关推荐
不像程序员的程序媛2 小时前
linux常见文本操作命令
linux·运维·服务器
wangbing11252 小时前
开发指南149-IotDB-常用命令
linux·运维·iotdb
看着博客敲代码2 小时前
WorkBuddy 接上 Kali MCP 做自动化渗透:信息收集到初步验证的落地记录
linux·人工智能·安全·网络安全·自动化
小HANN4 小时前
华为云企业网站上云实战|从零搭建高可用WordPress全站架构(ECS+RDS+ELB+弹性伸缩+云监控闭环)
linux·运维·服务器·经验分享
星恒随风4 小时前
Linux库的底层原理:ELF文件格式、静态链接、程序加载、虚拟地址空间与GOT/PLT详解
linux·运维·笔记·学习·状态模式
GeW5 小时前
2026新质生产力路线图:Linux、数据库与智能算力融合报告
linux
AR-26710-5 小时前
Linux Day19——日志轮转
linux·运维
祖力555 小时前
驱动工程搭建与字符设备驱动框架
linux·运维·服务器·内核·arm·imx6ull·驱动
Escalating_xu7 小时前
【Linux 网络编程】网络基础概念(下):IP、端口、Socket 与网络字节序,写代码前先打好基础
linux·网络·tcp/ip