深色模式
SSL/TLS 证书问题排查
摘要:证书问题最常见的三类是过期、中间证书缺失、SNI/主机名不匹配。本文用
openssl s_client拿到真实握手结果与证书链,再配合curl复现,最后说明为什么"浏览器能打开但程序报错"。
适用环境
bash
openssl version
curl --version | head -1
date -u1
2
3
2
3
排障步骤
第 1 步:确认本机时间正确
bash
date -u1
时间错误会伪造出证书问题
系统时间超前会报"证书尚未生效",滞后会报"证书已过期"。排查证书前务必先确认时钟,否则会误判为证书故障。
第 2 步:握手与证书链
bash
openssl s_client -connect <域名>:443 -servername <域名> -showcerts </dev/null1
必须传 -servername,否则拿到的可能不是目标站点证书。
第 3 步:查看有效期与主体
bash
echo | openssl s_client -connect <域名>:443 -servername <域名> 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName1
2
2
重点核对 notBefore/notAfter,以及 SAN 中是否包含实际访问的主机名。
第 4 步:验证链是否完整
bash
openssl s_client -connect <域名>:443 -servername <域名> </dev/null 2>&1 | grep -E 'Verify return code|depth'1
Verify return code: 0 (ok) 才表示链完整可信。非零值(如 20、21)说明缺中间证书或根不受信。
第 5 步:用 curl 复现客户端行为
bash
curl -vI https://<域名>/ 2>&1 | grep -iE 'SSL|TLS|certificate|subject|issuer|expire'
curl --cacert /etc/ssl/certs/ca-certificates.crt -sS -o /dev/null -w '%{http_code}\n' https://<域名>/1
2
2
第 6 步:确认服务端配置的链顺序
bash
# 服务端应提供:叶子证书 + 中间证书(顺序为叶子在前)
openssl crl2pkcs7 -nocrl -certfile /etc/nginx/ssl/fullchain.pem \
| openssl pkcs7 -print_certs -noout1
2
3
2
3
第 7 步:检查协议与套件兼容性
bash
openssl s_client -connect <域名>:443 -servername <域名> -tls1_2 </dev/null
openssl s_client -connect <域名>:443 -servername <域名> -tls1_3 </dev/null1
2
2
验证
bash
echo | openssl s_client -connect <域名>:443 -servername <域名> 2>/dev/null | grep -E 'Verify return code'
curl -sS -o /dev/null -w 'code=%{http_code} ssl_verify=%{ssl_verify_result}\n' https://<域名>/1
2
2
常见坑
浏览器能访问、curl 却报错
浏览器会自动补全中间证书并缓存,curl、Java、Go 等客户端通常不会。缺中间证书在浏览器上"看起来正常",但程序必然失败。
忘了传 SNI(servername)
同一 IP 托管多站点时,未传 SNI 会返回默认证书,导致看到"错误的证书"却查不到原因。
证书链顺序错误
服务端证书必须在前、中间证书在后,顺序颠倒时部分客户端解析失败。
用 -k 跳过校验"临时解决"
curl -k、--insecure、代码中关闭校验只是掩盖问题,会让中间人攻击成为可能。只能用于临时对照验证,不能作为修复。