# Authoritative DNS in General (and with an example with NSD in an Alpine Linux LXC container) # (February 2017) Whereas a **resolving nameserver**, like Unbound, queries other nameservers to construct answers for clients, an **authoritative nameserver** maintains the official records for a zone (e.g. "com.", "example.com."). NSD is an authoritative nameserver. $ dig columbia.edu NAPTR ;; ANSWER SECTION: columbia.edu. 3600 IN NAPTR 1 0 "s" "SIP+D2U" "" _sip._udp.columbia.edu. $ dig _sip._udp.columbia.edu SRV ;; ANSWER SECTION: _sip._udp.columbia.edu. 3600 IN SRV 10 10 5060 lily.cc.columbia.edu. _sip._udp.columbia.edu. 3600 IN SRV 20 10 5060 laurel.cc.columbia.edu. Forward dns maps names to IP addresses. Reverse dns maps IP addresses to names. If we're not responsible for the IP range (e.g. we're hosted on AWS), we don't need a reverse zone file; our hosting company takes care of that. The SOA (Start Of Authority) record defines default values for the zone. ## Set up an NSD server ## ``` # lxc-create -n alpine-ns1 -t alpine -- -r v3.5 # lxc-start -n alpine-ns1 # lxc-attach -n alpine-ns1 # cat << EOF > /root/.profile # When using lxc-attach, do "su -" to trigger a login shell that runs .profile. export PS1='--- \h \w \\$ ' export PAGER='less' alias l='ls' alias ll='ls -lah' alias la='ls -a' EOF # apk update # apk upgrade # apk add nsd man nsd-doc tzdata s6 drill # cp /usr/share/zoneinfo/America/Detroit /etc/localtime # echo 'America/Detroit' > /etc/timezone # apk del tzdata # rc-update add s6-svscan boot # rc-update add nsd boot # cat << 'EOF' >> /etc/hosts 10.100.0.20 alpine-ns1.example.net ns1 EOF # cat << 'EOF' > /etc/hostname alpine-ns1 EOF # cat << 'EOF' > /etc/nsd/nsd.conf server: ip-address: 10.100.0.20 hide-version: yes zone: name: example.net zonefile: example.net.zone zone: name: 0.100.10.example.net zonefile: 0.100.10.example.net.zone EOF # cat << 'EOF' > /etc/nsd/example.net.zone $ORIGIN example.net. $TTL 86400 ; @ IN SOA ns1.example.net. hostmaster.example.net. ( 20170130 ; Serial number we MUST increment each time we change the zone file 28800 ; Wait between refresh attempts by secondary 14400 ; Wait to retry failed zone refresh by secondary 604800 ; Expiration of secondary authority after contact lost with primary 14400 ; How long clients cache NEGATIVE results ) ; @ NS ns1.example.net. @ MX 10 mail.example.net. @ NAPTR 10 100 "s" "SIP+D2U" "" _sip._udp.example.net. @ NAPTR 10 100 "s" "SIP+D2T" "" _sip._tcp.example.net. ; ns1 IN A 10.100.0.20 mail IN A 10.100.0.2 bag IN A 10.100.0.20 gab IN A 10.100.0.99 ; _sip._udp SRV 10 100 5060 bag.example.net. _sip._udp SRV 20 100 5060 gab.example.net. _sip._tcp SRV 10 100 5061 gab.example.net. _sip._tcp SRV 20 100 5061 gab.example.net. EOF # lsof -i :53 ``` ## Using nsd ## Nsd compiles zone info into a binary the database `/var/db/nsd/nsd.db`. In old versions of nsd it was necessary to run `nsdc rebuild` after changing a zone file; nsd 4+ makes this unnecessary. See the man pages nsd(8), nsd.conf(5), nsd-checkconf(8), nsd-control(8), and nsd-checkzone(8). $ nsd-checkconf /etc/nsd/nsd.conf ## Anatomy of a Zone File ## Lines like `$TTL 3600` and `$INCLUDE /foo/example.org.zone` are directives that usually appear at the head of a zone file. The `@` symbol in zonefiles is a placeholder for the _zone root_, which is usually the most recent `$ORIGIN` directive in the zonefile. TTL is the number of seconds a client should consider a name record valid, and after which the client should check again. Any text on a line following a semi-colon is treated as a comment. Zonefiles contain several types of _resource records_. - **A** An "A" record maps an IP address to a name. - **CNAME** A "CNAME" record maps one name to another. - **MX** An "MX" record tells where to deliver mail sent to this zone. An MX record has a _preference value_, indicating order in which clients should try mail servers. - **NS** An "NS" record announces the authoritative nameservers for the zone. The name should be fully qualified. - **PTR** A "PTR" record maps a _last-IP-digit_ to a fully-qualified machine name. Use these for reverse name resolution. - Other types of records include NAPTR, SRV, and TXT records. - **SOA** A Start of Authority record should follow immediately after the directives. It takes this form: ``` @ IN SOA primary-name-server hostmaster-email ( serial-number ; A numerical value incremented whenever the zone file is altered that tells the nameserver to reload the zone time-to-refresh ; How long secondary nameservers wait between asking the primary for a refresh time-to-retry ; How long a secondary nameserver waits before trying another refresh request after the first request went unanswered. time-to-expire ; How long after a secondary nameserver looses contact with the primary before it no longer claims authority. minimum-TTL ) ; How long other nameservers should cache NEGATIVE answers from this zone (max 3H). NB: This is NOT the default TTL for records from the zone; use the $TTL directive for that. east IN A 192.168.200.2 www IN CNAME east.example.com. example.com. IN MX 10 mail-alpha.example.com. @ IN MX 20 mail-bravo.example.com. IN NS ns-1.example.com. IN NS ns-2.example.com. ``` (In the final two records above, the `$ORIGIN` is implicit in the first column. The final four records are functionally equivalent.) https://lists.isc.org/pipermail/bind-users/2000-September/019170.html Regarding a widespread misunderstanding of minimum-TTL in SOA records: > RFC 2308 clarified that the last field of the SOA record is the Negative Caching TTL, not the default or minimum TTL. > That's why BIND 9 requires the presence of a $TTL directive (also specified in RFC 2308), or an explicit TTL on the *first* record in the zone file; otherwise it doesn't know what TTL to use for the record(s). FAILING TO INCREMENT THE SERIAL NUMBER after editing a zone file leads to ZONE UPDATE PROBLEMS. The serial number can be any unique value. Using YYYMMDDv is common, where "v" is a version number in case of multiple update in one day. Note the final dot on the end of some names. If there's a dot at the end of a name in a resource record or directive, the name is _qualified_. If it's the whole name, including the hostname, it's _fully qualified_. If qualified, the nameserver uses the name unchanged. If there's no dot at the end of a name, the nameserver considers it _unqualified_, and **appends the value of the most recent `$ORIGIN` directive**. A reverse name resolution zone file for `10.0.1.0` looks like: $ORIGIN 1.0.10.in-addr.arpa. $TTL 3600 @ IN SOA dns1.example.com. hostmaster.example.com. ( 20170130 ; Serial number we MUST increment each time we change the zone file 28800 ; Wait between refresh attempts by secondary 14400 ; Wait to retry failed zone refresh by secondary 604800 ; Expiration of secondary authority after contact lost with primary 14400 ; How long clients cache NEGATIVE results ) ; @ IN NS dns1.example.com. ; 1 IN PTR dns1.example.com. 2 IN PTR dns2.example.com. It's safest to use fully-qualified names in reverse zone files for the non-reversed names. ## Primary/Master and Secondaries/Slaves ## Run at two (or more) authoritative nameservers to avoid unnecessary outages. One nameserver acts as the primary authority. One or more other nameservers act as secondaries. A secondary requests regular zone updates from the primary nameserver. `/etc/nsd/nsd.conf` on the primary server: server: hide-version: yes key: name: "mykey" algorithm: hmac-sha256 secret: "+a4BkO0Vu69C+Q9bEzMy3TIZVLH+fgT=8" pattern: name: tosecondary notify: 10.100.0.99 mykey provide-xfr: 10.100.0.99 mykey zone: name: example.net zonefile: example.net.zone include-pattern: tosecondary zone: name: 0.100.10.example.net zonefile: 0.100.10.example.net.zone include-pattern: tosecondary `/etc/nsd/nsd.conf` on the secondary server: server: hide-version: yes key: name: "mykey" algorithm: hmac-sha256 secret: "+a4BkO0Vu69C+Q9bEzMy3TIZVLH+fgT=8" pattern: name: fromprimary notify: 10.100.0.99 mykey provide-xfr: 10.100.0.99 mykey zone: name: example.net zonefile: example.net.zone include-pattern: fromprimary zone: name: 0.100.10.example.net zonefile: 0.100.10.example.net.zone include-pattern: fromprimary ## Glue Records and Registrars ## When we delegate a domain like "example.com" from the "com" TLD, we must tell "com" which nameservers are authoritative for "example.com". If the nameservers are part of the domain (e.g. "ns2.example.com"), we must also provide "com" with a **glue record** linking the each nameserver with an IP address (i.e. create an A record for the nameservers on "com"). We create these glue records through the domain name registrar. ## TTL Values ## TTL values are a balance between concerns: - Load on the nameserver (shorter TTL values means more queries --- LONGER TTL's ARE BETTER) - Speed of change distribution (longer TTL values mean changes take longer to propagate --- SHORTER TTL's ARE BETTER) - Vulnerability to cache poisoning (shorter TTL values give more poisoning opportunities --- SHORTER TTL's ARE BETTER) - Long TTL values can reduce the impact of outages, particularly long TTL's for NS records (the impact of some types of outages may be delayed for the length of the TTL --- LONGER TTL's ARE BETTER). A recent analysis of records at 500 popular domains found a mean TTL of 7200 (two hours) and a median TTL of 300 (five minutes); the maximum TTL found was ninety days, the minimum was one second. So, maybe: - Use short TTL's for many A records, especially those likely to change often (five to thirty minutes?). - Use long TTL's for NS, MX, and SOA records (a day or more?). - Use medium TTL's for everything else (one or two hours?). The SOA time-to-expire might well be set to two weeks or more. Zone files traditionally specify TTL values in seconds, but contemporary nameservers also support minutes (M), hours (H), days (D), and weeks (W). Seconds 60 1800 3600 86400 604800 Other Units 1M 30M 1H 1D 1W ## Security of zone transfers between primary and secondary ## TSIG (Transaction SIGnature, defined in RFC 2845) uses shared secret keys and one-way hashing to provide a cryptographically secure means of authenticating updates to a DNS database (i.e. zone transfers). Generate a secret: $ dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64 An algorithm may be specified for the TSIG key. By default, it uses hmac-sha256. The `/etc/nsd/nsd.conf` on the primary (10.0.1.10): server: hide-version: yes key: name: "example.net-tsig" secret: j53z1gs4nCH7P+/ab3JZkqB9HKVg9CDQPhaE2JzDEWo= zone: name: example.net zonefile: example.net.zone notify: 10.0.2.20 example.net-tsig provide-xfr: 10.0.2.20 example.net-tsig The `/etc/nsd/nsd.conf` on the secondary (10.0.2.20): server: hide-version: yes key: name: "example.net-tsig" secret: j53z1gs4nCH7P+/ab3JZkqB9HKVg9CDQPhaE2JzDEWo= zone: name: example.net zonefile: example.net.zone allow-notify: 10.0.1.10 example.net-tsig request-xfr: 10.0.1.10 example.net-tsig ## SRV records ## A SRV record lets DNS return information about services, as defined in RFC 2782. Newer clients of services like SIP and XMPP make significant use of SRV records. SRV records take the form: _service._protocol.domain TTL class SRV priority weight port target _sip._udp.example.com. 300 IN SRV 10 100 5060 sipserver.example.com. - service: symbolic name of service - protocol: protocol of service; usually TCP or UDP - domain: domain name to which this record applies - TTL: time to live - class: always IN - priority: lowest number is most preferred - weight: distribution between records with identical priority - port: service port - target: canonical hostname of box providing the service ## nslookup, dig, drill ## Some platforms switched from the Bind-based dnsutils package to the ldnsutils package. `drill` replaces `dig`, and accepts most of the same arguments. `nslookup` is inferior to `dig` and `drill`. ## Links ## - https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/ch-DNS_Servers.html - https://www.digitalocean.com/community/tutorials/how-to-use-nsd-an-authoritative-only-dns-server-on-ubuntu-14-04 - https://www.vultr.com/docs/running-nsd-and-unbound-on-openbsd-5-6 - https://wiki.alpinelinux.org/wiki/Setting_up_nsd_DNS_server - https://calomel.org/nsd_dns.html - https://en.wikipedia.org/wiki/Zone_file - https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/3/html/Reference_Guide/s1-bind-zone.html - http://www.zytrax.com/books/dns/ch6/mydomain.html - http://stackoverflow.com/questions/14180750/performs-a-naptr-query - https://tools.ietf.org/html/rfc3263 - https://www.nlnetlabs.nl/projects/nsd/documentation.html - https://en.wikipedia.org/wiki/List_of_DNS_record_types - https://www.digitalocean.com/community/tutorials/how-to-set-up-dnssec-on-an-nsd-nameserver-on-ubuntu-14-04 - https://en.wikipedia.org/wiki/TSIG