Announce: NoZone 1.0 – a Bind DNS zone generator

Posted: March 17th, 2013 | Author: | Filed under: Coding Tips, Fedora, Virt Tools | Tags: , , , , | 6 Comments »

My web servers host a number of domains for both personal sites and open source projects, which of course means managing a number of DNS zone files. I use Gandi as my registrar, and they throw in free DNS hosting when you purchase a domain. When you have more than 2-3 domains to manage and want to keep the DNS records consistent across all of them, dealing with the pointy-clicky web form interfaces is really incredibly tedious. Thus I have traditionally hosted my own DNS servers, creating the Bind DNS zone files in emacs. Anyone who has ever used Bind though, will know that its DNS zone file syntax is one of the most horrific formats you can imagine. It is really easy to make silly typos which will screw up your zone in all sorts of fun ways. Keeping the DNS records in sync across domains is also still somewhat tedious.

What I wanted is a simpler, safer configuration file format for defining DNS zones, which can minimise the duplication of data across different domains. There may be tools which do this already, but I fancied writing something myself tailored to my precise use case, so didn’t search for any existing solutions. The result of a couple of evenings hacking efforts is a tool I’m calling NoZone, which now has its first public release, version 1.0. The upstream source is available in a GIT repository

The /etc/nozone.cfg configuration file

The best way to illustrate what NoZone can do, is to simply show a sample configuration file. For reasons of space, I’m cutting out all the comments – the copy that is distributed contains copious comments. In this example, 3 (hypothetical) domain names are being configured, nozone.com, nozone.org which are the public facing domains, and an internal domain for testing purposes qa.nozone.org. All three domains are intended to be configured with the same DNS records, the only difference is that the internal zone (qa.nozone.org) needs to have different IP addresses for its records. For each domain, there will be three physical machines involved, gold, platinum and silver

The first step is to define a zone with all the common parameters specified. Note that this zone isn’t specifying any machine IP addresses, or domain names. It is just referring to the machine names to define an abstract base for the child zones

zones = {
  common = {
    hostmaster = dan-hostmaster

    lifetimes = {
      refresh = 1H
      retry = 15M
      expire = 1W
      negative = 1H
      ttl = 1H
    }

    default = platinum

    mail = {
      mx0 = {
        priority = 10
        machine = gold
      }
      mx1 = {
        priority = 20
        machine = silver
      }
    }

    dns = {
      ns0 = gold
      ns1 = silver
    }

    names = {
      www = platinum
    }

    aliases = {
      db = gold
      backup = silver
    }

    wildcard = platinum
  }

With the common parameters defined, a second zone is defined called “production” which lists the domain names nozone.org and nozone.com and the IP details for the physical machines hosting the domains.

  production = {
    inherits = common

    domains = (
        nozone.org
        nozone.com
    )

    machines = {
      platinum = {
        ipv4 = 12.32.56.1
        ipv6 = 2001:1234:6789::1
      }
      gold = {
        ipv4 = 12.32.56.2
        ipv6 = 2001:1234:6789::2
      }
      silver = {
        ipv4 = 12.32.56.3
        ipv6 = 2001:1234:6789::3
      }
    }
  }

The third zone is used to define the internal qa.nozone.org domain.

  testing = {
    inherits = common

    domains = (
      qa.nozone.org
    )

    machines = {
      platinum = {
        ipv4 = 192.168.1.1
        ipv6 = fc00::1:1
      }
      gold = {
        ipv4 = 192.168.1.2
        ipv6 = fc00::1:2
      }
      silver = {
        ipv4 = 192.168.1.3
        ipv6 = fc00::1:3
      }
    }
  }
}

Generating the Bind DNS zone files

With the /etc/nozone.org configuration file created, the Bind9 DNS zone files can now be generated by invoking the nozone command.

$ nozone

This generates a number of files

# ls /etc/named
nozone.com.conf  nozone.conf  nozone.org.conf  qa.nozone.org.conf
$ ls /var/named/data/
named.run           named.run-20130317  nozone.org.data
named.run-20130315  nozone.com.data     qa.nozone.org.data

The final step is to add one line to /etc/named.conf and then restart bind.

$ echo 'include "/etc/named/nozone.conf";' >> /etc/named.conf
$ systemctl restart named.service

The generated files

The /etc/named/nozone.conf file is always generated and contains references to the conf files for each domain named

include "/etc/named/nozone.com.conf";
include "/etc/named/nozone.org.conf";
include "/etc/named/qa.nozone.org.conf";

Each of these files defines a domain name and links to the zone file definition. For example, nozone.com.conf contains

zone "nozone.com" in {
    type master;
    file "/var/named/data/nozone.com.data";
};

Finally, the interesting data is in the actual zone files, in this case /var/named/data/nozone.com.data

$ORIGIN nozone.com.
$TTL     1H ; queries are cached for this long
@        IN    SOA    ns1    hostmaster (
                           1363531990 ; Date 2013/03/17 14:53:10
                           1H  ; slave queries for refresh this often
                           15M ; slave retries refresh this often after failure
                           1W ; slave expires after this long if not refreshed
                           1H ; errors are cached for this long
         )

; Primary name records for unqualfied domain
@                    IN    A               12.32.56.1 ; Machine platinum
@                    IN    AAAA            2001:1234:6789::1 ; Machine platinum

; DNS server records
@                    IN    NS              ns0
@                    IN    NS              ns1
ns0                  IN    A               12.32.56.2 ; Machine gold
ns0                  IN    AAAA            2001:1234:6789::2 ; Machine gold
ns1                  IN    A               12.32.56.3 ; Machine silver
ns1                  IN    AAAA            2001:1234:6789::3 ; Machine silver

; E-Mail server records
@                    IN    MX       10     mx0
@                    IN    MX       20     mx1
mx0                  IN    A               12.32.56.2 ; Machine gold
mx0                  IN    AAAA            2001:1234:6789::2 ; Machine gold
mx1                  IN    A               12.32.56.3 ; Machine silver
mx1                  IN    AAAA            2001:1234:6789::3 ; Machine silver

; Primary names
gold                 IN    A               12.32.56.2
gold                 IN    AAAA            2001:1234:6789::2
platinum             IN    A               12.32.56.1
platinum             IN    AAAA            2001:1234:6789::1
silver               IN    A               12.32.56.3
silver               IN    AAAA            2001:1234:6789::3

; Extra names
www                  IN    A               12.32.56.1 ; Machine platinum
www                  IN    AAAA            2001:1234:6789::1 ; Machine platinum

; Aliased names
backup               IN    CNAME           silver
db                   IN    CNAME           gold

; Wildcard
*                    IN    A               12.32.56.1 ; Machine platinum
*                    IN    AAAA            2001:1234:6789::1 ; Machine platinum

As of 2 days ago, I’m using nozone to manage the DNS zones for all the domains I own. If it is useful to anyone else, it can be downloaded from CPAN. I’ll likely be submitting it for a Fedora review at some point too.