Split DNS FTW

After many months of not posting, I can post again. Long story short, I couldn't get to my blog to post new content because of internal DNS issues. The reason? Public facing computers resolve DNS entries differently than internal clients.

The problems started after getting a new router while trying to debug a Nexus One WiFi problem. After installing dd-wrt, WAN NAT redirection no longer worked. From what I can find on the internet, it has been disabled in dd-wrt (I'm too lazy to find a link, use Google if you are interested) to improve compatibility with certain services (and also because WAN NAT redirection is a hack to begin with).

To fix this, you need split DNS so that internal clients resolve the internal IP to your server, while outside clients resolve your public IP which is then forwarded to your server. My first attempt was to setup a DNS server and tell dd-wrt to use it as the primary DNS lookup server for internal clients. That didn't work, so I eventually found a different way.

The trick is to use DNSMasq which is built-in to dd-wrt. In the "Services" tab in dd-wrt, scroll down to the DNSMasq section. Make sure DNSMasq and "Local DNS" are both enabled. Then in the "Additional DNSMasq Options" add:

address=/yourdomain.com/192.168.1.xxx address=/mail.yourdomain.com/172.16.0.xxx

This will tell your router to skip regular DNS lookups and use that IP for yourdomain.com or ANY SUBDOMAIN. A more specific domain rule has precedence over other rules. This means that in the example above, yourdomain.com, www.youdomain.com, *.yourdomain.com will resolve to the 192.168.1.xxx IP except for mail.yourdomain.com which resolves to 172.16.0.xxx (because it's more specific).

With this trick, both internal and external clients can use the same domain, but each client type will get a different IP based on the source of the request (internal vs external).