Java 8 初始SSL握手失败问题排查与解决求助
SSL握手失败(handshake_failure)故障排查与解决
问题背景
原本正常的连接在初始握手阶段出现SSL握手失败:发送ClientHello后未收到ServerHello,直接收到致命警报:
Fatal (HANDSHAKE_FAILURE): Received fatal alert: handshake_failure
已确认目标域名的 cipher suites 与TLS版本无兼容性问题。
SSL日志片段
javax.net.ssl|FINE|16 61|New I/O worker #36|2023-09-11 14:54:50.305 CEST|SSLEngineOutputRecord.java:505|WRITE: TLS13 handshake, length = 377 javax.net.ssl|FINE|16 61|New I/O worker #36|2023-09-11 14:54:50.306 CEST|SSLEngineOutputRecord.java:523|Raw write ( 0000: 16 03 03 01 79 01 00 01 75 03 03 0E 38 E9 53 F4 ....y...u...8.S. 0010: 6F CA B9 08 6E B6 FD C2 56 8F C3 90 7C 39 B3 62 o...n...V....9.b 0020: 49 97 06 6D 6C 0B 7A AD 87 63 95 20 0F 60 8F 82 I..ml.z..c. .`.. 0030: E3 4A F3 25 B9 B1 DD A0 27 E6 94 6F 70 3F 41 39 .J.%....'..op?A9 0040: FA 10 E5 45 F0 15 98 6D 05 2C 79 8B 00 5A 13 02 ...E...m.,y..Z.. 0050: 13 01 C0 2C C0 2B C0 30 C0 2F 00 9F 00 A3 00 9E ...,.+.0./...... 0060: 00 A2 C0 24 C0 28 C0 23 C0 27 00 6B 00 6A 00 67 ...$.(.#.'.k.j.g 0070: 00 40 C0 2E C0 32 C0 2D C0 31 C0 26 C0 2A C0 25 .@...2.-.1.&.*.% 0080: C0 29 C0 0A C0 14 C0 09 C0 13 00 39 00 38 00 33 .).........9.8.3 0090: 00 32 C0 05 C0 0F C0 04 C0 0E 00 9D 00 9C 00 3D .2.............= 00A0: 00 3C 00 35 00 2F 00 FF 01 00 00 D2 00 0A 00 12 .<.5./.......... 00B0: 00 10 00 17 00 18 00 19 01 00 01 01 01 02 01 03 ................ 00C0: 01 04 00 0B 00 02 01 00 00 0D 00 28 00 26 04 03 ...........(.&.. 00D0: 05 03 06 03 08 04 08 05 08 06 08 09 08 0A 08 0B ................ 00E0: 04 01 05 01 06 01 04 02 03 03 03 01 03 02 02 03 ................ 00F0: 02 01 02 02 00 32 00 28 00 26 04 03 05 03 06 03 .....2.(.&...... 0100: 08 04 08 05 08 06 08 09 08 0A 08 0B 04 01 05 01 ................ 0110: 06 01 04 02 03 03 03 01 03 02 02 03 02 01 02 02 ................ 0120: 00 17 00 00 00 2B 00 05 04 03 04 03 03 00 2D 00 .....+........-. 0130: 02 01 01 00 33 00 47 00 45 00 17 00 41 04 F7 1B ....3.G.E...A... 0140: 8D 37 18 D5 E9 DD 4F 85 85 BD FF DF ED 3B 94 87 .7....O......;.. 0150: BF 4B 79 D3 49 8A B3 11 BC 98 B9 53 1E 1B B6 28 .Ky.I......S...( 0160: EF 7E 16 0D 73 CA E9 A4 51 95 CE C7 D0 80 18 8C ....s...Q....... 0170: 7B C7 13 74 F1 29 D7 93 E6 1E BE 39 10 6C ...t.).....9.l ) javax.net.ssl|FINE|16 61|New I/O worker #36|2023-09-11 14:54:50.333 CEST|SSLEngineInputRecord.java:177|Raw read ( 0000: 15 03 01 00 02 02 28 ......( ) javax.net.ssl|FINE|16 61|New I/O worker #36|2023-09-11 14:54:50.334 CEST|SSLEngineInputRecord.java:214|READ: TLSv1 alert, length = 2 javax.net.ssl|FINE|16 61|New I/O worker #36|2023-09-11 14:54:50.334 CEST|Alert.java:238|Received alert message ( "Alert": { "level" : "fatal", "description": "handshake_failure" } )
故障原因分析
结合日志和已知信息,核心可能原因包括:
- 证书信任链不完整:客户端JVM信任存储中未包含目标服务器的根证书或中间证书,导致服务器证书验证失败,触发握手终止
- SNI扩展缺失:客户端发送的ClientHello中未携带Server Name Indication(SNI)信息,服务器无法匹配对应的虚拟主机配置或证书
- TLS 1.3兼容性问题:客户端JDK版本对TLS 1.3的支持存在缺陷,或服务器对特定JDK的TLS 1.3握手逻辑不兼容
- 服务器侧访问拦截:服务器防火墙、WAF或安全策略拦截了客户端的握手请求,直接返回失败警报
可行解决办法
- 补全证书信任链:将目标服务器的根证书/中间证书导入客户端JVM的默认信任存储(如
cacerts),执行命令:
注:默认keytool -importcert -alias snl-root -file root.crt -keystore $JAVA_HOME/jre/lib/security/cacertscacerts密码为changeit - 强制启用SNI:在客户端SSL代码中明确指定SNI,示例:
import javax.net.ssl.SNIHostName; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import java.util.Collections; // 获取SSLSocket实例后设置SNI SSLSocket sslSocket = ...; SSLParameters params = sslSocket.getSSLParameters(); params.setServerNames(Collections.singletonList(new SNIHostName("snl.no"))); sslSocket.setSSLParameters(params); - 降级TLS版本测试:临时将客户端TLS协议限制为TLS 1.2,排查兼容性,通过JVM系统属性设置:
java -Djdk.tls.client.protocols=TLSv1.2 YourApplication - 排查服务器侧规则:联系服务器管理员确认是否存在针对客户端IP、握手特征的拦截策略,或服务器SSL配置是否有变更
内容的提问来源于stack exchange,提问作者Nils Weinander
相关产品推荐
相关产品推荐

