网站接入 HTTPS 后,常见的故障有三类:证书过期、浏览器提示“不受信任”、个别客户端(尤其是 Java、Android 旧版本、curl)握手失败而浏览器正常。这些问题用 openssl 和 curl 就能快速定位,不需要先猜。
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName输出重点:
notAfter:证书到期时间,确认是否已过期或临近过期。subjectAltName:证书覆盖的域名列表。现代客户端以 SAN 为准,不再只看 CN。issuer:签发机构,用于判断链是否对得上。-ext 选项需要 OpenSSL 1.1.1 及以上版本,低版本可用 -text 查看全部内容。
浏览器“不受信任”最常见的原因是服务器只配置了域名证书,缺少中间证书。部分浏览器会自动补全中间证书所以表面正常,但 curl、Java 等不会,从而表现为“浏览器能开,程序报错”。
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null关注两处:
Certificate chain 部分,正常应当看到域名证书和至少一级中间证书。Verify return code:0 (ok) 表示验证通过;21 (unable to verify the first certificate) 或 20 通常说明缺少中间证书。修复方式是在服务端配置包含完整链的证书文件,即域名证书在前、中间证书在后。以 Nginx 为例:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com_bundle.crt; # 域名证书 + 中间证书
ssl_certificate_key /etc/nginx/ssl/example.com.key;
}证书服务商下载包里通常提供合并好的 bundle 文件,以及单独的证书文件,使用 bundle 文件即可。根证书无需放入链中,客户端自带信任库。
同一个 IP 上托管多个 HTTPS 域名时,服务器依赖客户端在握手中发送的 SNI 来选择证书。如果不带 -servername,openssl s_client 不会发送 SNI,服务器会返回默认证书,容易误判。
# 不带 SNI,可能得到默认证书
echo | openssl s_client -connect 1.2.3.4:443 2>/dev/null | openssl x509 -noout -subject
# 带 SNI,模拟浏览器访问指定域名
echo | openssl s_client -connect 1.2.3.4:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject对比两次输出,可以确认服务端的虚拟主机与证书是否对应。用 CDN、负载均衡或网关做回源时,回源请求是否带正确的 SNI 也是常见问题来源。
curl -vI https://example.com 2>&1 | grep -E 'SSL|subject|issuer|expire|HTTP/'
# 指定解析到某个 IP,绕过 DNS 测试某台后端
curl -vI --resolve example.com:443:1.2.3.4 https://example.com--resolve 能让你在不改 hosts 的前提下,让请求带着正确的域名和 SNI 发往指定 IP,适合逐台检查多个节点是否部署了同样的证书。
更换证书后服务无法启动,常见原因是证书与私钥不是一对。对比公钥摘要:
openssl x509 -noout -pubkey -in example.com.crt | openssl sha256
openssl pkey -pubout -in example.com.key | openssl sha256两个摘要一致才是同一对。
可以用脚本检查剩余天数,配合定时任务和告警:
end=$(echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 ))
echo "剩余 ${days} 天"告警阈值按证书续期流程的耗时来定,留出足够的处理时间。使用自动续期时,也要监控续期任务是否真的成功,并在续期后重载服务。
-servername 查看证书的 SAN 和有效期。Verify return code 与证书链是否完整。curl --resolve 逐台验证后端节点。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。