Tony Finch has created a gem of a utility called nsnotifyd. It’s a teeny-tiny DNS “server” which sits around and listens for DNS NOTIFY messages which are sent by authority servers when they instruct their slaves that the zone has been updated and they should re-transfer (AXFR / IXFR) them. As soon as nsnotifyd receives a NOTIFY, it executes a shell script you provide. (This is a very welcome alternative to doing it in Perl, as I did when I wanted to be notified of new and changed KSK in a zone.)
The script you provide (Tony has a few examples in the repository) is passed the name of the notified zone, its SOA serial number and the address of the master authority server which emitted the NOTIFY. Whether or not you actually use that data is up to you, of course. nsnotifyd can be used for all sorts of things:
- Creating backups (discussed below). (You could even rsync zone files to a remote location.)
- Alerting humans or machines on zone changes.
- Taking snapshots of PowerDNS databases on zone changes.
- Read the zone, create reverse-DNS entries in another zone. Tony provides a script which helps with that.
- Poor-man’s bump-in-the-wire DNSSEC signer; see repository.
So, let’s assume I wish to keep a Git repository with changes to a few zones. I create a repository, add empty zone files, and create the shell script nsnotifyd will be invoking.
#!/bin/sh
export GIT_AUTHOR_NAME='nsnotifyd'
export GIT_AUTHOR_EMAIL='nsnotifyd@example.com'
export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
(
cd /etc/nsd/backup || exit 2
zone=$1 serial=$2 master=$3
case $zone in
(.) zone=root
esac
# BIND <= 9.9.0? You may want to replace +rrcomments with +multiline
dig +noall +answer +onesoa +rrcomments @$master $zone axfr >$zone
git commit -q -m "$zone IN SOA $serial" $zone
) 2>&1 |
logger -p daemon.notice -t $0 -s
I add an explicit notify
statement to the zone stanza in NSD, and enable transfers from the address nsnotifyd runs on.
zone:
name: "example.org"
zonefile: "example.org.zone"
allow-notify: 192.168.1.110 NOKEY
request-xfr: 192.168.1.110 NOKEY
provide-xfr: 192.168.1.110 NOKEY
provide-xfr: 127.0.0.1 NOKEY
notify: 127.0.0.1@5353 NOKEY
A similar configuration for a BIND zone could look like
zone "example.org." IN {
type master;
file "example.org";
allow-transfer { 192.168.1.110; };
update-policy {
grant local-ddns zonesub ANY;
};
also-notify port 5353 { 127.0.0.1; };
};
I then launch nsnotifyd which daemonizes itself.
$ nsnotifyd -4 -a 127.0.0.1 -p 5353 -s 127.0.0.1 /etc/nsd/nsnotifyd/jp2git.sh example.org
As soon as nsnotifyd starts up, it queries the SOA record of the specified zones, typically by querying the host’s resolver. (I overrode that with the -s
option to force it to query a particular name server.) It then sits back and waits until refresh time has elapsed, whereupon it will check whether the serial number has changed; if so, it launches our script.
nsnotifyd[5117]: example.org refresh at 2015-06-16 15:22:12 +0000
I then issue a notify using nsd notify
(or Gavin Brown’s pnotify, or rndc notify example.org
– you get the drift). Following along in the file syslog logs to, we see:
nsnotifyd[5117]: example.org notify from 127.0.0.1/50028
nsnotifyd[5117]: example.org IN SOA 1434350317 unchanged
nsnotifyd[5117]: example.org refresh at 2015-06-16 15:24:45 +0000
I then actually update the zone. NSD sends out its NOTIFY, and nsnotifyd reacts:
nsnotifyd[5117]: example.org notify from 127.0.0.1/45669
nsnotifyd[5117]: example.org IN SOA 1434350318 updated; running /etc/nsd/nsnotifyd/jp2git.sh
nsnotifyd[5117]: example.org refresh at 2015-06-16 15:25:43 +0000
and our repository looks like this:
commit 23278840888ea80785e5c6efef8bdc3c5ec73842
Author: nsnotifyd <nsnotifyd@example.com>
Date: Tue Jun 16 07:25:43 2015 +0000
example.org IN SOA 1434350318
nsnotifyd is perfect for keeping backups of zones, particularly if you update them dynamically.