Binding hosts to IP-addresses
© 2013 Dennis Leeuw dleeuw at made-it dot com
License: GPLv2 or later
With the introduction of Dynamic DNS, it became possible to tie a DHCP-server to DNS. When the DCHP server hands out an IP-address to a host it can immediately tell the DNS server about it. This is probably the most common use for Dynamic DNS. I needed a way to configure printer SRV and other Zeroconf records in DNS, based on the configuration in CUPS, to be able to that in a safe way, I used Dynamic DNS. This document reflects the stuff I discovered in the process of writing das_dns.
The generic procedure to create a safe Dynamic DNS setup is:
There are several ways to dynamically update DNS, one way is by creating TSIG (Transaction Signature) keys. Based on on these keys a certain process (nsupdate or dhcpd) is allowed to make changes in the DNS server.
To be absolute certain the key that you will later on place in your DNS configuration works with the key that is used by your application, create the key on the system the application is running on. So for DHCP, create the key on the system dhcpd is running on. I found it easiest to store the keys I need in the configuration directory of the application. So my dhcpd keys are placed in /etc/dhcpd/.
cd into the directory where you want your keys to be located, we will start creating our keys shortly, but first a bit about bits. You can create different keys with different lengths. For HMAC-MD5 the maximum key size is 512 bits. Of course you could choose to use other keys like, RSAMD5 / RSASHA1 keys (512-2048 bits), Diffie Hellman keys (128-4096 bits), DSA keys (512-1024 bits, in a multiple of 64). RFC-2535 says that the implementation of DSA is mandatory and HMAC-MD5 is recommended. For our example HMAC-MD5 will do:
# dnssec-keygen -a HMAC-MD5 -b 512 -T KEY -n HOST bofh.example.com. Kbofh.example.com.+157+01559 # chmod 400 Kbofh.example.com.*The -T KEY (this used to be the -k option and on most systems that still is) creates a KEY record instead of a DNSKEY record, which is what is needed for the -n HOST option. The -n option is in the above command set for HOST meaning a host key is generated. The available options are:
The key needed to be included in our DNS configuration is available in the .private file.
# cat Kbofh.example.com.+157+01559.private
On you DNS server add to named.conf the key(s) that should be available to the zones, for our example host the entry would look like this:
key bofh.example.com. { algorithm "HMAC-MD5"; secret "BOMH6IihALdh4ksRI0drbXw/q1MQILI+5a8qO2XNynIR9yiY7js5bBP31zySbrp3omiPIq3KsqsBtk0hogfnXg=="; };The name after the key can be anything. Just create a string that you can easily remember, or has some logic with the key you created.
The allow-update statement can be set as a zone, view or global option. The following example is a zone setting:
zone example.com { type master; file "zones/com/example.zone"; allow-update { # Allow updates by key key bofh.example.com.; # Allow updates by IP 192.168.1.5; }; }; zone 168.192.in-addr.arpa. { type master; notify no; file "zones/192/168.zone"; allow-update { # Allow updates by key key bofh.example.com.; # Allow updates by IP 192.168.1.5; }; }Now anyone with the key described in bofh.example.com. is allowed to change almost all fields in the zone file.
With update-policy one can create a list of rules defining what is and what is not allowed during dynamic updates. The rules are checked from top to bottom for a match. As soon as a rule matches that one is performed and further checking is skipped.
When you use update-policy you may not use allow-update, and update-policy is only useful in the master zone.
The generic format of the policy rule looks like this:
( grant | deny ) identity nametype name [ types ]As you probably expected you can create grant and deny rules, allowing or disallowing certain access. Based on the combination of identity, nametype, and name access to certain types can be controlled.
Value | Description | |
---|---|---|
self | Matches when the name to be updated exactly matches the identity. The name field is ignored. | |
selfsub | Matches when the name to be updated exactly matches or is a subdomain of identity. | |
selfwild | Matches when the name to be updated is a subdomain of identity. | |
name | Matches when the to be updated name is the same as the name in the name field, so only that record can be updated by identity. E.g. host.example.com. | |
subdomain | Matches when the to be updated name is a subdomain of the name in the name field (which includes the name itself). E.g. If name is example.com., then host1.example.com and host2.example.com both match. | |
zonesub | Is the same as subdomain, except that a name field is not needed. It assumes that for name the name of zone (and its subdomains) in which it is configured is meant. | |
wildcard | Matches when the to be updated name is a valid expansion of the wildcard name in the name field. The name field must thus contain a wildcard. | |
tcp-self | allow updates sent via TCP for which the updater's source IP address maps into a corresponding in-addr.arpa or ip6.arpa domain [subtree] being updated. | |
krb5-self | The name should contain a Kerberos principal (host/machine@REALM). This is checked against the REALM provided by identity. Which then allows (or not) the change of machine.realm | |
krb5-subdomain | The name should contain a kerberos principal (host/machine@REALM). This is checked against the REALM provided by identity. Which then allows (or not) the change of subdomains of machine.realm | |
ms-self | The name should contain a Windows machine principal (machine$@REALM). This is checked against the REALM provided by identity. Which then allows (or not) the change of machine.realm | |
ms-subdomain | The name should contain a Windows machine principal (machine$@REALM). This is checked against the REALM provided by identity. Which then allows (or not) the change of subdomains of machine.realm | |
6to4self | allow updates to the 6to4 prefix by a TCP connection from the 6to4 network or corresponding IPv4 address mapped into the 6to4 address (intended to allow NS or DNAME RR updates) |
update-policy { deny host-key name ns1.example.com. A; grant zone-key subdomain example.com. ANY; grant EXAMPLE.COM krb5-self * A PTR; grant wild-key wildcard *.example.com.; grant ipp.example.com. subdomain _ipp._tcp.example.com. SRV; };
echo "server ns1.example.com. zone example.com. update add mynewhost.example.com. 86400 A 192.168.1.42" | nsupdate -k Kbofh.example.com.+157+01559.private
FIXME: to do