The Swede in the middle of Silicon Valley

Sunday, April 5, 2009

Enabling your recursive BIND server to support DNSSEC

So I've been doing some BIND hacking this weekend looking into enabling my recursive BIND instance to do DNSSEC lookups if available.

Since the root-servers today doesn't have native support for DNSSEC DLV (Look-aside Validation) has to be used. ISC provides one of these giving somewhat of a proxying DNSSEC validation.

To enable DNSSEC lookups on your servers the easiest approach is to use dnssec-configure which reconfigures your named.conf with the appropiate variables. To enable, run:
dnssec-configure --dnssec=on --dlv=on -u -b
This will add the following to your config:
options {
...
dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside . trust-anchor dlv.isc.org.;
dnssec-accept-expired yes;
...
}

...
include "/etc/named.dnssec.keys";
Open up /etc/named.dnssec and add the following to enable DLV:
include "/etc/pki/dnssec-keys/dlv/dlv.isc.org.conf";
This includes the DNSKEY of dlv.isc.org which is required to validate lookups towards this server. Unless you include the key lookups will not work. Notice that you may have to shuffle the files around a bit to adopt to your setup.

After you restart named your BIND server will query the DLV server for secure lookups, if you have logging enabled you will be able to see DNSSEC debug records.

As you probably know, when using signed entities keys are refreshed with a set constant of time. The recommended time for a DNSKEY is 1 month. Due to this the key you have present in your dlv.isc.org.conf will become deprecated after 1 month. I decided to solve this by making a perl-script re-creating the dlv-configuration every night to ensure that my server doesn't loose the capability of doing lookups. If DLV is unavailable no recursion will work!

Here's the script:

#!/usr/bin/perl

use IO::File;
use strict;
use warnings;
use Net::DNS;
use Data::Dumper;

my $dlv_file = "/var/named/chroot/etc/pki/dnssec-keys/dlv/dlv.isc.org.conf";

my $res = Net::DNS::Resolver->new(
nameservers => [qw(127.0.0.1)],
recurse => 1,
debug => 0
);

my $dnssec_key = $res->query("dlv.isc.org", 'DNSKEY');

my $dlvconf = new IO::File('<'.$dlv_file);

sub nl2br {
my $t = shift or return;
$t =~ s/([\r\n])/$1/g;
return $t;
}

open FILE, ">".$dlv_file;
print FILE "trusted-keys {\n\n";
print FILE for map {

"dlv.isc.org. ".$_->flags.' '.$_->protocol.' '.$_->algorithm.' "'.nl2br($_->key)."\";\n"

} $dnssec_key->answer;

print FILE "};\n";
close (FILE);

chown 25, 25, $dlv_file;

system("rndc reload");

exit 0;

Add the script to crontab and it will automatically update the DLV key as needed.

No comments: