Java SSL SSLHandshakeException handshake_failure
Posted
技术标签:
【中文标题】Java SSL SSLHandshakeException handshake_failure【英文标题】: 【发布时间】:2015-05-16 21:06:26 【问题描述】:我正在使用 java 8 并使用 SSLSocket 请求此 url: https://www.flixbus.de/sites/default/files/6_jetzt_buchen_button_tiny.png
我总是收到握手错误。 socket.setEnabledProtocols() 强制使用特定协议没有帮助。
顺便说一句,所有其他网络服务器都可以正常工作。所以它可能与我的代码无关。
在没有任何 ssl/tls 协议限制的情况下也会发生此错误。
有什么想法吗?
选项“javax.net.debug=all”的输出如下:
DEBG getSecureScocket: Supported protocols:
- SSLv2Hello
- SSLv3
- TLSv1
- TLSv1.1
- TLSv1.2
DEBG getSecureScocket: Enabled protocols:
- TLSv1.2
Http Client, setSoTimeout(120000) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1426330417 bytes = 229, 161, 185, 11, 136, 85, 35, 88, 166, 144, 191, 126, 10, 196, 215, 241, 43, 190, 221, 246, 240,
217, 82, 29, 180, 106, 35, 253
Session ID:
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_
AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH
_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_A
ES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WIT
H_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WIT
H_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_12
8_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: 0
Extension elliptic_curves, curve names: secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1,
secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r
2, secp224k1, sect239k1, secp256k1
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA25
6withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
***
[write] MD5 and SHA1 hashes: len = 193
[Raw write]: length = 198
[Raw read]: length = 5
[Raw read]: length = 2
Http Client, READ: TLSv1.2 Alert, length = 2
Http Client, RECV TLSv1.2 ALERT: fatal, handshake_failure
Http Client, called closeSocket()
Http Client, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Http Client, called close()
Http Client, called closeInternal(true)
Http Client, called close()
Http Client, called closeInternal(true)
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
at sun.security.ssl.AppOutputStream.write(Unknown Source)
at java.io.OutputStream.write(Unknown Source)
[...]
【问题讨论】:
您是否尝试过启用所有支持的协议而不仅仅是 TLSv1.2?只是看看这是否是问题所在(因为您可能已经知道,SSLvX 不再推荐用于生产) 是的。首先,我使用启用所有协议的默认值。也不行。我找到了这个解决方案here。这就是我限制协议并希望它会有所帮助的原因。 【参考方案1】:该站点需要SNI (server name indication),即没有SNI,握手将失败。所有现代浏览器都支持 SNI,但并非所有编程语言中的 SSL 堆栈都支持或默认使用 SNI。有关如何在 Java 8 中使用 SNI,请参阅 http://www.vimino.com/2014/01/jep-114-tls-sni-extension-sunjsse-behavior-changes/。
你可以用openssl s_client
检查这种行为:
# without SNI
$ openssl s_client -connect www.flixbus.de:443
CONNECTED(00000003)
140612985652896:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:770:
....
New, (NONE), Cipher is (NONE)
# with SNI
$ openssl s_client -connect www.flixbus.de:443 -servername 'www.flixbus.de'
CONNECTED(00000003)
...
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
或者你可以使用analyze.pl:
$ perl analyze-ssl.pl www.flixbus.de
-- www.flixbus.de port 443
* maximum SSL version : TLSv1_2 (SSLv23)
...
* SNI supported : SSL upgrade fails without SNI
【讨论】:
非常感谢您指出这个(新的)SNI 扩展。这确实解决了问题。 @steffen-ullrich 嗨,如果我运行你的脚本,我会收到IO::Socket::SSL version 1.984 required--this is only version 1.31 at analyze-ssl.pl line 10.
。对非 perler 的任何提示?
@injecteer:您使用的 1.31 版本已经超过 5 年了,所以我想您需要以某种方式获得更新的版本。如果您在 Windows 上,最新的 Strawberry Perl 应该包含您需要的内容。如果您使用的是 Linux,则最新的发行版包含您需要的内容。
您如何确定此站点需要 SNI?
@heez:使用我在答案中提到的工具。但你也可以使用SSLLabs。【参考方案2】:
这个错误可能是服务器不支持你使用的Tls1.2
【讨论】:
我限制为 TLS1.2,因为服务器使用 TLS1.2 回复。至少这是我从日志中了解到的。如果我不做任何协议限制,它也不起作用。以上是关于Java SSL SSLHandshakeException handshake_failure的主要内容,如果未能解决你的问题,请参考以下文章