Catalog zones in BIND 9.11 You know the drill: you provision a server with a master zone, and then you have to hop over to all secondary servers and add the slave zone to their configuration. You probably do that with some form of automation, or you use something slightly convoluted like what we've discussed previously in [1]automatic provisioning of slave DNS servers. If your master and slave servers are [2]BIND, you're in luck: catalog zones will automate this for you within the BIND code itself: there'll no longer be a need for "hacking" this to accomplish automatic provisioning of slave BIND servers. Catalog zones [3]are scheduled for release in BIND 9.11, but [4]Evan Hunt graciously let me have a peek at a preview of the code, and I must warn you: first, this is a work in progres and hasn't been released yet, and second (and more importantly) what I'm going to show you is the little I know of catalog zones. Be warned on both accounts! Update: Catalog zones are now in [5]BIND 9.11.0a3. Catalog zones are based on an Internet-Draft called [6]draft-muks-dnsop-dns-catalog-zones-01, updated in [7]draft-toorop-dnsop-dns-catalog-zones-01, which describes a method for automatic synchronization of zones among primary and secondary servers. The way this is works is that a zone contains the names (and optional metadata) describing which zones are to be used on slave (secondary) servers; these zone names in a catalog are called member zones. The secondary server obtains a copy of this catalog (via zone transfer (AXFR/IXFR)) and uses it to update the internal catalog of zones it ought to have; once it detects a change, it adds and slaves the member zone or deletes it, depending on whether the member zone was added or removed. More concisely: we add one or more member zones to the catalog zone which is transferred to its slaves where it triggers the creation (or removal) of the member zones. Catalog zones Let's see how this works in practice with a preliminary copy of [8]BIND which supports this. Primary and secondary servers On my primary test server, I add the following to named.conf: options { directory "/etc/namedb"; ... server-id "authoritative"; allow-new-zones yes; }; zone "catalog.example.com" { type master; file "catalog.example.com.db"; also-notify { 192.168.1.189; }; notify explicit; }; Pay attention to the [9]allow-new-zones directive. The catalog zone proper is mostly empty: mname, rname and NS are irrelevant, and the relative version label specifies the catalog zone format version ([10]currently "2"): $TTL 3600 @ IN SOA . . 1 86400 3600 86400 3600 @ IN NS nop. version IN TXT "2" On a secondary (192.168.1.189) I have the following configuration: options { directory "/etc/namedb"; ... masterfile-format text; zone-statistics yes; server-id "slave"; allow-new-zones yes; catalog-zones { zone "catalog.example.com" zone-directory "cat-zones" in-memory no default-masters { 192.168.1.188; }; }; }; zone "catalog.example.com" { type slave; file "catalog.example.com.db"; masters { 192.168.1.188; }; }; Here we also add allow-new-zones so that the secondary can create member zones on the fly, and we use the new catalog-zones stanza to define the primary server which holds our catalog. The default-masters statement in the catalog-zones stanza defines the default masters for its member zones. The optional zone-directory in "catalog-zones" allows master files for slaves provisioned by catalog zones to be stored in a directory other than the server's working directory. If in-memory is set to yes, local copies of master files on slaves will be stored in memory only and not on the file system. Adding a new member zone On the primary server I add a new zone, either dynamically with rndc addzone or manually; I'll use the former: $ rndc addzone example.org '{type master; file "example.org";};' $ dig +short @127.0.0.1 example.org soa localhost. root.localhost. 22 10800 3600 604800 3600 From this point onwards, my primary server is ready to serve this master zone, but I want the secondary to serve the zone as well. Here's what I do: 1. I create a hash of a value. Basically any value should do, but it must currently be a valid BIND "nzf" hash. (The pre-alpha code I have does a little oops if it isn't - I'm reporting that as we speak.) ISC is considering loosening this rule to allow me to use any label I wish to, but for interoperability with possible future implementations which comply with the draft, the hash is preferable. 2. I then add a record to the catalog zone in which I name the member zone, bump its serial and reload the zone. #!/usr/bin/env python import dns.name # pip install dnspython import hashlib import sys print(hashlib.sha1(dns.name.from_text(sys.argv[1]).to_wire()).hexdiges t()) I run the above (thanks Witold!) to create the hash: $ ./nzf.py example.org 47ac1a4d93b61fffdb4762c18c9e7d1a6b046d33 Another way of creating the hash (thanks, [11]Peter) is: $ printf '\7example\3org\0' | openssl sha1 47ac1a4d93b61fffdb4762c18c9e7d1a6b046d33 I've dropped a slightly more useful Python program [12]here. I now use that hash for step 2 and add a record containing the member zone: @ 3600 SOA . . 2 86400 3600 86400 3600 @ 3600 IN NS nop. 47ac1a4d93b61fffdb4762c18c9e7d1a6b046d33.zones PTR example.o rg. When I reload named on the primary (rndc reload), I watch the transfer logs; they look very promising: xfer-out: info: client 192.168.1.189#33213 (catalog.example.com): tran sfer of 'catalog.example.com/IN': AXFR-style IXFR started (serial 2) xfer-out: info: client 192.168.1.189#33213 (catalog.example.com): tran sfer of 'catalog.example.com/IN': AXFR-style IXFR ended xfer-out: info: client 192.168.1.189#45095 (example.org): transfer of 'example.org/IN': AXFR started (serial 22) xfer-out: info: client 192.168.1.189#45095 (example.org): transfer of 'example.org/IN': AXFR ended Note how first the catalog zone was transferred, and then our new example.org zone. So, what's on the secondary? $ ls -l /etc/namedb/cat-zones -rw-r--r-- 1 root root 316 Jun 2 13:33 __catz__catalog.example.com_e xample.org.db The __catz__* file contains a copy of the slaved zone. If I delete a member zone record from the catalog the process is reversed, and the secondaries remove the zone completely: catz: updating catalog zone 'catalog.example.com' with serial 3 catz: deleting zone 'example.org' from catalog 'catalog.example.com' - success catz: catz_delzone_taskaction: zone 'example.org' deleted Metadata BIND can use metadata on a zone which is transferred with the catalog: for example different master servers for a particular zone. This allows us to add a member zone to the catalog, which is configured with different master servers. So, on my primary server, I can add the following to the catalog: the first record specifies a member zone, and the second record the master(s) for that zone. 45414dc99ae20a84507692de578c0dd9d2522134.zones IN PTR ww.men s.de. masters.45414dc99ae20a84507692de578c0dd9d2522134.zones IN A 192.168. 1.130 When the secondaries get the catalog, this member zone is created and configured to obtain a copy of its data from the specified master server. Another interesting feature is the possibility of setting ACLs on particular member zones within the catalog. This is done using [13]Address Prefix Lists (RFC 3123): allow-transfer.45414dc99ae20a84507692de578c0dd9d2522134.zones IN APL 1:192.168.1.189/32 1:192.168.1.206/32 The above example would allow transfers from the two addresses only. Catalog zones may also carry TSIG signatures for member zones; this is described in the BIND ARM. Closing It goes without saying (so why am I?) that the catalog zone can be [14]dynamically updated of course; this makes provisioning easy and ensures the SOA serial number is bumped. We should probably all wish for other Open Source DNS server implementations to embrace catalog zones and add support for them in order to increase interoperability between DNS server software brands. Updates: * [15]Peter van Dijk has created a [16]proof of concept implementation which supports catalog zones in PowerDNS. * In [17]a short introduction to Catalog Zones ISC talks about catz and demonstrates two small Python programs to add and delete zones programatically. References 1. http://jpmens.net/2013/02/13/automatic-provisioning-of-slave-dns-servers/ 2. https://www.isc.org/bind/ 3. https://www.isc.org/events/bind-9-11-0-final-release-planned-date/ 4. https://mastodon.social/@nuthaven@noc.social 5. https://lists.isc.org/pipermail/bind-announce/2016-June/000991.html 6. https://tools.ietf.org/html/draft-muks-dnsop-dns-catalog-zones-01 7. https://tools.ietf.org/html/draft-toorop-dnsop-dns-catalog-zones-01 8. https://www.isc.org/bind/ 9. http://jpmens.net/2010/10/04/dynamically-add-zones-to-bind-with-rndc-addzone/ 10. https://tools.ietf.org/html/draft-ietf-dnsop-dns-catalog-zones-00 11. https://twitter.com/habbie 12. https://gist.github.com/jpmens/3aac1fcedb788f43deb8ed36ccf75443 13. https://tools.ietf.org/html/rfc3123 14. http://jpmens.net/2011/10/13/dynamically-or-not-dynamically-that-is-the-question/ 15. https://twitter.com/habbie 16. https://github.com/PowerDNS/powercatz 17. https://kb.isc.org/docs/aa-01401