I have a server in development and a few developers connecting to it.
This server uses Java\'s TLS implementation with SSLEngine
.
We saw that, at first,
Ari's solution of passing an empty hostname to the InetAddress
worked for connecting to a single host, but it had some side effects when connecting to multiple hosts by IP address. Java caches the SSLSession object using the tuple <remote-hostname, port>
. This can be seen in the OpenJDK here. Thus, TLS settings for a previous connection (specifically TLS protocol version in my case), were applied to a new connection to a different host (since both shared the same empty hostname). In my case, the new host rejected the downgraded TLS v1 protocol negotiated by the previous host, causing TLS handshake errors.
The solution was to construct a unique hostname based on the remote IP address instead like so:
String hostname = String.format("host-%s", BaseEncoding.base16().encode(address.getAddress()));
InetAddress newAddress = InetAddress.getByAddress(hostname, address.getAddress());
Thus the reverse DNS lookup Java performs was disabled, but cached TLS settings to remote hosts were only applied to the same remote host and port without the crosstalk effect.
I faced this same problem today when I tried to create a SSL socket connection by IP address only. That resulted in reverse DNS lookup attempt, and therefore it was really slow...
To me the solution was simply to pass a dummy empty string as the host name, when creating the InetAddress for the SSL connection. That is, I changed
InetAddress.getByAddress(addrBytes)
to
InetAddress.getByAddress("", addrBytes)
and it no longer does the reverse DNS lookup.
This question came up in 2006 on the Sun JSSE forums. The bottom line is that it seems to occur only in the Windows java runtime. In this bug report, towards the bottom, is one proposed solution. And here is another proposed solution:
Basically, a reverse DNS lookup during the SSL handshake causes a long timeout.
To fix the problem, cache your server address as an InetAddress object and reuse it in the Socket constructor whenever you are making a new connection to your server.
Hopefully one of these will work for you.