BIND/Named: disabled recursion, client to use alternative servers

binddomain-name-systemmac-osx

I'm setting up a simple DNS server (BIND/Named), which is running locally on a OSX Laptop.

Its purpose is to resolve all requests for "*.laptop.example.com" to "192.168.2.2" – which is the manually assigned IP address (not DHCP) of a virtual network interface.

I'm using a virtual network interface (provided by Parallels) to ensure the IP address always remains the same (eth0 will change its IP address when connected to different networks), and to also ensure it is always available (eth0 is disabled/unavailable when a network cable isn't plugged in).

I have been using the following setup:

options {

  ...

  forwarders {
    192.168.1.1;
  };
  forward only;

};

However this requires the configuration to be updated each time the laptop changes network (as most networks have a different DNS address to use).

I would like to drop this requirement so that if BIND/Named does not recognise the domain name (i.e. it isn't a sub domain of "laptop.example.com"), then it returns an error so the laptop can try the second DNS address it has on record (one that it has picked up from DHCP).

One possibility is to use:

options {

  ...

  forwarders {
  };
  forward only;

  recursion no;

};

Which does stop it from spending 3+ seconds to query the ROOT servers… however the client interprets that response as "the domain does not exist", rather than an error which can be fixed by trying the next server.

Best Answer

Thanks Alnitak, duffbeer703, John Gardeniers, all very good feedback.

The solution I have used for my problem is to use launchd to detect the changes in /etc/resolv.conf, and then update the forwarders list.

By creating the file:

/Library/LaunchDaemons/myname.update.plist

With the contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
   "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Disabled</key>
    <false/>
    <key>Label</key>
    <string>myname.update</string>
    <key>ProgramArguments</key>
    <array>
        <string>[PATH]/update.sh</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/var/run/resolv.conf</string>
    </array>
</dict>
</plist>

And loading this with:

launchctl load /Library/LaunchDaemons/myname.update.plist
launchctl start myname.update

A script at:

[PATH]/update.sh

Can run something like:

DST="/var/named/forwarders.conf";

echo "forwarders {" > $DST

cat /etc/resolv.conf | \
    grep -v -E "(127.0.0.1|localhost)" | \
    awk '{ sub("^nameserver ", "\t"); sub("$", ";"); print }' >> $DST

echo "};" >> $DST

And then in the named config, it can use it with:

options {
    directory "[PATH]/conf/";
    listen-on { 127.0.0.1; [IP_ADDRESS_HOST]; };
    include "/var/named/forwarders.conf";
    forward only;
};

If you want to see or use the full implementation, go to my BIND setup page and use the download form... it creates a ZIP package with a single install script, so hopefully it is quite simple to setup and use.