DNSSEC

From SixXS Wiki
Jump to: navigation, search

SixXS allows you to sign your reverse zones with DNSSEC, utilizing DLV from ISC anchor.

Once you have zones signed and updated across primary/secondary servers, you can add delegate record to reverse zone.

Howto: Signing your zones with LDNS toolkit

!!! NOTE: When using DNSSEC domain case does matter: zone in uppercase will not pass some validators (i.e. dlv.isc.org) which are using canonical (lowercase) names. !!!

Signing script

Below script can be used to simplify zone signing or to understand the process:

#!/bin/bash

# Input parameters
ZONE=$1
FILE=$2
# Ok, but I'm always using $ORIGIN at the beginning of the zone, so why bother
if [ -z $FILE ]
then
       FILE=$ZONE
       ZONE=$(head -5 $FILE | awk '/^\$ORIGIN /{print$2}' | sed 's/\.$//')
fi

# Checking existing keys - keys should be at least one year old
KSK=$(find . -name "K$ZONE.+0*+*.key" -mtime -365 -exec grep -q ksk \{} \; -printf '%T@ %f\n' | sort -rn | head -1 | sed 's/[0-9.]\+ //;s/.key$//')
ZSK=$(find . -name "K$ZONE.+0*+*.key" -mtime -365 -exec grep -q zsk \{} \; -printf '%T@ %f\n' | sort -rn | head -1 | sed 's/[0-9.]\+ //;s/.key$//')

# If there're no suitable keys
if [ "x" = "x$KSK" -o "x" = "x$ZSK" ]
then
       # Generating new keys
       echo "No valid keys found, generating new set for $ZONE"
       KSK=$(ldns-keygen -a ECDSAP256SHA256 -k $ZONE)
       ZSK=$(ldns-keygen -a ECDSAP256SHA256    $ZONE)
       # Adding keys to zone
       echo "Adding keys to zone file $FILE"
       echo "\$INCLUDE \"$PWD/$KSK.key\"" >> $FILE
       echo "\$INCLUDE \"$PWD/$ZSK.key\"" >> $FILE

       # Calculating expiration date
       EXP=$(date '+%Y%m%d' -d 'next year + 5 day')
else
       echo "Found existing keys $KSK & $ZSK, proceeding"
       # Key file mtime in secs since epoch + number of seconds in 370 days
       EXP=$( date '+%Y%m%d' -d  @$(( `stat -c '%Y' $KSK.key` + 31968000 )) )
       #EXP=$( date '+%Y%m%d' -d  @$(( `stat -c '%Y' $KSK.key` + 31643326 )) )
fi
# Checking serial: Unsigned zone should have comment '; serial' next to serial
# Signed zone will have SOA in one line with full spec (name class type params)
OLDSER=$( awk '/[ \t]+IN[ \t]+SOA[ \t]+/{print$7}' $FILE.signed 2>/dev/null )
SERIAL=$( awk '/; serial/{print$1}' $FILE )

# !!! TODO:We're not following RFC 1982 to check wraps !!!
if [ $(( $OLDSER + 0 )) -ge $SERIAL ]
then
       # Incrementing zone's serial
       echo "Adjusting zone's serial"
       NEWSER=$(( $SERIAL + 1 ))
       sed -i "/; serial/s/$SERIAL/$NEWSER/" $FILE
fi
# Signing zone
# !!! TODO: We're not doing key rollover here, just re-signing with new keys !!!
echo "Signing zone file $FILE with keys $KSK & $ZSK untill $EXP"
ldns-signzone $FILE $KSK $ZSK -n -e $EXP

Signing Makefile

The below Makefile is created for NSD daemon, however it should not be difficult to adopt it for other daemons.

