浏览器提示“不安全”主因是证书链不完整或不可信,需检查:1.证书是否含访问域名的SAN;2.Nginx是否通过fullchain.pem发送完整有序证书链;3.客户端是否信任签发者根证书。

浏览器提示“不安全”或显示红色警告,多数不是 Nginx 没启 HTTPS,而是它发出去的证书链有问题——客户端无法从你给的证书顺藤摸瓜信任到一个已知根证书。排查核心就三点:证书是否真含访问域名、Nginx 是否发出了完整链、浏览器是否认得签发者。
确认证书是否覆盖实际访问的域名
现代浏览器强制校验 SAN(Subject Alternative Name),只看 CN 已经没用了。
- 用命令检查:openssl x509 -in server.crt -text -noout | grep -A1 "Subject Alternative Name",输出里必须有你正在访问的完整域名或 IP,比如 DNS:api.example.com 或 IP:192.168.5.10
- 如果访问的是 www.example.com,但证书只写了 example.com,或者用了 *.example.com 却去访问根域,都会失败
- 自签名证书必须在生成时用 -extfile 显式写入 SAN,不能靠改配置补救
验证 Nginx 实际发送的证书链顺序和完整性
Nginx 只通过 ssl_certificate 这一个指令对外发证书链,它必须是拼好的 PEM 文件,且顺序不能错。
- 确保 ssl_certificate 指向的是 fullchain.pem,而不是单独的 cert.pem;内容应为:
— 第一段:你的服务证书(server.crt)
— 第二段:中间证书或 CA 根证书(CA.crt,自签名场景下就是它)
两段之间**不能有空行**,每段以 -----BEGIN CERTIFICATE----- 开头 - 用命令实测它发了什么:openssl s_client -connect your-domain.com:443 -showcerts 2>/dev/null,观察输出中 BEGIN CERTIFICATE 块的数量和顺序:第一块必须是你域名的证书,后续是中间/根证书;如果只有一块,说明链没发全
- 别把根证书塞进 ssl_certificate_key,也别把私钥混进证书文件——这类错误会导致握手直接失败
检查客户端是否真正信任签发者
浏览器不信任,本质是它本地没存你这个 CA 的根证书。这不是 Nginx 配置能解决的,必须手动干预客户端。
- 把你的 CA.crt(自签名场景下的根证书)导入操作系统或浏览器的“受信任的根证书颁发机构”存储区,不是“其他用户”或“临时允许”
- Windows 上双击证书 → “安装证书” → 选择“本地计算机” → 存储位置选“受信任的根证书颁发机构”
- macOS 上用钥匙串访问,拖入后右键“显示简介”→“信任”→“始终信任”
- 导入后需重启浏览器,部分系统还需运行 sudo update-ca-certificates(Linux)刷新信任库
排除常见干扰项
有些问题看起来像证书链错误,其实卡在别的环节。
- 改完配置后只执行 nginx -s reload 不够,先运行 nginx -t 确认语法和文件路径无误;权限也要检查:证书文件建议 644,私钥必须 600
- 多个 server 块共用 443 端口时,注意 server_name 是否匹配;没匹配上的请求会被第一个 HTTPS server 块兜底,可能返回完全无关的证书
- CDN、代理或浏览器自身会缓存旧的证书链,测试时用无痕窗口或换设备,避免被缓存误导











