Catalog zones are specially-formatted DNS zones that allow for easy provisioning of zones to secondary servers. The zones listed in a catalog zone are called member zones, and when a catalog is transferred and loaded on a secondary with support for catalog zones, the secondary creates the member zones automatically. This is a DNS server integral method for provisioning secondary servers without having to manually configure each secondary (even if it is via configuration management). BIND was the first server to support catalog zones, but support for them has meanwhile reached PowerDNS and Knot.

As described in this post, member zones are typically added to the catalog by, say, performing a dynamic update on the catalog. This causes the catalog zone to get its SOA serial number incremented and NOTIFY its secondaries, whereupon they transfer the catalog zone and provision themselves with the member zones, deleting members which have been removed and adding new members.

Knot has a special mode with which the catalog zone can automatically generate its content from configured zones. This is enabled with catalog-role: generate which causes the catalog zone to include member zones which have a catalog-role: member. The members are added to the specified catalog, of which there can be many.

  - id: bind1

  - id: catzonetemplate
    catalog-role: generate
    acl: catalog_transfer

  - id: cmember # catalog member
    catalog-role: member
    catalog-zone: my-catalog
    acl: secondaries_may_transfer

  - domain: my-catalog
    template: catzonetemplate
    notify: [ bind1, bind2, ... ]
    acl: [ catalog_transfer ]

  - domain: a01
    template: cmember

  - domain: a02
    template: cmember

  - domain: b01
    template: other

So the above configuration on a Knot primary provides a catalog zone my-catalog which holds the member zones a01 and a02 but not b01`. (The latter doesn’t have a member catalog-role for our catalog.)

If I transfer the catalog zone from the primary Knot server I see its content:

$ dig @ my-catalog AXFR +noall +answer +onesoa | named-compilezone -q -F text -s relative -o - my-catalog.
$TTL 0  ; 0 seconds
my-catalog              IN SOA  invalid. invalid. (
                                1676734585 ; serial
                                3600       ; refresh (1 hour)
                                600        ; retry (10 minutes)
                                2147483646 ; expire (3550 weeks 5 days 3 hours 14 minutes 6 seconds)
                                0          ; minimum (0 seconds)
                        NS      invalid.
$ORIGIN my-catalog.
version                 TXT     "2"
5ef8e84727fd007d        PTR     a02.
a918f34730f99351        PTR     a01.

The zone’s MNAME, RNAME, and NS are generated as “invalid” which is fine for most purposes, and should we need to modify that we can simply not use the generate function but manage the catalog zone “manually”.

(I was curious as to what Knot uses for the unique member names, as they’re shorter than a SHA-1. If I read the source code correctly, they opted for a SipHash-2-4 keyed with a timestamp.)

The good news for me in a current project is that Knot’s catalog zones are compatible with BIND’s (to be expected), and the automatic member zone addition will make the administrators’ lives easier.