BINHOME=$(PWD)
BINPROG=sh $(BINHOME)/dnsec
DNSHOME=/etc/nsd
ZONES:=$(wildcard $(DNSHOME)/*.signed)
VPATH=$(DNSHOME)
NSDC=nsd-control

all: /var/lib/nsd/nsd.db

/var/lib/nsd/nsd.db: $(ZONES)
       $(NSDC) reload
       $(NSDC) notify

%.zone.signed: %.zone
       $(BINPROG) $?

Putting everything together

root@ruff:~/dnssec# make
sh ~/dnssec/dnsec /etc/nsd3/2001.db8.1f15.1b0a.rev.zone
Found existing keys Ka.0.b.1.5.1.f.1.8.b.d.0.1.0.0.2.ip6.arpa.+007+09693 & Ka.0.b.1.5.1.f.1.8.b.d.0.1.0.0.2.ip6.arpa.+007+08819, proceeding
Adjusting zone's serial
Signing zone file /etc/nsd3/2001.db8.1f15.1b0a.he.rev.zone with keys Ka.0.b.1.5.1.f.1.8.b.d.0.1.0.0.2.ip6.arpa.+007+09693 & Ka.0.b.1.5.1.f.1.8.b.d.0.1.0.0.2.ip6.arpa.+007+08819 until 20120710
sh ~/dnssec/dnsec /etc/nsd3/2001.db8.ff6d.rev.zone
Found existing keys Kd.6.f.f.8.b.d.0.1.0.0.2.ip6.arpa.+007+23370 & Kd.6.f.f.8.b.d.0.1.0.0.2.ip6.arpa.+007+48407, proceeding
Adjusting zone's serial
Signing zone file /etc/nsd3/2001.db8.ff6d.rev.zone with keys Kd.6.f.f.8.b.d.0.1.0.0.2.ip6.arpa.+007+23370 & Kd.6.f.f.8.b.d.0.1.0.0.2.ip6.arpa.+007+48407 until 20120710
sh ~/dnssec/dnsec /etc/nsd3/example.com.zone
Found existing keys Kexample.com.+007+21303 & Kexample.com.+007+13910, proceeding
Adjusting zone's serial
Signing zone file /etc/nsd3/example.com.zone with keys Kexample.com.+007+21303 & Kexample.com.+007+13910 until 20120710
nsdc rebuild
nsdc reload
root@ruff:~/dnssec# make
make: Nothing to be done for `all'.
root@ruff:~/dnssec#


---

Setting up DNSSEC/IPv6 enabled recursive cache

I prefer software to be little, light and efficient, and doing precisely what it is intended to do. That's why if I need authoritative IPv6 and DNSSEC enabled DNS server I install NSD rather than BIND, and when I need recursive cache with the same features I install Unbound - from the same vendor btw. As such, when I'm troubleshooting master zones I'm not affecting cache used by my wife to surf her blogs.

Unbound

Server is supplied with extensive config file, where majority of default options are sufficient for normal run. On ubuntu you can install with simpe apt-get install unbound, on gentoo with emerge unbound. On ubuntu server is pre-installed with control certificates, on gentoo with root anchor. Here is configuration sufficient for following features:

  • IPv6 socket support
  • DNSSEC root anchor support
  • DNSSEC DLV support (from dlv.isc.org anchor)
  • remote control (unbound-control)
  • Forwarding of google to SixXS cache
server:
        verbosity: 1
        interface: 127.0.0.1
        interface: ::1
        interface: 10.0.0.252
        interface: 2001:db8:ff6d:1::1
        do-ip4: yes
        do-ip6: yes
        do-udp: yes
        do-tcp: yes
        access-control: 10.0.0.128/25 allow
        access-control: 127.0.0.1/8 allow
        access-control: 2001:db8:ff6d::/48 allow
        access-control: 2001:db8:ff00:e8::2/128 allow
        access-control: 0.0.0.0/0 deny
        access-control: ::0/0 deny
        chroot: ""
        auto-trust-anchor-file: "/etc/unbound/root.key"
        dlv-anchor-file: "dlv.isc.org.key"
        val-log-level: 2
remote-control:
        control-enable: yes
        control-interface: 127.0.0.1
        control-interface: ::1
        server-key-file: "/etc/unbound/unbound_server.key"
        server-cert-file: "/etc/unbound/unbound_server.pem"
        control-key-file: "/etc/unbound/unbound_control.key"
        control-cert-file: "/etc/unbound/unbound_control.pem"
forward-zone:
        name: "google.com"
        forward-addr: 2001:b18:0:1000:2e0:81ff:fe61:ae0d
        forward-addr: 2001:14b8:0:3007::6
        forward-addr: 2001:1418:10:2::2
        forward-addr: 2001:41e0:ff00::5
        forward-addr: 2001:16d8:aaaa:3::2
        forward-addr: 2001:7b8:3:4f:202:b3ff:fe46:bec

Now fetch root anchor (unbound-anchor -a "/etc/unbound/root.key"), adjust its permissions (chown unbound "/etc/unbound/root.key"), fetch dlv root anchor (wget http://ftp.isc.org/www/dlv/dlv.isc.org.key -O /etc/unbound/dlv.isc.org.key) and start the server (/etc/init.d/unbound start). Check control tool works:

~# unbound-control status
version: 1.4.9
verbosity: 1
threads: 1
modules: 2 [ validator iterator ]
uptime: 329051 seconds
unbound (pid 6054) is running...

That's it, check google is properly resolving:

~# drill aaaa google.com @::1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 48741
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; google.com.  IN      AAAA

;; ANSWER SECTION:
google.com.     300     IN      AAAA    2a00:1450:8007::67

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 186 msec
;; SERVER: ::1
;; WHEN: Wed Jul 13 22:22:04 2011
;; MSG SIZE  rcvd: 56

References

Dnssec howto with NSD and ldns