openssl s_client 排障用法
s_client 是一个手工的 TLS 客户端,能把握手过程的每个细节摊开给你看:协商到哪个版本与套件、对端下发了哪些证书、证书链能否验证、OCSP 状态如何。它不依赖浏览器或应用框架,因此是判断「问题在服务端配置还是在调用方」最中立的一把尺子。
基本信息
| 适用平台 | Linux/macOS 自带或 OpenSSL 包;Windows 可用 Git Bash 或 WSL |
|---|---|
| 权限要求 | 普通用户即可,读取系统 CA 目录时需注意权限 |
| 版本差异 | 1.1.1 与 3.x 在套件与选项上有差别(-ciphersuites 只影响 1.3) |
| 权威文档 | man 1 s_client / OpenSSL 官方文档 |
| 结束连接 | 标准输入加 </dev/null 或按 Ctrl-D,否则会挂住等待输入 |
典型使用场景
- 确认某个域名到底协商到 TLS 1.2 还是 1.3、用了哪个套件
- 检查服务端是否下发了完整证书链(缺失中间证书时最常来这里验证)
- 验证证书有效期、SAN 列表与签发者是否与预期一致
- 排查旧客户端握手失败:锁定版本或套件复现问题
- 手工发一条 HTTP 请求,绕过浏览器与代理干扰做对比
常用组合
常用组合
openssl s_client -connect example.com:443 -servername example.com </dev/null # 指定 SNI 的标准写法
openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null | head -80 # 打印整条证书链
openssl s_client -connect example.com:443 -tls1_3 -brief </dev/null # 精简输出,适合脚本判断
openssl s_client -connect example.com:443 -status </dev/null 2>/dev/null | head -20 # 查看 OCSP 装订状态
printf 'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n' | openssl s_client -quiet -connect example.com:443 -servername example.com 2>/dev/null | head输出逐段读法
| 输出段 | 含义 | 异常信号 |
|---|---|---|
| Protocol / Cipher | 最终协商的版本与套件 | 出现 TLSv1/1.1 或 CBC 套件即为配置过老 |
| Certificate chain | 服务端下发的证书序列 | 只有一段且为叶证书,说明缺中间证书 |
| Verify return code | 客户端验证结论 | 非 0 表示链或域名有问题;0 (ok) 才是正常 |
| OCSP response | 装订的吊销状态 | 显示 no response sent 说明未启用装订 |
| Session-ID / TLS session ticket | 会话恢复参数 | 票据持续变化属正常,说明未命中恢复 |
测试多域名站点时必须带 -servername(SNI),否则拿到的可能是默认虚拟主机的证书,很容易得出「证书不匹配」的错误结论。
排错起手式
- 先跑一条不带额外参数的连接,确认基础握手能否成立,把问题范围先框住
- 再逐步加 -servername、-tls1_2 等参数复现具体的失败条件
- 用 -showcerts 数一数链上证书数量,少于两段就直接查中间证书
- 最后与浏览器或应用客户端的报错对照,判断是单侧配置问题还是双方不兼容