A guide to DNS configuration on servers

Published on Fri 06 April 2012. Filed under . Tags .

I use DNS daemons on my server for two different tasks:

  • to find what names maintained by others point to
  • to publish this mapping for the mtjm.eu. zone

This article aims to explain how these tasks could be done on a small personal server.

DNS servers work in different ways to perform these tasks. Recursive (or caching) servers ask other servers for names and cache the results (the real algorithm is more complex). Authoritative servers get all their answers locally, usually from a file or from data synchronized from other authoritative servers (sometimes called masters, the difference is completely internal).

There are important security, reliability and modularity arguments for using separate recursive and authoritative daemons. The only argument against this known to me is that they need having separate IP addresses, this is not a problem on any machine having both local and public interfaces (and there is no reason to host an authoritative server otherwise). Caches don’t need to and shouldn’t be public.

Unbound recursive server

I use Unbound as a caching server. The default configuration of the package in Parabola GNU/Linux-libre is probably correct, by default it listens on IPv4 and IPv6 localhost addresses.

For other programs to query this daemon, the /etc/resolv.conf file should contain the nameserver 127.0.0.1 line (no other lines are needed). Your network configuration scripts might replace it, a simple and portable way to solve this is to run ‘chattr +i /etc/resolv.conf’ after editing, so no program will change it (without chattr -i).

NSD authoritative server

I use NSD to publish my zone.

The Parabola package includes a foreign rc.d script which makes rc.d not know its status, this is easily solved by using systemd and its nsd.service unit. I haven’t found other problems using it.

This my /etc/nsd/nsd.conf with default comments stripped:

server:
        # These two are the public addresses of the machine running it.
        # The default is to listen on all addresses, which would conflict
        # with Unbound listening on local addresses.
        ip-address: 178.79.140.113
        ip-address: 2a01:7e00::f03c:91ff:fe96:3f65

zone:
        name: "mtjm.eu"
        zonefile: "mtjm.eu.zone"
        # Used to allow zone transfers to secondary server for specific
        # addresses.
        provide-xfr: 216.218.130.2 NOKEY

Writing zone file

The format of zone files is complex and difficult to understand or parse. Somehow most DNS servers use it (djbdns has a much simpler, extensible and somewhat user friendly format).

These are fragments of my zone file, based on various examples found more than a year ago:

$ORIGIN mtjm.eu.     ; designates the start of this zone file in the name space
$TTL 12h                  ; default expiration time of all resource records without their own TTL value
mtjm.eu.  IN  SOA  ns1.he.net. hostmaster.mtjm.eu. (
              2012032801 ; serial number of this zone file
              1d         ; slave refresh (1 day)
              2h         ; slave retry time in case of a problem (2 hours)
              4w         ; slave expiration time (4 weeks)
              1h         ; minimum caching time in case of failed lookups (1 hour)
              )
@      IN NS    ns1.he.net.
       IN NS    ns2.he.net.
       IN NS    ns3.he.net.
       IN NS    ns4.he.net.
       IN NS    ns5.he.net.
; mail
       IN MX    0 elderthing
; WWW
       IN A     178.79.140.113
       IN AAAA  2a01:7e00::f03c:91ff:fe96:3f65
       IN TXT   "v=spf1 ip4:178.79.140.113 ip6:2a01:7e00::f03c:91ff:fe96:3f65 -all"
       IN SPF   "v=spf1 ip4:178.79.140.113 ip6:2a01:7e00::f03c:91ff:fe96:3f65 -all"
; machines
elderthing IN A 178.79.140.113
       IN AAAA  2a01:7e00::f03c:91ff:fe96:3f65
       IN TXT   "v=spf1 ip4:178.79.140.113 ip6:2a01:7e00::f03c:91ff:fe96:3f65 -all"
       IN SPF   "v=spf1 ip4:178.79.140.113 ip6:2a01:7e00::f03c:91ff:fe96:3f65 -all"
; sites on elderthing
b      IN A     178.79.140.113
       IN AAAA  2a01:7e00::f03c:91ff:fe96:3f65
       IN TXT   v=spf1 -all
       IN SPF   v=spf1 -all
; some other sites ommitted
; XMPP
_jabber._tcp IN SRV 0 0 5269 elderthing.mtjm.eu.
       IN TXT   v=spf1 -all
       IN SPF   v=spf1 -all
_xmpp-client._tcp IN SRV 0 0 5222 elderthing.mtjm.eu.
       IN TXT   v=spf1 -all
       IN SPF   v=spf1 -all
_xmpp-server._tcp IN SRV 0 0 5269 elderthing.mtjm.eu.
       IN TXT   v=spf1 -all
       IN SPF   v=spf1 -all

The SOA record has various numbers to make synchronizing zones with secondary servers harder. The secondary servers are provided by the gratis Hurricane Electric DNS service, they have all features that I need (e.g. IPv6 support) and I haven’t observed any problems with them.

The A and AAAA records specify IPv4 and IPv6 addresses of various machines. DNS supports CNAME aliases which shouldn’t be used (that page lists many other problems with DNS design or implementation).

The TXT and SPF records show that most of my records aren’t used in email envelope sender addresses and the other ones are used only for mail sent by elderthing. If enough domains and mail servers used these records, spammers would need to buy their own domains and not forge their sender addresses.

The SRV records here just specify that elderthing provides all XMPP services. They are much more powerful than that.

Run nsdc rebuild && nsdc reload after changing the zone file.

Useful changes not described here

DNS has big security problems and introducing more secure replacements is difficult. Some of these problems can be optionally solved by DNSSEC or DNSCurve (each of them solves different problems). I have no experience with these specifications nor how they could be used.