云计算百科
云计算领域专业知识百科平台

OpenSSL报self-signed certificate in certificate chain:error 19与信任根排查

服务器明明把根证书也发出来了,OpenSSL却报self-signed certificate in certificate chain,curl仍然不信任。这里容易把“链里有根”与“客户端信任根”混成一件事。本文用临时私有CA和回环HTTPS对照,定位error 19,并解释为什么删掉服务端根证书后,错误文字变了,问题却没修好。

一、error 19不是说叶证书一定自签

OpenSSL把这个错误标为X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:利用不受信任的证书材料可以构建到根,但本地没有找到可信的根。这里的“不受信任材料”是构链输入的角色,不是已经判定每张证书伪造。

叶证书完全可以由中间CA签发。链条走到了自签根,仍缺少客户端认可它的信任依据。对端递来的“身份证明册”里有盖章的人,不代表这个盖章人自动进入你的信任名单。

同时保留完整错误和depth。本文三层链中叶子为depth 0,中间CA为1,根为2;19是X.509验证错误号,不是Shell进程退出码,也不是curl错误码。

OpenSSL error19:收到自签根不等于信任根,分开检查构链材料与本地信任

二、先确认哪个客户端、哪套信任库

浏览器正常而脚本报错,不足以证明服务端没问题,也不足以证明证书被吊销。两者可能走不同代理、不同入口,或使用不同信任库。先记录实际客户端版本与TLS后端,再确认URL、目标节点及运行账户。

openssl version
curl –version

本文实测命令行是OpenSSL 1.1.1k FIPS、curl 7.61.1的OpenSSL后端。这是复现实验环境,不是推荐部署的版本基线。生产应使用受支持的版本,并按实际后端查信任配置;不能把Linux文件路径原样套到所有系统。

若只有某个容器、服务账户或定时任务失败,应在它实际运行的环境读取CA配置,而不是以管理员终端成功作结论。诊断日志可能含请求头或内部域名,对外分享前脱敏。

三、分清发来的链与受信任的根

s_client的-showcerts展示的是服务器发来的证书列表,不是一条已经验证通过的链。不要把抓到的全部PEM直接放进受信任CA文件;对端不能通过多发一张证书,就替客户端决定该信谁。

私有PKI场景应从获授权的管理渠道取得根证书,独立核对指纹、用途与适用范围,再向需要它的客户端分发。下面只读取本地文件,不修改系统信任库;subject与issuer相同也不能单独证明其可信。

openssl x509 -in root.pem -noout \\
-subject -issuer -dates -fingerprint -sha256

指纹应与独立可信渠道提供的值比较,不是把同一份网络下载文件算两遍。文件名root.pem不带任何信用,下载成功更不是授权决定。公开网站则应核查是否部署了适合目标客户端的证书链,避免让普通访客安装来路不明的根。

四、把两种角色写进验证命令

以下假定已准备好leaf.pem、intermediate.pem和经授权确认的root.pem,叶证书SAN包含localhost。它们分别是待验证叶子、辅助构链的中间CA和信任锚;示例不是从未知服务抓证书后自动授信的脚本。

openssl verify -trusted root.pem \\
-untrusted intermediate.pem -purpose sslserver \\
-verify_hostname localhost -show_chain leaf.pem

在本文OpenSSL版本中,-trusted只使用指定信任锚,不再读取默认CA列表,且不能与-CAfile或-CApath混用。-untrusted补充构链材料,并不会因为放了根就让它受信任。命令还显式检查服务端用途与主机名,-show_chain用于观察实际构建路径。

需要的是“来源可信、角色正确、验证通过”三件事。离线OK不代表线上发链已经更新,下一步还必须连真实TLS终止点验收。

五、隔离实验:为什么删根只会换报错

本轮生成Root→Intermediate→localhost三层临时链,另建不相关的Other根作信任负例。所有离线验证使用明确的-trusted文件;另在127.0.0.1随机端口运行HTTPS服务,分别发送带根和不带根的链。未更改系统时间、系统信任或生产服务,结束销毁临时证书与私钥。

信任锚与构链材料verify实测结果含义
信Other;中间+根放untrusted 19,depth 2 根出现但未获信任
信Other;仅提供中间 20,depth 1 找不到可用的上级
信Root;提供中间 退出0,OK 路径到可信根
信Root;缺少中间 20,depth 0 构链材料仍不足
信Root;提供中间但验证错名 62,depth 0 信任不替代名称匹配

表中的失败案例进程均退出2,而不是退出19、20或62。HTTPS对照中,curl信Other时,带根返回60并报告self signed certificate in certificate chain;去掉根仍是60,只是变为unable to get local issuer certificate。两次均未进入HTTP处理。

改用正确Root后,两种发链方式都得到HTTP 200。这个结果不是鼓励生产发送根,而是证明删除根本身不能修复缺失的信任。实验只代表本机工具与夹具,不推断所有浏览器的构链策略。

六、修复后用真实请求验收

下面在Bash中执行,针对已准备的回环服务;8443替换为实际测试端口,root.pem为已确认的测试根。-q须放在首个选项以忽略默认curlrc,–noproxy仅用于本地实验,不是绕过生产网络策略的建议。

umask 077
rc=0
curl -q –noproxy '*' –cacert root.pem \\
–connect-timeout 3 –max-time 8 \\
–fail –silent –show-error –output body.txt \\
–write-out '%{http_code}' https://localhost:8443/ \\
> probe.status 2> probe.err || rc=$?
[ "$rc" -eq 0 ] || exit "$rc"
[ "$(<probe.status)" = 200 ] || exit 1

保留证书验证,不使用-k。包装器同时检查curl退出码和测试接口约定的200;HTTP错误、输出文件写失败、错误日志路径不可写都不能当成功。000表示未取得HTTP状态,不是服务端返回“000”。真实业务还需按接口契约验响应内容。

七、交付前最后一遍清单

  • 明确失败账户、运行环境、TLS后端与实际终止点。
  • 保留原始错误、depth、退出码和当时的证书指纹。
  • 信任根来自独立授权渠道,辅助链不自动变为信任锚。
  • 离线用途与名称检查通过,再做HTTPS和业务验证。
  • 覆盖受影响客户端及节点,不拿一次成功代表全网。

遇到19,优先问“这个根为什么应该被我信任”,而不是“怎样把错误提示去掉”。证书链材料、信任策略和业务响应分开交付,修复才不会只停在一行OK。

八、参考资料

  • OpenSSL verify:错误与信任参数
  • OpenSSL s_client:showcerts边界
  • curl:证书验证与CA来源
  • curl命令手册
赞(0)
未经允许不得转载:网硕互联帮助中心 » OpenSSL报self-signed certificate in certificate chain:error 19与信任根排查
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!