Nginx代理自签名证书上游服务器出现SSL握手错误求助
我之前处理过一模一样的问题,你遇到的这个dh key too small错误,本质上不是证书信任的问题(哪怕你已经开了proxy_ssl_verify off),而是上游旧服务器使用的DH密钥长度不符合现代安全标准,Nginx依赖的OpenSSL默认会拒绝这种弱密钥的握手请求。
先拆解下日志里的错误信息:
2018/05/02 11:31:39 [crit] 3500#2284: *1 SSL_do_handshake() failed (SSL: error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small) while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1...
这个错误明确指向了DH密钥长度不足,现代OpenSSL默认要求DH密钥至少2048位,而你的旧服务器可能用了1024位甚至更小的密钥,所以握手直接失败了。
解决方案:调整Nginx代理的SSL策略
最稳妥的方式是在你的代理location块里添加针对性的SSL参数,绕开DH密钥交换的限制,同时兼容旧服务器的TLS版本:
修改后的完整Nginx配置
server { listen 8009; location / { proxy_ssl_verify off; proxy_ssl_session_reuse off; # 新增以下两行解决DH密钥过小问题 proxy_ssl_ciphers 'DEFAULT:!DH'; proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2; proxy_pass https://192.168.10.20:8009/; } }
参数解释:
proxy_ssl_ciphers 'DEFAULT:!DH':禁用DH密钥交换算法,改用RSA等其他密钥交换方式,这样就避开了DH密钥过小的问题。proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2:明确指定兼容的TLS版本,因为旧服务器大概率不支持TLS 1.3,而Nginx默认可能已经禁用了老版本的TLS,手动指定后能确保握手成功。
备选方案(不推荐全局修改)
如果上面的配置没生效,你也可以尝试在Nginx的全局http块里调整SSL策略,但这样会影响所有站点的安全级别,所以仅作为最后手段:
http { # ... 其他全局配置 ssl_ciphers 'DEFAULT:!DH'; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; }
额外提醒
虽然这个配置能解决当前的握手问题,但自签名证书+弱DH密钥本身存在严重的安全风险。如果条件允许,建议尽快升级旧服务器的SSL配置:
- 生成至少2048位的DH密钥(推荐4096位)
- 替换为可信证书机构颁发的证书,或者至少确保自签名证书的密钥长度符合安全标准
内容的提问来源于stack exchange,提问作者Venkatesh Nannan




