// vim: set syntax=asciidoc textwidth=75: Dynamic DNS Updates =================== Holger Zuleger, 0.3, 18. May 2021 :lang: en :icons: :data-uri: include::{ldir}/attributes.adoc[] == DNS Overview DNS is a UDP (optionally TCP) based client/server protocol using port 53 on server side. There are mainly four DNS-protocol messages types, each of it related to a dedicated application. [style="arabic"] . DNS Queries (recursive / non-recursive) . Zone transfer, full or incremental . Notify (A SOA query like DNS message) . Usually authenticated DNS updates There are three different types of DNS name server: [style="lowerroman"] . Authoritative name server (ANS) + These are the name servers hosting the content of a DNS domain (+zone+) . Recursive name server (RNS), also called Resolver + These are used in the query process only . Forwarding name server (mostly useless but widespread today) + Out of scope here. == Queries * The DNS query is the most used DNS message. * UDP as transport protocol but also TCP is used, especially if the response packet is larger than the maximum DNS UDP packet size (512 minimum, now adjustable) * Two query types: - recursive - iterative (non-recursive) * Queries are send by - Stub resolvers (clients) as recursive query against recursive name server (RNS) - Resolver (RNS) as non-recursive query against authoritative name servers (ANS) ifdef::backend-html5,backend-xhtml11[image::queries.svg[]] ifndef::backend-html5,backend-xhtml11[] include::queries.a2s[] endif::[] .Stub Resolver query (recursive) against recursive ns ---- $ dig host.hznet.de @rns.hkn.hznet.de | grep -e "^host" -e ";; flags" ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 host.hznet.de. 20776 IN AAAA 2a01:4f8:150:92a9::2 ---- The flags field in the message header shows that this is a query response (+qr+) with recursion desired (+rd+) and recursioan available (+ra+) flag on and DNSSEC validation successfull (+ad+). dig(1) sets the +rd+ bit by default. .Resolver query (non-recursive) against the authoritative ns for the zone ---- $ dig +norec host.hznet.de @ns1.hznet.de | grep -e "^host" -e ";; flags" ;; flags: qr aa ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 host.hznet.de. 21600 IN AAAA 2a01:4f8:150:92a9::2 ---- Here the +rd+ bit is cleared and in the response the +aa+ bit (authoritative answer) is set. .Resolver query (non-recursive) against a ANS *not* responsible for the zone ---- $ dig +norec host.hznet.de @a.nic.de | sed -n -e '/;; flags/p' -e '/^;; AUTH/,/^$/p' ;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 5 ;; AUTHORITY SECTION: hznet.de. 86400 IN NS ns2.hznet.de. hznet.de. 86400 IN NS ns1.hznet.de. hznet.de. 86400 IN NS ns-ext.nlnetlabs.nl. ---- Because this name server is not authoritative for the domain in question, the response has no answer (+ANSWER: 0+) but an authority section. The authority section contains the full qualified domain names (FQDN) of all authoritative name servers for the domain in question. + That's the best information the +de.+ servers are aware of and is called a delegation. In the additional section (not shown here) the IP addresses of the name servers are provided as long as space in the UDP packet is available. == Zone Transfer One authoritative name server per domain is not enough. A second or third or even more name servers are usually configured as authoritative name servers (ANS) for a domain. + But only one of them manages the source file for the zone. * This one is called the ``primary'' ANS. * All other NS are named ``secondary'' ANS. footnote::[Formaly those were called ``Master'' and ``Slave'' server, but this is rather a racism term.] How is the content of a zone synchronized between the authoritative name servers of a zone? ifdef::backend-html5,backend-xhtml11[image::zone-transfer.svg[]] ifndef::backend-html5,backend-xhtml11[] include::zone-transfer.a2s[] endif::backend-html5,backend-xhtml11[] ifdef::false[] ANS NOTIFY (Serial 6) ANS (primary) ---------------------> (secondary) In memory Zone: IXFR (diff 5->6) In memory Zone: SOA 5 .... <------------------> SOA 5 .... horst AAAA 2001:db8::1 horst AAAA 2001:db8::1 ^ | reload Zonefile: SOA 6 ... horst AAAA 2001:db8::2 endif::[] .AXFR To replicate the zone database (a plain text file) to all secondary NS, the second DNS-protocol message format is used: A zone transfer (AXFR). A zone transfer uses TCP as transport protocol, and is initiated by each secondary NS at regular intervals (refresh time). It starts always with a SOA serial number comparison. The SOA serial number is an integer within the header of a zone used for versioning of the zone. .A SOA Record ===== $ dig +noall +answer SOA +multi hkn.hznet.de hkn.hznet.de. 6012 IN SOA ns1.hznet.de. hostmaster.hznet.de. ( 2021051803 ; serial 43200 ; refresh (12 hours) 1800 ; retry (30 minutes) 1209600 ; expire (2 weeks) 900 ; minimum (15 minutes) ) ==== Whenever a change on the primary NS is made on a zone file, the serial number MUST be incremented. A zone transfer to a secondary NS takes place only if the serial number on the primary is higher than the one on the secondary NS. .NOTIFY To speed up the transfer of a zone to the secondaries, the DNS protocol is supplemented by NOTIFY messages (RFC1996) to tell a secondary NS that something has changed on the primary. A Notify message is a bit like a SOA query for a zone, except that the DNS opcode is +NOTIFY+ and that it is send by the authoritative primary server to all secondary servers. The secondary response to the NOTIFY ``query'' with a response to signal that it is informed about the change. The secondary NS initiate than a zone transfer in the same way as the timely triggered zone transfer. .IXFR A second improvement made to the DNS protocol is a partial, so called ``incremental'' zone transfer (IXFR). With IXFR only that part of a zone is transfered to the secondary which has changed between the zone version on the secondary and the one on the primary. The primary holds a journal file to know what has been changed which each version of the zone. All this is needed to speed up the distribution of a zone change to all authoritative name servers, and helps the third kind of DNS protocol messages. == Updates * Dynamic Update (RFC2136) is a mechanism to change the content of a zone via DNS messages. * The destination of a DNS update message is always one of the authorititative NS (usually the master NS) of a zone. * Dynamic updates use UDP or TCP as transport protocol The DNS messages opcode is 5 (UPDATE). * These messages should use some kind of authentication (RFC3007). - Shared Secrets (TSIG HMAC or GSS-TSIG) - Public Keys (SIG0) ifdef::backend-html5,backend-xhtml11[image::dyn-upd.svg[]] ifndef::backend-html5,backend-xhtml11[] include::dyn-upd.a2s[] endif::[] === Policy On the primary server, the zone is configured as dynamic zone and a +update-policy+ directive defines who is allowed to update what kind of resource. .BIND Update policy ==== zone "example.net" { type master; file "example.net.dyn"; max-zone-ttl 43200; <1> serial-update-method date; <2> update-policy { // identity ruletype name types grant ddns-key zonesub ANY ; <3> grant EX.NET krb5-self . A(1) AAAA(3) TXT(2) SSHFP(10) HIP(2) KEY(2) IPSECKEY(2); <4> grant * self . A(1) AAAA(3) TXT(2) SSHFP(10) HIP(2) KEY(2) IPSECKEY(2); <5> }; } ==== <1> The maximum TTL value of the zone <2> Format of the SOA serial number, in this case: +yyyymmddnn+ e.g. `2021052500` <3> The owner of the key "local-ddns" can change any record in the zone and all sub zones <4> Each Kerberos host principal of the realm "EX.NET" can add/del/modify the address, txt and several key resource records <5> The same as above for TSIG HMAC and SIG0 keys Beside a +grant+ permission also a +deny+ configuration is possible to restrict a more general grant. The +self+, +krb-self+ and +ms-self+ rules are almost identical and are used to authenticate hosts via it's TSIG or SIG0 keyname, via it's Kerberos host principal (+host/fqdn@REALM+) or via the Windows machine name (+fqdn$@REALM+). If the ruletype in the grant directive above is changed from +self+ (or +krb5-self+) to +selfsub+ (or +krb5-selfsub+ respectively) than the identiy can also add subdomains of it's name (e.g. +horst.example.net+ can also add an address or key for a name like +int1.host.example.net+). The +zonesub+ directive allows the owner of the key with the name +local-ddns+ to change anything in the zone. The resource records are there to restrict the grant to specific record types. An number in parenthesis restricts the number of records of this type. === Authentication There are primary three authentication mechanism available: . Shared Secret . Public Key . Third party The shared secret method requires the exchange of the key via a secure channel and a configuration of the key on the primary name server and the client as well. The key is defined within the +named.conf+ file with a key directive. .BIND key specification ==== key "ddns-key" { algorithm hmac-sha256; secret "DwyeTCqKBHlSrkuTVphG9cfr8hMvzlDA8q8nPNQB0AE="; }; ==== A copy of this is placed in a file on the system from which +nsupdate+ will be run. The command +ddns-confgen+ generates a `hmac-sha256` key like this one. In case of Public Key authentication the key could be generated with the `dnssec-keygen` command. ---- $ dnssec-keygen -n HOST -T KEY -a RSASHA256 -b 2048 horst.example.net Generating key pair......................+++++ ................................................................+++++ Khorst.example.net.+008+00566 $ ls -l Khorst.example.net.+008+00566.* -rw-rw-r-- 1 hoz hoz 389 Mai 25 18:49 Khorst.example.net.+008+00566.key -rw------- 1 hoz hoz 1776 Mai 25 18:49 Khorst.example.net.+008+00566.private $ cat Khorst.example.net.+008+00566.key horst.example.net. IN KEY 512 3 8 AwEAAd5Oq0T/sOGAc.......ln2bX7tRnlE= ---- Now the public part of the key, the content of the file with extension +.key+ must be placed into the zone in question. The private key is then used by the +nsupdate+ command. Kerberos is a third party authentication system. All hosts and services are added with a key to the Kerberos Key Distribution Center (KDC). The primary name server gets a service principal like +DNS/fqdn@REALm+ and every host a host principal +host/fqdn@REALM+. === Updates To send a update to