Why does Java's SSLSocket send a version 2 client hello?
The SSLSocket.getEnabledProtocols()
method returns the following: [SSLv2Hello, SSLv3, TLSv1]
. And indeed, when I call connect()
and I have SSL debugging turned on, I see that a v2 client hello is used:
main, WRITE: TLSv1 Handshake, length = 81
main, WRITE: SSLv2 client hello message, length = 110
But I have found two (admittedly old) references that say JSSE does not support SSL version 2:
From Fundamental Networking in Java:
'SSLv2Hello' is a pseudo-protocol which allows Java to initiate the handshake with an SSLv2 'hello message'. This does not cause use of the SSLv2 protocol, which is not supported by Java at all.
And from the JSSE Reference Guide:
The JSSE implementation in the J2SDK 1.4 and later implements SSL 3.0 and TLS 1.0. It does not implement SSL 2.0.
Now, my understanding is that version 2.0 client hello should only be sent when the client does support SSL version 2.0. From RFC 2246:
TLS 1.0 clients that support SSL Version 2.0 servers must send SSL Version 2.0 client hello messages [SSL2] ... Warning: The ability to send Version 2.0 client hello messages will be phased out with all due haste.
So why does Ja开发者_开发技巧va use it?
Sun's JSSE doesn't support SSLv2 but it supports the SSlv2ClientHello
, to support some SSL servers that require it. You can turn it off by removing it from the enabled protocols.
IBM's JSSE does support SSLv2 entirely.
From the JSSE Reference Guide:
For example, some older server implementations speak only SSLv3 and do not understand TLS. Ideally, these implementations should negotiate to SSLv3, but some simply hangup. For backwards compatibility, some server implementations (such as SunJSSE) send SSLv3/TLS ClientHellos encapsulated in a SSLv2 ClientHello packet. Some servers do not accept this format, in these cases use setEnabledProtocols to disable the sending of encapsulated SSLv2 ClientHellos.
I imagine 'server implementations' should read 'SSL implementations' above.
EDIT: thanks for citing my book!
I faced the same issue, we had this error on our RCP application, it was trying to access our nginx which only handle TLS protocols. but openjdk which we use has a bug with TLS which in some case will end in: javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
. So i was trying to find a way to use a different protocol to do the handshake like SSLv3. At first I though that SSLv2Hello
is the handshake protocols! but it is not!
SSLv2 never implemented in sun jdk or openjdk, this SSLv2Hello
is not the actual protocol for the handshake, it is there for backward compatibility(my guess is because of the probability of existence of some servers) and it will be used for negotiation on the available protocols that will be used for the actual handshake!
on this link search for the answer from Stoinov
, he wrap the answer very well.
精彩评论