DNSSEC
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.
Contents
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