`curl`能通但浏览器不行,这个现象通常指向客户端(浏览器)不支持或无法识别服务端(国密Nginx)的加密套件与证书链。以下是结构化的排查思路:
第一步:检查Nginx是否真的支持国密
官方Nginx默认不支持国密算法。你需要确认Nginx是否已用支持国密的OpenSSL分支(如GmSSL、Tongsuo)重新编译。
执行检查:运行 `nginx -V`,查看输出中 `--with-openssl` 指向的路径是否为国密库,以及 `built with OpenSSL` 信息中是否包含 `GMSSL` 字样。
第二步:检查证书链是否完整
证书链不完整是常见原因。服务器若只发送了域名证书,没附带中间证书,浏览器会因无法构建完整信任链而报错。
执行检查:确保Nginx配置的 `ssl_certificate` 文件包含完整的证书链(即:服务器证书 + 所有中间证书),而不仅仅是服务器证书。顺序需从服务器证书开始,逐级到根证书。
第三步:确认浏览器是否支持国密
这是最核心的一步。普通浏览器(Chrome、Firefox等)不内置国密算法和根证书,必须使用专门的国密浏览器(如密信、红莲花、奇安信可信浏览器等)。
动作:
1. 换用上述国密浏览器访问。
2. 检查国密浏览器是否开启了“启用国密SSL通信”开关(如奇安信浏览器,默认可能关闭)。
3. 若浏览器曾用国际算法访问失败,可能会缓存错误状态,可尝试清理浏览器缓存和数据后再试。
第四步:检查加密套件与协议配置
国密浏览器和服务端必须就加密套件和协议达成一致。
检查 `ssl_protocols`:确保配置包含支持国密的协议版本,如 `TLSv1.1` 或 `NTLSv1.1`。
检查 `ssl_ciphers`:确保包含国密套件,例如 `ECDHE-SM2-SM4-CBC-SM3`。如果配置了双证书(SM2/RSA),需正确配置Nginx根据客户端支持的算法选择证书。
执行检查:使用 `openssl ciphers -v` 确认你的国密OpenSSL库支持的套件,并与Nginx配置的 `ssl_ciphers` 对比。
第五步:抓包分析与日志查看
如果以上步骤都无效,需要进行深层排查。
抓包分析:在服务器端用 `tcpdump` 抓包,然后用Wireshark分析TLS握手过程。重点看客户端Hello广播的加密套件,与服务端Hello选择的套件是否匹配。
查看Nginx错误日志:检查 `/var/log/nginx/error.log`,看是否有证书、协议或握手相关的错误。
第六步:其他通用排查
确认端口监听:确保Nginx监听在 `0.0.0.0:443` 而非 `127.0.0.1`。
检查防火墙/安全组:确保服务器防火墙和云服务商安全组已放行 `443` 端口。
如果问题依旧,可以尝试用支持国密的 `gmcurl` 工具在服务器本地测试,或在Nginx中增加 `ssl_session_cache` 配置。
总的来说,绝大多数情况都归结于浏览器不支持国密或证书链配置不完整。建议优先从这两点入手排查。