spray icon indicating copy to clipboard operation
spray copied to clipboard

Unnecessary reverse DNS query when connecting by IP with SSL

Open briandignan opened this issue 11 years ago • 9 comments

When connecting to a SSL server with the spray client by IP address, an unnecessary reverse DNS query is performed to lookup the hostname for the given IP. The query happens after the TCP 3-way handshake completes, and in some cases several seconds later. In my testing, it typically happens 4 seconds later (like in the attached packet capture screenshot) and sometimes causes the session to timeout, because it blocks the request from being sent. Other times the request completes but takes much longer than it should because of the query.

wireshark-capture

The DNS query is caused by a call to the java.net.InetSocketAddress.getHostName() in spray.io.SslTlsSupport.scala. From the Javadoc for InetSocketAddress.getHostName():

"Note: This method may trigger a name service reverse lookup if the address was created with a literal IP address."

http://download.java.net/jdk7/archive/b123/docs/api/java/net/InetSocketAddress.html#getHostName()

The actual behavior and delay with the DNS query might vary by operating system. I'm running OSX 10.9.5 with JRE version 1.7.0_67.

I'll submit a PR for a fix. Also, I'm pretty new to the open source scene, so please let me know if I should be doing anything differently with the issue report or PR. I did some manual testing after locally committing a fix using hostname and IP address, and both seem to work fine.

briandignan avatar Jan 21 '15 06:01 briandignan

I got ahead of myself and pushed the commit before running the tests. The change is causing some to fail. I'll take a closer look tomorrow.

briandignan avatar Jan 21 '15 07:01 briandignan

I don't know where I went wrong when I first ran the tests, but they're all passing now.

briandignan avatar Jan 21 '15 07:01 briandignan

Brian, thanks a lot for digging into this and reporting! (And sorry for taking so long to respond!) This looks like a valid problem with an easy fix. Thanks again!

sirthias avatar Feb 09 '15 10:02 sirthias

Actually, passing the hostname isn't unnecessary but required to support the SSL server name indication extension (starting with Java 7). So, the fix should be to check if the inetaddress is an ip address or a host name. If it's an ip address, pass that to the SSLEngine. If it's a host name pass that one.

jrudolph avatar Feb 09 '15 11:02 jrudolph

So, the fix would be to use InetSocketAddress.getHostString instead of InetSocketAddress.getHostName.

jrudolph avatar Feb 09 '15 11:02 jrudolph

Good catch! I didn't know that. Do you want me to submit an updated PR with the change? Also (you may have already seen this), but I noticed in the JavaDoc for InetSocketAddress that the getHostString method was first introduced in Java 1.7.

On another note, I'll be at Scala Days in San Fran this year. I'm looking forward to Roland Kuhn's presentation on Akka HTTP!

briandignan avatar Feb 09 '15 13:02 briandignan

Ah, I missed that. I guess Java 7 is not an option right now so I guess we need a new suggestion.

jrudolph avatar Feb 09 '15 13:02 jrudolph

It seems like the original host string would need to be passed along with the InetSocketAddress object so that it could be used in the call to sslContext.createSSLEngine( host, port ). From what I recall, it would require several intermediate functions to change. Maybe there's a cleaner way to do it? I'm not sure..

Does Akka HTTP also do reverse DNS resolution for SSL connections that are initiated with an IP Address? If so, I could look into fixing there instead.

briandignan avatar Feb 09 '15 22:02 briandignan

Hey @sirthias . Let me know what you think about the latest commit. Thanks!

briandignan avatar Feb 26 '15 16:02 briandignan