Sunday, 29 September 2013

ColdFusion / JVM and DNS caching: maybe Adobe aren't out to get me after all!

G'day:
Well here's something I didn't know. Depending on how your ColdFusion server is configured, DNS look-ups it does might be cached "forever" (read: for the life of the JVM).

Ray followed up my earlier post about "Adobe possibly messing with ColdFusion community projects again", pointing this out in a comment:

Anyway - don't forget that CF has that bug where it caches DNS lookups. Maybe the IP changed, and your host CF install is holding on to the wrong IP. That could be why it worked just fine on your local machine and Sharon's.

Try using the IP on the host. Of course, if they have multiple servers on the box it won't resolve to the right virtual server, but you would get a response right away.
My response to Ray (and the next two paras are a re-edit of my reply to him) was that I didn't know that! We learn something every day.

Since then I had a google around and found a lot of chatter about java.net.InetAddess caching DNS TTLs ad infinitum, which seems to be the underlying issue here (so not CF per se). Tom Jordahl blogged about this back in 2004: "CFMX and DNS caching".

Basically the issue can be traced back to a para in the docs for java.net.InetAddress:

InetAddress Caching


The InetAddress class has a cache to store successful as well as unsuccessful host name resolutions.

By default, when a security manager is installed, in order to protect against DNS spoofing attacks, the result of positive host name resolutions are cached forever.



[...]

If the default behavior is not desired, then a Java security property can be set to a different Time-to-live (TTL) value for positive caching. Likewise, a system admin can configure a different negative caching TTL value when needed.

Two Java security properties control the TTL values used for positive and negative host name resolution caching:

networkaddress.cache.ttl

Indicates the caching policy for successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the successful lookup. The default setting is to cache for an implementation specific period of time.

A value of -1 indicates "cache forever".

networkaddress.cache.negative.ttl (default: 10)

Indicates the caching policy for un-successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the failure for un-successful lookups.

A value of 0 indicates "never cache". A value of -1 indicates "cache forever".
So this sounds like a reasonable explanation.


Googling further, I found a comment against an article entitled "Any way to make Java honor the DNS Caching Timeout (TTL)?" on StackOverflow, which seems to suggest it's been fixed in Java 6 onwards, and having compiled and run that code, can indeed see DNS resolution following google about the place correctly. Well the resolved IP address was changing, anyhow.

I found some more code on a forum thread "Java's DNS cache behaviour", which returns the system's TTL setting:

public class TTL {
    public static void main(String[] args) {
        return;
    }

    public static int get(){
        return sun.net.InetAddressCachePolicy.get();
    }
}

Compiling that and running it locally via ColdFusion, I get: 30. Code:

// checkTtl.cfm
pathToTtlClass = expandPath("./");
javaLoader = createObject("javaloader.JavaLoader").init([pathToTtlClass]);
ttl = javaLoader.create("TTL");
writeOutput(ttl.get());

Running this on my CFMLDeveloper rig though, I get: -1. IE: the DNS is being cached forever!

Locally I'm running CF10, and Java 7. On CFMLDeveloper it's CF9 and Java 6. That said, I'd still expect the setting to be 30 by default on Java 6 too. Indeed I just tested on my CF9 rig - which is still running Java 6 - and it defaults to 30 as well. NB: I say it "defaults" to this... that's the value that gets returned from that code, and I've not monkeyed with anything in my CF install which'd change it, so I'm calling that the default.

So I think the setting on CFMLDeveloper is sub-optimal, and if Adobe have changed their DNS settings... this could be causing my problems!

Update:
I ran some more code locally and on CFMLDeveloper, and get different results for the bugbase IP address:

// checkCachedIp.cfm
javaLoader = createObject("javaloader.JavaLoader").init();
inetAddress = javaLoader.create("java.net.InetAddress");
writeOutput(inetAddress.getByName("bugbase.adobe.com"));

This results in this locally:
bugbase.adobe.com/192.150.19.119

And this on my CFMLDeveloper-hosted box:
bugbase.adobe.com/192.150.14.192

Thanks to Sharondio for putting me onto this blog article: "CFHTTP and DNS Revisited" by ColdFusion Muse (Mark Kruger), which had a comment (by Scott Pinkston) that had the above code in it. Well different code, but it prompted me to go make this check.

I shall touch base with Russ, and see if he can cycle my CF instance, and perhaps suggest he alters that setting from -1 to 30 (or just any number that's not -1. 30sec seems very low, really).

Ray: you're a star. Adobe... you're (at least temporarily ;-) off the hook!

Watch this space...

--
Adam