Nginx自签名证书被浏览器标记“不安全”的根本原因是客户端未信任根证书,需三步闭环解决:1. 证书必须含SAN扩展(如IP或DNS);2. Nginx的ssl_certificate须为server.crt与CA.crt拼接的完整链;3. 根证书须手动导入系统/浏览器受信任根证书库并设为始终信任。

Nginx 自签名证书在浏览器提示“不安全”,本质不是 Nginx 没配 HTTPS,而是客户端没把你的证书当作可信来源。排查重点不在服务端是否启用 SSL,而在“客户端是否真正信任该证书”——这需要两步闭环:服务端正确提供证书链,客户端主动导入并信任根证书。
确认服务端证书是否含 Subject Alternative Name(SAN)
Chrome、Edge、Safari 等现代浏览器强制要求证书包含 SAN 扩展,否则即使 HTTPS 能通,也会标记为“不安全”。自签名证书若只填了 CN(如 CN=192.168.1.100),而没在扩展中声明对应 IP 或域名,就会失败。
- 生成 CSR 或签发证书时,必须使用 -extfile 指定扩展配置文件,其中明确写入:
subjectAltName = IP:192.168.1.100 或 subjectAltName = DNS:dev.local - 用命令验证证书是否含 SAN:
openssl x509 -in server.crt -text -noout | grep -A1 "Subject Alternative Name",输出应类似:
X509v3 Subject Alternative Name: IP Address:192.168.1.100, DNS:dev.local - 若无此字段,需重新签发证书,不能仅修改配置文件或重启 Nginx
检查 Nginx 是否发送完整证书链(关键!)
自签名场景下,“完整链”就是你自己的根证书(CA.crt)+ 服务证书(server.crt)拼成的 fullchain。Nginx 只通过 ssl_certificate 向浏览器发送证书链,ssl_trusted_certificate 完全不参与此过程,设它无效。
- 确保 ssl_certificate 指向的文件是拼接好的 PEM 文件,顺序严格为:
— server.crt(你的服务证书)
— CA.crt(你自建的根证书)
两段之间不能有空行,每段以 -----BEGIN CERTIFICATE----- 开头 - 不要把根证书加进 ssl_certificate_key 或混入私钥文件
- 验证拼接是否正确:用 openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout 查看是否输出两个证书
客户端导入根证书并设为“受信任的根证书颁发机构”
浏览器只信任操作系统或自身维护的根证书列表。自签名证书的根证书必须手动导入到系统级信任库,而非仅“临时允许”或点击“继续访问”。
- Windows:双击 CA.crt → “安装证书” → 选择“本地计算机” → 存储位置选“受信任的根证书颁发机构” → 完成
- macOS:双击 CA.crt → 添加到“钥匙串访问” → 右键证书 → “显示简介” → 展开“信任” → “当使用此证书时”设为“始终信任”
-
Ubuntu/Debian:
sudo cp CA.crt /usr/local/share/ca-certificates/my-ca.crt
sudo update-ca-certificates - Chrome 和 Edge 使用系统根证书库,Firefox 使用独立证书库,需单独导入(地址栏输入 about:preferences#privacy → “证书” → “查看证书” → “权威机构” → 导入)
验证与清理缓存
证书信任状态会缓存,改完后不刷新可能仍报错。
- 浏览器访问 https://your-domain-or-ip 后,点击地址栏锁图标 → “连接是安全的” → “证书有效” → 查看证书路径,确认最上层是你导入的根证书
- 清除浏览器 SSL 状态:
Chrome 地址栏输入 chrome://restart(重启)或访问 chrome://net-internals/#hsts → 删除域名的 HSTS 记录(尤其曾被拒绝过) - 手机端需在系统设置中导入根证书(iOS:设置 → 已下载描述文件;Android:设置 → 安全 → 加密与凭据 → 安装证书)


















