bind DNS zone transfers with dynamic zones

dig netmess.org

If you operate a name server, you know you should have at least two of them. But how do you keep them in sync? “Easy, this is done with zone transfers!” you say? But what if you have a changing set of zones? Wonder how you can easily populate this zones to the slave server? Wonder no more!

This article is written along a Debian/Ubuntu flowered Linux. If you run any other distribution, it may happen that you can’t find a config file at the location I refer to here, but the principle is the same.

Before you get going, install the required software so you can later just go on. On Debian or Ubuntu, type this:

# apt-get install bind9 curl xml2 mktemp

Now you’re ready. On the master server, add this to /etc/bind/named.conf.options in between options {}:

allow-transfer { ip of slave server; };
notify yes;
version "Not available";
recursion no;

Of course you need to replace “ip of slave server” with the actual IP of the slave server. The version setting is not really needed, it just hides the bind version you’re running and therefore makes it harder for an attacker to tell what DNS server you are running. After you did the changes, restart bind:

# service bind9 restart

Then, edit the same file on the slave server:

allow-notify { ip of master server; };
version "Not available";
recursion no;

Also on the slave, add a directory where your zones are stored and set correct owner:

# mkdir /var/cache/bind/slave
# chown bind.bind /var/cache/bind/slave

The bind configuration files are very flexible. You can point to files to include them into the main config file. This allows you to organize your config and makes it cleaner. We use that, so a script can later generate a file containing slave zones only – without the whole rest of the config. On the slave, add this to /etc/bind/named.conf:

include "/etc/bind/named.conf.myzones";

With this setup you can already transfer zones. There is just one problem: The slave server does not know what zones he is responsible for. We change that with the magic of a simple shell script that creates the /etc/bind/named.conf.myzones file. Put the following in /usr/local/sbin/bind-zone-sync.sh on the slave server:

# config
master=ip of master server
remoteuser=user of master server that can access /var/cache/bind/
# helpers
#code :)
logger -t bind-zone-sync "starting bind zone sync."
for zone in $(ssh $remoteuser@$remotehost "echo /var/cache/bind/*"); do
	echo "zone \"$(basename ${zone%%???})\" {" >>$tmpfile
	echo "	type slave;" >>$tmpfile
	echo "	masters { $master; };" >>$tmpfile
	echo "	file \"slave/$(basename ${zone%%???}).bdb\";" >>$tmpfile
	echo "};" >>$tmpfile
	echo >>$tmpfile
if [ ! -e $myzonesfile ]; then
	cp $tmpfile $myzonesfile
	service bind9 restart
	logger -t bind-zone-sync "first run: generated $myzonesfile."
if [ "$(md5sum $myzonesfile | cut -d" " -f1)" != "$(md5sum $tmpfile | cut -d" " -f1)" ]; then
	cp $myzonesfile $bkpfile
	cp $tmpfile $myzonesfile
        service bind9 restart
	logger -t bind-zone-sync "done. backup of $myzonesfile is in $bkpfile."
rm -f $tmpfile
logger -t bind-zone-sync "done. no changes detected."

Set the correct values according to your environment below the “#config” marker. Then, make the script executable:

# chmod +x /usr/local/sbin/bind-zone-sync.sh

If you wish to automatically sync the zones, create an ssh key to allow automatic login to the master server. This is now very brief, ask if the stuff below doen’t work. Run this on the slave server and just press return on all questions unless you know why to change the proposed values:

# ssh-keygen

This creates a new key pair for you. The public key has to be copied to the master server, so he knows you’re allowed to login. As “remoteuser” you must take the same user you defined in the shell script above:

# ssh-copy-id remoteuser@masterserver

When you got the auto login running, add a cronjob on your slave server to schedule the sync. Insert this into /etc/cron.d/bind-zone-sync:

* */15 * * * root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin /usr/local/sbin/bind-zone-sync.sh

Now, your zones will be synced every 15 minutes to the slave server. Bind is only restarted if you added or removed a zone. Simply modifying records on the master wont trigger a bind restart but will be synced immediately to the slave without a restart.

If everything is working fine, you may want to monitor your bind DNS server with Zabbix?

monitoring bind9 DNS server with Zabbix

DNS-in-zabbix graph example

This is how to monitor the amount of queries in bind9 (version required is bind 9.5 at least) with Zabbix.

You need a working Zabbix server to follow these steps.

First, enable statistics in bind9. To do so, add the following line in /etc/bind/named.conf. (The location of the file can vary for different distributions). Do not put it between options {}!

statistics-channels {
 inet port 8053 allow {; };

Then, restart bind:

# service bind9 restart

This enables a web service within bind. To query it, we use curl and to flatten the served XML we use xml2. Both must be installed for this to work. On Debian flowered systems, simply do this:

# apt-get install xml2 curl

Now you can try to query by hand:

# curl http://localhost:8053/ 2>/dev/null | xml2 | grep -A1 queries

This spits out the counter for every request done against your nameserver. Now, configure Zabbix agents so they can get data to monitor this. Add the following two lines to /etc/zabbix/zabbix_agentd.conf:

UserParameter=bind.queries.in[*],curl http://localhost:8053/ 2>/dev/null | xml2 | grep -A1 "/isc/bind/statistics/server/queries-in/rdtype/name=$1$" | tail -1 | cut -d= -f2
UserParameter=bind.queries.out[*],curl http://localhost:8053/ 2>/dev/null | xml2 | grep -A1 "/isc/bind/statistics/views/view/rdtype/name=$1$" | tail -1 | cut -d= -f2

Then, restart zabbix agent:

# service zabbix-agent restart

And now you can add items to your Zabbix config like so:


Or, download my template ( zabbix-bind9-dns-template ) and import it in Zabbix. The following is then pre configured:

  • A records in & out
  • AAAA records in & out
  • ANY records in & out
  • CNAME records in & out
  • MX records in & out
  • NS records in & out
  • PTR records in & out
  • SOA records in & out
  • SPF records in & out
  • TXT records in & out
  • All queries in graph
  • All queries out graph


© 2017 netmess

Theme by Anders NorenUp ↑