4、OpenSSL工具箱:常用命令速查(s_client, verify, x509)

说实话,排查证书信任链故障,OpenSSL 就是我的瑞士军刀。这三个命令——s_client、verify、x509——我几乎每天都会用到。它们各有侧重,配合起来能解决 90% 的证书问题。

下面这张图是我自己总结的,三个命令分别管什么,以及它们之间的关系。

OpenSSL 三命令核心逻辑图 OpenSSL 三命令核心逻辑 s_client 连接测试 + 抓取证书链 verify 本地信任链校验 x509 证书内容解析 抓取证书链 校验路径 & 信任锚 查看有效期/颁发者/指纹 💡 我的使用习惯 先用 s_client 抓取服务端证书链,再用 x509 逐张解析证书内容, 最后用 verify 做本地校验。三步走,基本能定位 90% 的信任链问题。

4.1 s_client:远程连接与证书抓取

s_client 是我排查远程服务端证书问题的首选工具。它模拟了一个 SSL/TLS 客户端,能直接和服务端握手,并把证书链原样拉下来。

最基本的用法是这样的:

openssl s_client -connect example.com:443 -showcerts

加上 -showcerts 参数后,它会输出完整的证书链。我个人习惯把输出重定向到文件里,方便后续分析:

openssl s_client -connect example.com:443 -showcerts > cert_chain.pem
小技巧: 如果服务端只暴露了 443 端口,但你想测试其他端口(比如 8443),直接改端口号就行。我曾经遇到过客户说“证书没问题”,结果我用 s_client 连上去一看,服务端根本没配中间证书。

有时候你只想看证书链,不想看握手细节。可以加 -servername 参数(用于 SNI 场景),再配合 sed 提取证书部分:

openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p'
注意: 有些老旧服务端不支持 SNI,如果你不指定 -servername,它可能返回默认证书,而不是你想要的域名证书。我曾经踩过这个坑,排查了半天才发现是 SNI 没传对。

4.2 verify:本地信任链校验

verify 命令用来做本地校验。你把证书链文件和根证书准备好,它就能告诉你这条链是否可信。

基本语法:

openssl verify -CAfile <根证书> -untrusted <中间证书> <服务器证书>

举个例子,假设你有三个文件:

  • root.pem —— 根证书
  • intermediate.pem —— 中间证书
  • server.pem —— 服务器证书

校验命令如下:

openssl verify -CAfile root.pem -untrusted intermediate.pem server.pem

如果一切正常,你会看到:

server.pem: OK

如果出错了,它会告诉你具体原因。比如:

  • unable to get local issuer certificate —— 找不到颁发者证书
  • certificate has expired —— 证书过期了
  • self-signed certificate in chain —— 链里出现了自签名证书
核心要点: verify 只做本地校验,它不联网。所以你得确保本地有完整的根证书和中间证书。我经常把根证书和中间证书拼成一个文件,用 -CAfile 一次性加载。

还有一个参数 -CApath,可以指定一个目录,OpenSSL 会去那里找根证书。Linux 系统上通常是 /etc/ssl/certs:

openssl verify -CApath /etc/ssl/certs -untrusted intermediate.pem server.pem
避坑指南: 我曾经遇到过一个问题:本地 verify 显示 OK,但浏览器就是报错。后来发现是中间证书的顺序不对。OpenSSL 的 verify 对证书顺序比较宽容,但有些服务端和客户端很严格。所以,verify 通过不代表线上一定没问题。

4.3 x509:证书内容解析

x509 命令用来查看证书的详细信息。它就像一把手术刀,能把证书的每个字段都剖开给你看。

最常用的参数是 -text,它会输出证书的全部内容:

openssl x509 -in server.pem -text -noout

-noout 表示不输出证书的 base64 编码,只看解析后的文本。输出内容很长,我一般重点关注这几个字段:

字段 说明 常见问题
Subject 证书持有者信息 CN 是否匹配域名?
Issuer 颁发者信息 是否与上一级证书的 Subject 一致?
Not Before / Not After 有效期 是否过期?是否还没生效?
Subject Public Key Info 公钥算法和长度 是否使用了弱算法(如 RSA 1024)?
X509v3 extensions 扩展字段 是否有 Basic Constraints、Key Usage?

只看指纹(fingerprint)也很常用,用来快速比对证书是否一致:

openssl x509 -in server.pem -fingerprint -sha256 -noout

输出类似:

SHA256 Fingerprint=AB:CD:EF:...:12:34
我的习惯: 拿到一张证书后,我第一件事就是看 Issuer 和 Subject。如果 Issuer 和 Subject 一样,那就是自签名证书。如果不一样,再看有效期。很多故障其实都是证书过期引起的,看一眼 Not After 就能排除掉一半问题。

还有一个实用场景:提取公钥或私钥信息。比如查看证书对应的公钥长度:

openssl x509 -in server.pem -pubkey -noout | openssl pkey -pubin -text -noout
注意: x509 只能处理 PEM 格式的证书。如果你拿到的是 DER 格式(二进制),需要先转换:openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM。我遇到过有人直接把 DER 文件扔给 x509,结果报错说“no start line”,其实就是格式不对。

4.4 三个命令的配合使用

说实话,单独用哪个命令都只能看到一面。我通常的排查流程是这样的:

  1. 抓取: 用 s_client 从远程服务端拉下证书链。
  2. 解析: 用 x509 逐张查看证书内容,确认 Subject、Issuer、有效期、扩展字段。
  3. 校验: 用 verify 做本地信任链校验,确认根证书和中间证书是否完整。

举个例子,假设你发现浏览器访问 https://example.com 报错,但不知道原因。你可以这样操作:

# 第一步:抓取证书链
openssl s_client -connect example.com:443 -showcerts 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > chain.pem

# 第二步:查看服务器证书(第一张)
openssl x509 -in chain.pem -text -noout | head -30

# 第三步:查看中间证书(第二张)
# 需要手动拆分 chain.pem 文件,或者用 awk 按 -----BEGIN 分割
# 然后对每张证书分别执行 x509 命令

# 第四步:本地校验(假设你有根证书 root.pem)
openssl verify -CAfile root.pem -untrusted intermediate.pem server.pem
总结一下: s_client 负责“拿”,x509 负责“看”,verify 负责“验”。三个命令配合使用,基本能覆盖证书信任链故障排查的各个环节。我个人习惯把常用参数记在笔记里,遇到问题直接复制粘贴,省得每次都要查 man 手册。