核心是精准配置proxy_ssl_protocols以对齐旧版Java微服务支持的TLS版本:实测确认后端仅支持TLSv1或TLSv1.1后,在location/upstream块中设proxy_ssl_protocols TLSv1 TLSv1.1,禁用TLSv1.2+,并配合proxy_ssl_server_name on和弱套件等必要调整。

直接在 Nginx 的 proxy_pass 上下游配置中设置 proxy_ssl_protocols,让 Nginx 作为客户端连接旧服务时使用对方能接受的 TLS 版本,这是解决握手失败最核心的一步。关键不是“降级”,而是精准对齐——旧版 Java 微服务(如 JDK 7u95 或 JDK 8u31 前)通常只支持 TLSv1 或 TLSv1.1,而现代 Nginx 默认不启用这些协议。
确认微服务实际支持的 TLS 版本
别猜,要实测。用 OpenSSL 直连后端地址验证:
-
openssl s_client -connect your-service:8443 -tls1→ 成功说明支持 TLSv1 -
openssl s_client -connect your-service:8443 -tls1_1→ 成功说明支持 TLSv1.1 -
openssl s_client -connect your-service:8443 -tls1_2→ 失败且报错 handshake failure,基本可确认不支持 TLSv1.2
同时检查微服务启动参数,如是否显式设置了 -Dhttps.protocols=TLSv1,这会强制锁定协议,覆盖 JVM 默认行为。
在 proxy\_pass 作用域内配置 proxy\_ssl\_protocols
这个指令只影响 Nginx **作为上游客户端**的行为,和面向用户的 ssl_protocols 完全无关。必须放在 location 或 upstream 块里,不能写在 http 全局块:
- 若后端仅支持 TLSv1:
proxy_ssl_protocols TLSv1; - 若支持 TLSv1 和 TLSv1.1(JDK 8u60 前常见):
proxy_ssl_protocols TLSv1 TLSv1.1; - 绝对不要加入
TLSv1.2或更高版本,否则协商必败
注意:Nginx 1.19.4+ 默认已移除 TLSv1 支持。如需启用,需确认编译所用 OpenSSL ≥ 1.0.1(CentOS 7 的 1.0.2k 通常满足)。
同步调整加密套件与 SNI 行为
光调协议不够。旧版 Java 默认不支持 AEAD 类套件(如 AES-GCM),还可能依赖 SNI 才能选对证书:
- 匹配弱套件(仅限临时调试):
proxy_ssl_ciphers 'ECDHE-RSA-AES128-SHA:AES128-SHA';(避免 RC4,生产禁用) - 若微服务启用了 SNI(例如 Spring Boot + Tomcat 配了多个域名证书),必须开启:
proxy_ssl_server_name on; - 同时指定 SNI 域名:
proxy_ssl_name "your-service-domain.com";(upstream 场景下不可省略,不能只靠$host)
谨慎对待证书校验
内网可信场景下,若仍握手失败且确认协议/套件/SNI 均无误,可临时关闭上游证书校验辅助排查:
proxy_ssl_verify off;proxy_ssl_trusted_certificate /dev/null;
⚠️ 此配置仅用于定位问题,生产环境必须恢复证书校验并配置正确 CA 信任链。











