浏览器报“不安全”是因客户端不信任自签名证书,需闭环排查:证书是否含SAN、Nginx是否发送完整证书链(server.crt+CA.crt拼接)、根证书是否手动导入系统信任库。

浏览器对 Nginx 自签名证书报“不安全”,不是 HTTPS 没启用,而是客户端根本不信任这个证书。排查要围绕“证书是否被正确生成、是否被完整发送、是否被主动信任”这三点闭环展开。
检查证书是否含 Subject Alternative Name(SAN)
现代浏览器(Chrome、Edge、Safari)强制要求证书包含 SAN 扩展,仅靠 CN(如 CN=localhost 或 CN=192.168.1.100)已完全失效。若缺失,会直接报 NET::ERR_CERT_COMMON_NAME_INVALID。
- 用命令验证:
openssl x509 -in server.crt -text -noout | grep -A1 "Subject Alternative Name",输出应类似:X509v3 Subject Alternative Name: DNS:localhost, IP:127.0.0.1, IP:192.168.1.100 - 生成时必须显式指定 SAN:OpenSSL 3.0+ 可用
-addext "subjectAltName = DNS:dev.local,IP:192.168.1.100";旧版本需配合-extfile配置文件 - 如果没 SAN,删掉旧证书重做,改配置或重启 Nginx 无效
确认 Nginx 是否发送了完整证书链
自签名场景下,“完整链” = 服务证书(server.crt)+ 根证书(CA.crt),二者必须拼成一个 PEM 文件,并由 ssl_certificate 指向——这是唯一影响浏览器接收内容的指令。
- 拼接顺序严格:先
-----BEGIN CERTIFICATE-----(server.crt),紧接着换行,再-----BEGIN CERTIFICATE-----(CA.crt),中间不能有空行,不能混入私钥 - 验证拼接效果:
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout应输出两段证书 -
ssl_trusted_certificate对浏览器无作用,只用于 Nginx 内部(如 OCSP、mTLS),设它不能替代ssl_certificate
验证客户端是否真正信任根证书
浏览器只信任操作系统或自身维护的根证书库。你自建的 CA.crt 必须手动导入为“受信任的根证书颁发机构”,点击“继续访问”或临时允许不算数。
- Windows:双击 CA.crt → “安装证书” → 选择“本地计算机” → 存储位置选“受信任的根证书颁发机构”
- macOS:双击证书 → 导入钥匙串 → 右键证书 → “显示简介” → “信任” → 设为“始终信任”
- Android:设置 → 安全 → 加密与凭据 → 安装证书(类型选“CA 证书”)
- Linux(Chrome/Edge):需导入到系统级 trust store(如
trust anchor --store /etc/ssl/trust-store.pem CA.crt)或浏览器独立管理
快速交叉验证是否修复成功
别只看浏览器图标,用命令和第三方工具实测更可靠:
- 在服务器执行:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -showcerts 2>/dev/null | grep "BEGIN CERTIFICATE",应输出至少两段,且第二段 Subject 含你 CA 的组织信息 - 用 SSL Labs(ssllabs.com)扫描域名,关注 “Certification Paths” 显示绿色 ✔️,“Chain issues” 为 None
- 特别试 iOS Safari 和安卓 Chrome——它们不缓存中间证书,若这些设备正常,基本说明链已传全











