DNS, Multicast DNS, Apple devices and .local domains
Nearly ten years ago, we decided to use a first-level domain of .local for servers on our internal network that were not supposed to be accessed from the Internet. Back then, this was actually quite popular, and even Microsoft suggested the use of .local as a pseudo-TLD for small private networks with internal DNS servers.
Interestingly, times have changed. Today, even an article on Wikipedia states that "resolving such names via unicast DNS servers has fallen into disfavor". It turns out that .local domains are now widely used by devices supporting zero-configuration networking. And zeroconf no longer relies on good old (unicast) DNS - it uses Multicast DNS (mDNS) instead, which is very different. But even though no one was recommending using unregistered suffixes such as .local any more, they worked just fine. After all, we mostly use Windows, which doesn't even support mDNS.
But when we upgraded our Apple devices to iOS 8 and OS X Yosemite (10.10), all our servers using .local domain names suddenly became invisible to our iPads and Macs.
What's going on? Well, it turns out that Apple decided to only use mDNS for .local domain name resolving. They also made it impossible to disable this behavior - instead, the recommended solution is "changing your private network to use a domain-name suffix other than .local". Unfortunately, this is easily said than done. We have been using those .local domain names for so long that it would take ages to reconfigure all the servers and application to use a different suffix! We use most of our Apple devices to run automated unit tests, and going through tens of thousands lines of code just to change .local to something else sounds like something we would rather skip.
After we found out that no one has a simple solution to this issue, we decided to implement a "Multicast DNS to DNS" proxy. Our platform of choice is C# and .NET, so naturally, we tried to utilize the open-source mDNS.NET library first. Unfortunately, it turned out its API is too high-level for this purpose. Then we stumbled upon multicast-dns, a newly-released mDNS implementation for Node.js. Fortunately, I have been looking into this platform recently and we were able to write a simple mDNS proxy server based on that library within an hour. And it works! Our Macs and iPads can now happily resolve all of our .local domain names again.
If you are dealing with a similar issue, give this a try - it's actually quite simple:
- Install Node.js and NPM on one of your servers.
- In your OS shell, execute
npm install mdns-proxy -g. This will install our mDNS proxy package.
mdns-proxycommand. On Windows, you might need to add the machine's IP address as an additional argument.
That's it! If you would like to run the app forever, check out forever package.
Although this simple application solved our issues with Apple devices, it's still not perfect. For example, it doesn't pay attention to the time-to-live value of DNS records and uses a default of 1800 seconds. But the biggest limitation is lack of support for "does not exist" replies), and this actually causes a several-second delay on IPv6 networks if your .local domains names lack IPv6 "AAAA" records. We don't plan to add this feature ourselves, but both mdns-proxy server and multicast-dns library are open-source, which means anyone can add what's missing. If you do, please let us know.