最可靠方法是用openssl s_client直测tls握手:openssl s_client -connect ip:443 -servername domain -showcerts | openssl x509 -noout -subject,应精确匹配对应域名cn或san;还需验证证书链完整性及无sni时的兜底行为。

直接用 openssl s_client 测试最可靠,它绕过浏览器缓存、CDN 和中间层,直击 TLS 握手阶段,能真实反映 Nginx 是否按域名返回了正确的证书。
用 OpenSSL 模拟不同域名的 SNI 请求
在服务器或任意能访问你 Nginx 的机器上运行:
- 测试 site-a.com:
openssl s_client -connect your-server-ip:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -subject
应输出类似CN = site-a.com或包含DNS:site-a.com的 SAN 信息 - 测试 site-b.net:
openssl s_client -connect your-server-ip:443 -servername site-b.net -showcerts 2>/dev/null | openssl x509 -noout -subject
应返回CN = site-b.net对应的证书主体,不能和上一条结果一样
检查证书链是否完整
仅验证 subject 不够,还要确认返回的是 fullchain.pem(含中间证书):
- 加
-text参数看详情:openssl s_client -connect your-server-ip:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -text | grep "Subject Alternative Name" -A1 - 输出中必须列出该域名所有有效 SAN 条目(如
DNS:site-a.com, DNS:www.site-a.com),且无缺失
验证无 SNI 请求的兜底行为
模拟老旧客户端(不发 SNI):
- 去掉
-servername参数:openssl s_client -connect your-server-ip:443 -showcerts 2>/dev/null | openssl x509 -noout -subject - 结果应与你配置的
default_server块或配置文件中第一个server块的证书一致 - 若未设兜底块,会返回第一个定义的 server 的证书——需确认这是否符合预期
排查常见误判点
如果结果不符合预期,优先检查这几项:
- Nginx 是否已重载:
nginx -t && nginx -s reload,避免配置未生效 - OpenSSL 版本是否支持 SNI:
nginx -V 2>&1 | grep -i openssl,必须显示 ≥1.0.2 的 OpenSSL,不能是 BoringSSL - 每个
server块是否都写了listen 443 ssl http2,漏掉ssl参数会导致证书不加载 - 证书路径是否写错或权限不足(
privkey.pem应为 600 权限)











