这条路径解决什么
证书到期与证书链不全是线上高频事故。做法是用 openssl s_client 对一批域名逐个发起 TLS 握手,再用 openssl x509 解析出主题、签发者与到期时间,配合 -checkend 提前预警。整件事可以写成一个循环,接入巡检或监控脚本定期执行。
基本信息
| 适用场景 | 批量证书到期检查与链完整性验证 |
|---|---|
| 核心组合 | openssl s_client 握手、openssl x509 解析、shell 循环 |
| 关键参数 | -servername 指定 SNI 域名;-connect 指定地址与端口;x509 的 -enddate 与 -checkend 秒数 |
| 预警思路 | 用 -checkend 2592000(30 天)判断是否进入续期窗口 |
| 权限说明 | 普通用户即可,只依赖出网能力 |
典型使用场景
- 到期巡检:定期批量检查所有对外域名,提前进入续期流程
- 上线验收:确认新证书链完整、域名匹配
- 故障定位:应用报证书错误时,区分是证书本身问题还是客户端信任库问题
- SNI 核对:同一 IP 上多张证书时,确认按域名返回的是正确的证书
- 链完整性检查:确认中间证书是否随服务器下发
单域名检查
单域名检查
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -enddate -checkend 2592000
# -checkend 2592000:证书在 30 天内到期时退出码非 0,可直接作为告警判据批量巡检
批量巡检
for d in qiqicto.com api.example.com static.example.com; do
end=$(echo | openssl s_client -connect "$d:443" -servername "$d" 2>/dev/null \
| openssl x509 -noout -enddate)
echo "$d $end"
done链完整性与协议细节
链完整性与协议细节
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>&1 | head -n 40
echo | openssl s_client -connect example.com:443 -servername example.com 2>&1 | grep -E 'Protocol|Cipher|Verify'检查项读法
| 检查项 | 命令要点 | 异常表现 |
|---|---|---|
| 到期时间 | x509 -enddate | 日期临近或在过去,必须立即续期 |
| 签发者 | x509 -issuer | 与预期 CA 不符说明证书被替换或部署错 |
| 域名匹配 | 看证书里的 SAN 列表 | SAN 里没有目标域名会出现名称不匹配错误 |
| 链完整性 | -showcerts 看下发了几张证书 | 只发叶子证书时部分客户端会报链不可信 |
| 协议与套件 | -s_client 输出的 Protocol 与 Cipher | 出现已废弃版本说明服务端配置需要更新 |
链不全(缺少中间证书)常表现为浏览器或 curl 报错、而 openssl 手工握手看起来正常:因为部分客户端会尝试自动补齐,另一些不会。用 -showcerts 看服务端实际下发了哪几张证书,是最直接的判断方式。
-servername 必须写上目标域名:同一 IP 上常托管多张证书,不指定 SNI 会拿到默认证书,从而误判成「证书域名不对」。检查内网服务时则反过来——先用 -connect 指向目标 IP,再用 -servername 指定域名,避免 DNS 把请求带到别处。
想让检查可告警,就把日期数值化:从 -enddate 的输出里取出日期部分,用 date -d 解析成时间戳,再与当前时间相减得到剩余天数,按 30、14、7 天分级告警。这样证书巡检能直接接进监控与值班流程,而不依赖人工看日期。