info@openesque.com +1 (248) 330-4446

BIND 9 without slaves

Formerly "BIND 8 without slaves," it works on both.

Disclaimer

This document is provided free of charge, and thus, only provided on an "as-is" basis. Although the information contained in this document is believed to be correct, there may be errors or omissions in this document. Neither the author nor Openesque LLC shall be liable for any damages, including incidental or consequential damages, as a result of any errors or omissions in this document.

As with any server configuration change, you should test and verify this in a test environment before including this in your operational environment.

Audience

This document assumes that you have previous experience configuring and running a BIND 9 server, as well as basic sh(1) scripting skills (at least enough to read and understand what's presented here.)

This procedure works best in conjunction with ssh-agent(1) loaded with a key that provides necessary access. The alternative is to either repeatedly type passwords, or have a horribly insecure key without a passphrase. If none of this means anything to you, then:

  1. man ssh and man ssh-agent.
  2. Use ssh with an agent until you understand the system thoroughly, including security ramifications. Once mastered, it's a useful tool for many system administration (and power user) tasks in a Unix environment.
  3. Don't try using the techniques described here until you've completed the above steps.

Overview

Managing master and slave BIND DNS servers has been a complicated, error-prone, bandwidth-wasting, and from a security standpoint, dangerous operation for some time. This document describes how to eliminate slave BIND servers forever. Dan Bernstein provided the insight for this technique in his documentation for his djbdns name server.

In a nutshell, here's how it works: you run all your nameservers as primaries. Turn off notify for zone updates, and don't accept zone transfers from anyone. Instead, use rsync with ssh to securely transfer updated zone files from one name server to all other name servers serving the same data. Then, use ssh to reload the name servers. It's simpler, faster, and much more secure.

This works for BIND 8 and 9. It may work for BIND 4, but I have no intention of investigating this unless paid to.

Can I use this technology?

If you're running BIND 9 servers on platforms that support rsync and ssh, you can. However, if any of your name servers don't follow these requirements, then the answer is no.

Deployment

Include the following in your global options in your named.conf.

notify no;
allow-transfer { none; };

Each zone that you serve is labeled as type master;. This tells the local server that it is authoritative for this zone (even though SOA may be different,) and that it does not need an update from another master.

 zone "openesque.com" {
    type master;
    file "p/openesque";
    allow-query    { any; };
};

ndc reload to make this take effect.

Now, your nameservers are "stand-alone". But you will need to modify your zones from time to time. rsync, ssh, and a little shell scripting make this trivial.

NOTE: zone serial numbers must still be updated properly or this procedure will fail.

My real-world example follows.
NOTE: These machines have all been retired long ago. I actually use CVS (over ssh) to keep my zone files synched now, but I don't have time to spell out the nuances of that. So, understand this before you try it!

olly.openesque.com and chester.openesque.com are my public nameservers. bighead is a private BIND 8 server on my work firewall (only answering on the private interface) which also serves as a primary server for zones that I host.

Normally, I do zone maintenance from my office on bighead, then use push-named to propagate my changes to olly and chester. However, in the event that I'm away from the office and need to make changes, olly and chester will at least synchronize each other (they can't get to bighead from the outside.) Later, I would have to manually resynchronize bighead's files. This happens very rarely, so I haven't bothered to write a pull-named.

#!/bin/sh
# push-named: distribute changes to /var/named to other servers.

[ $# -eq 0 ] || { echo "usage: push-named" >&2; exit 1; }

RSYNC=/usr/local/bin/rsync

# can't get to bighead from the outside (yet. ;-)

ME=$(hostname -s)

case $ME in
bighead)
	NSERVERS="olly.openesque.com chester.openesque.com" ;;
olly)
	NSERVERS="chester.openesque.com" ;;
chester)
	NSERVERS="olly.openesque.com" ;;
*)
	echo "push-named: unknown host \"$ME\"" >&2; exit 1; ;;
esac

for NSERVER in $NSERVERS; do
	echo "-> $NSERVER"
	$RSYNC -avz -e ssh push-named named.conf named.root p \
	$NSERVER:/var/named
	ssh $NSERVER ndc reload
done

That's all there is to it.

Feedback and comments are welcome; send to feedback@openesque.com.