DNS Security I : Dynamic Updates
Originally published in SysAdmin Magazine, September 2004Contents
IntroductionSecure Dynamic Updates
TSIG-secured zone transfers
DHCP Dynamic Updates
Conclusion
References
Introduction
Of all of the many network protocols we use in computer networking, DNS is one of the most fundamental and important. The task of mapping domain names to IP addresses seems simple, and at first approach it is. However, issues arise when that protocol becomes extensively trusted by systems. Packets within the DNS protocol are all sent as clear text which means that they can be easily read and modified while in transit. DNS uses the UDP protocol which has no handshaking between clients and servers and is therefore quite susceptible to spoofing attacks. We no longer have a trusted Internet in which we can trust insecure services - there are malicious attackers that will do their very best to make users go to spoofed banking sites, to swamp everyone with spam, and generally wreak havoc. This article is the first of two in which I will be looking at the use of cryptographic methods to secure DNS. In this article I will be covering secure dynamic updates and zone transfers using TSIG keys, in the second article I will cover the DNSSEC protocols for securing zone data. In the examples below, I'm using an installed copy of ISC BIND version 9.3.0rc2 from www.isc.org, which has been setup to serve a test domain "domain.tld", and a reverse domain "1.168.192.in-addr.arpa". I won't cover the installation of the BIND software here, but it is quite straightforward. Note that you will need to add the "--with-openssl" option to the ./configure command if you want to use the DNSSEC functionality.Secure Dynamic Updates
Using dynamic updates is a great way of maintaining your DNS zone data. With some knowledge and a bit of practice you will probably find it easier and less mistake-prone than the old-fashioned way of editing zone files ( don't forget to update that serial number! ). Enabling dynamic updates is easy, but care must be taken to make sure it is secure. While you can restrict updates by their originating IP address this approach is not very secure at all because updates use UDP which is quite easily spoofed. The better method is by signing the updates with Transaction Signature ( TSIG ) keys and permitting only updates with authorized keys. Keys are simply base-64 encoded random data which is shared by the DNS server and the client system sending updates. To generate a key for updates, use the dnssec-keygen command :dnssec-keygen -a HMAC-MD5 -b 512 -n HOST update_keythis generates a 512-bit key with the HMAC-MD5 algorithm, and places the result into 2 files : Kupdate_key.+157+59571.key and Kupdate_key.+157+59571.private for the public and private key data. The numbers in the key file name are for the key algorithm ( 157 for HMAC-MD5 ) and a 5-digit random key identifier ( which will be different on your system ). Store both key files in /var/named or wherever you keep DNS zone files on your DNS server. Now, configure your DNS server to accept updates signed with this key, edit /etc/named.conf, and add the definition for the key :
key update_key {
algorithm HMAC-MD5;
secret "fxT7q+Kq8TUmZrN4edxAVeTeOmiX/3A6HQ40HcyI...g==";
};
where the secret string is extracted from the private key file ( it
has been truncated in this example ). You won't be able to include the
key file directly into the named.conf file ( with the 'include'
statement ) because the key files generated by dnssec-keygen are
formatted to be included into zone files and the syntax is different
to what the configuration file uses. Now, edit /etc/named.conf and
configure a zone to receive updates with this key, edit your zone
definition and add an allow-update option:
zone "domain.tld" IN {
type master;
file "domain.tld";
allow-update { key update_key; };
};
don't forget the reverse zone as well :
zone "1.168.192.in-addr.arpa" IN {
type master;
file "1.168.192.in-addr.arpa";
allow-update { key update_key; };
};
you can add a finer-grained level of control with the update-policy
option, for example:
zone "1.168.192.in-addr.arpa" IN {
type master;
file "1.168.192.in-addr.arpa";
update-policy { grant update_key name * A; };
};
this would grant changes to A ( Address ) records only for requests
signed with the update_key key.
Now, restart you DNS server, check the syslog for any errors, and test
the updates from the command line:
/usr/local/bin/nsupdate -k Kupdate_key.+157+59751.key <this example sends a single update to add an A record into the domain.tld zone. You can use either 'nslookup', 'dig' or the 'host' commands to check that the update has been made. The DNS server will also log an entry in syslog recording the update. Naturally, we like to use perl to get the job done efficiently. Using the Net::DNS package, we can use perl to perform updates:
#!/usr/bin/perl -w
use Net::DNS;
use strict;
my $key_name = 'update_key';
my $key = 'fxT7q+Kq8TUmZrN4edxAVeTeOmiX/3A6HQ40HcyI...g==';
# Create the update packet.
my $update = Net::DNS::Update->new('domain.tld');
# Add a TXT record to the domain
$update->push(update => rr_add('testrec.domain.tld 86400 IN TXT "A test record"'));
# Send the update to the zone's primary master.
my $res = Net::DNS::Resolver->new;
$res->nameservers('192.168.1.3');
# Sign the update message
$update->sign_tsig($key_name, $key);
my $reply = $res->send($update);
# Check return code
if ($reply) {
if ($reply->header->rcode eq 'NOERROR' ) {
print "Update succeeded\n";
} else {
print 'Update failed ', $reply->header->rcode, "\n";
}
} else {
print 'Update failed', $res->errorstring, "\n";
}
this example creates a new TXT record called
"testrec.domain.tld". Note that we can make multiple updates within a
single request packet - they can even include multiple add and delete
operations, but only if they are all under the same domain. Also note
that dynamic updates simply increment the zone serial number in the
SOA record, it doesn't maintain the YYYYMMDD sort of format often
used for serial numbers.
Also be aware that once you start using dynamic updates, you can't
really use manual editing of the zones anymore. The BIND server
maintains journal files which contain a record of dynamic updates and
these need to be taken into account. If you do need to edit a zone
manually, the only way is to shut down the DNS server, remove the zone
journal ( .jnl ) file, edit the zone, and start the server again.
TSIG-secured zone transfers
Its also very useful to secure the transfers of zone data between master and slave DNS servers. This is particularly relevant if the transfers are taking place across untrusted networks such as the public Internet. As mentioned before, the data being transferred is all in plain-text and contains no checking mechanism, so there is a risk of data corruption or malicious interference of the data being transferred. We can easily use TSIG keys to sign the zone transfer data. Firstly, generate a key to be used for zone transfers. This should not be the same as the key you created for dynamic updates. You could create a separate key for each slave server, but in the examples below I've created a single key for all slaves. Generate a new key on the master, named "slave_xfers_key":dnssec-keygen -r /dev/urandom -a HMAC-MD5 -b 128 -n HOST slave_xfers_keycopy the key data string from the created key file into /etc/named.conf on the master server:
key slave_xfers_key {
algorithm HMAC-MD5;
secret "mv0NxiVT4ho/TZbvPID+Kg==";
};
and permit zone transfers on the master server for clients with the
key by adding allow-transfer statements in /etc/named.conf:
zone "domain.tld" IN {
type master;
file "domain.tld";
allow-update { key update_key; };
allow-transfer { key slave_xfers_key; };
};
zone "1.168.192.in-addr.arpa" IN {
type master;
file "1.168.192.in-addr.arpa";
allow-update { key update_key; };
allow-transfer { key slave_xfers_key; };
};
now restart the master server and check there are no errors in the
syslog ( it is quite easy to forget those semicolons in named.conf
files! ).
On the slave server, configure the same key for the zone in
/etc/named.conf:
key slave_xfers_key {
algorithm HMAC-MD5;
secret "mv0NxiVT4ho/TZbvPID+Kg==";
};
and add a "server" statement which will specify the TSIG key which
this slave will use when communicating to the specified server:
server 192.168.1.3 {
keys { slave_xfers_key; };
};
the definitions for the slave zones stay the same, there is no need to
configure the key in them. The slave server will automatically use the
TSIG key when requesting a transfer of any zone from the master server
whose IP address was specified in the server statement.
Now, restart the slave server, and check syslog for errors. If the
TSIG-secured zone transfer is successful you should see the following
syslog messages on the slave server :
named[3733]: zone domain.tld/IN: Transfer started. named[3733]: transfer of 'domain.tld/IN' from 192.168.1.3#53: connected using 192.168.1.2#32835 named[3733]: zone domain.tld/IN: transferred serial 1: TSIG 'slave_xfers_key' named[3733]: transfer of 'domain.tld/IN' from 192.168.1.3#53: end of transfer... and similar messages on the master server describing the transfer of the zone using the slave_xfers_key TSIG key.
DHCP dynamic updates
DHCP servers can also send dynamic updates to DNS servers as they allocate IP addresses to clients, and naturally you will want to secure these updates with TSIG signatures. This is relatively easy to configure when using ISC's DHCPD server as follows. In this scenario, we have a client device ( such as a laptop ) which wants to connect to networks and be allocated an IP address ( otherwise known as a DHCP lease ). The client would also like to choose its own host name on the network to be inserted into DNS. In this example I'll configure my linux-based laptop to have the name "gorgon" allocated to it when it connects to networks with a DHCP server and dynamic DNS updates which permit client elected names. There is 3 steps we need to take to achieve this:- Step 1 : configure the DHCP server and DNS server to use TSIG dynamic updates
- Step 2 : configure the DHCP server to update the DNS server each time a lease is let for the subnet
- Step 3 : configure the DHCP client to give the DHCP server a domain name to insert into DNS
key update_key {
algorithm HMAC-MD5;
secret "fxT7q+Kq8TUmZrN4edxAVeTeOmiX/3A6HQ40HcyI...g==";
}
zone 1.168.192.in-addr.arpa {
key update_key;
primary 192.168.1.3;
}
zone domain.tld {
key update_key;
primary 192.168.1.3;
}
ddns-updates on;
ddns-update-style interim;
allow client-updates;
Step 2. when the DHCP server leases an address for a subnet, instruct
it to also send a DNS update, in /etc/dhcpd.conf we add a couple of
lines to the subnet statement:
subnet 192.168.1.0 netmask 255.255.255.0 {
option domain-name "domain.tld";
option domain-name-servers 192.168.1.3;
option routers 192.168.1.1;
range 192.168.1.20 192.168.1.254;
# Dynamic DNS updates:
ddns-domainname "domain.tld";
ddns-rev-domainname "1.168.192.in-addr.arpa";
}
Step 3. Configure the DHCP-enabled clients to send their names to the
DHCP server. Most Windows clients seem to do this automatically, but
some *nix DHCP clients need configuration. For those using the ISC
DHCP client software, this is in /etc/dhclient.conf and should look
like the following example:
send host-name "gorgon";
send fqdn.fqdn "gorgon.domain.tld.";
send fqdn.encoded on;
send fqdn.server-update on;
Once the DHCP server has been restarted, and the client requests a
DHCP lease, the server should send a TSIG signed dynamic DNS update to
the master DNS server to add the name of the client as an A record,
and the reverse PTR record.
There is a number of ways of integrating DHCP and dynamic DNS. An
alternative to the above could be to have the clients call a script
after they get a DHCP lease and use nsupdate to send the updates
themselves. In this case each client would need a TSIG key in order to
secure the update packets.
Conclusion
In this article I've shown the reader how to set up and use TSIG-signed DNS updates, TSIG secured zone transfers, and TSIG secured dynamic updates from a DHCP server. In the next article on DNS Security Protocols I will look at DNSSEC secured zones where the actual zone resource records are signed with cryptographic keys. This is used to ensure that the query from a DNS client are valid and come from the true server for the domain.References
Secure Dynamic DNS HOWTOhttp://ops.ietf.org/dns/dynupd/secure-ddns-howto.html Dynamic DNS updates with isc-dhcpd
http://tinyurl.com/6lssd BIND v9 ARM ( Administrators Reference Manual )
http://www.nominum.com/content/documents/bind9arm.pdf DNSSEC Operations HOWTO
http://www.ripe.net/disi/Course/TechCourse.pdf Nominum DNSSEC FAQ
http://www.nominum.com/getOpenSourceResource.php?id=8
