DNSSEC is a very good thing, in my opinion. For almost twenty years, there has been at least a proof of concept about attacks against DNS. Kaminsky’s DNS flaw last year only strengthened the push to implement cryptographic extensions, and now, ICANN says that com. and . (the root zone) will be signed by year’s end, which means that DNSSEC can be properly implemented.
Generating the keys and signing a bunch of zones, however, quickly becomes arduous. For one domain, it’s not bad. When you administer two external domains, four reverse IPv4 and IPv6 zones, and an internal zone or two, it quickly becomes a hassle. Like any Linux user who spends some time at the command-line, I wrote a rudimentary shell script to automate this process. The latest version is at the end of this post, but read on. I ran into a problem, and not finding anything on Google, I decided to document it here.
Now, I like a nice clean directory listing. When you use SSH as your primary means of getting things done on the server, it’s a requisite. I wrote my script to rename the generated keys, and place them all in the keys folder before signing the zone ($1 being the zone name):
1 2 3 4 | /bin/mv $ZSKNAME.key keys/$1.zsk.key /bin/mv $ZSKNAME.private keys/$1.zsk.key.private /usr/sbin/dnssec-signzone -t -N increment -H 10 -k $1.ksk.key \ -e +7776000 -o $1. $1.zone /var/bind/pri/$1.zsk.key |
All seemed well until I ran it:
# ./signzone.sh example.com Will sign example.com.zone Generating new key-signing keypair. Generating zone-signing keypair. Signing zone. dnssec-signzone: cannot load dnskey keys/example.com.zsk.key: file not found Done.
It complained about the file not existing, but it definitely did:
# stat example.com.zsk.key File: `example.com.zsk.key' Size: 395 Blocks: 8 IO Block: 4096 regular file Device: 6802h/26626d Inode: 17989721 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2009-08-11 11:20:12.000000000 -0400 Modify: 2009-08-11 11:20:12.000000000 -0400 Change: 2009-08-11 11:20:12.000000000 -0400
It took me a few hours of troubleshooting, modifying the script, wondering about NSEC3 records, and even rebuilding BIND 9.6.1-p1 from source. Finally, I installed and used strace on my script, which revealed the problems:
- BIND, especially dnssec-signzone, expect the public keys to end in .key and the private keys to end in .private. Changing their extensions from .key.private to .private fixed it.
- dnssec-signzone expects, as an argument, the name of the keypair, minus the extension. With the correctly-named keypair of example.com.ksk.key and example.com.ksk.private, dnssec-signzone should be run with the -k example.com.ksk argument. Note the lack of extensions.
After fixing that, dnssec-signzone stopped complaining, and I was able to sign all of my zones without a hitch. Restarted BIND, and it’s sending out notifies as I type this.
Now, for those of you who came here for the finished, bug-free script, here you go.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #!/bin/sh # signzone.sh, Copyright © 2009 Colin Cogle. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http ://www.gnu.org/licenses/>. # # Usage: signzone.sh <name of zone to sign> # Example: signzone.sh example.com # Example: signzone.sh 8.b.d.0.1.0.0.2.ip6.arpa if [ -f $1.zone ]; then echo "Will sign $1.zone" else echo "$1.zone does not exist."; exit; fi # # Stash our keys in the keys subdirectory, just to keep things clean. # if [ -f keys/$1.ksk.key ]; then echo "Using pre-generated key-signing keypair." else echo "Generating new key-signing keypair." KSKNAME=$(/usr/bin/dnssec-keygen -f KSK -e -a NSEC3RSASHA1 -b 2048 -n ZONE $1) /bin/mv $KSKNAME.key keys/$1.ksk.key /bin/mv $KSKNAME.private keys/$1.ksk.private fi if [ -f keys/$1.zsk.key ]; then echo "Using pre-generated zone-signing keypair." else echo "Generating zone-signing keypair." ZSKNAME=$(/usr/bin/dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE $1) /bin/mv $ZSKNAME.key keys/$1.zsk.key /bin/mv $ZSKNAME.private keys/$1.zsk.private fi echo "Signing zone." /usr/sbin/dnssec-signzone -a -g -t -N increment -H 10 -3 caf3 -d keys -k keys/$1.ksk -e +7776000 -o $1. $1.zone keys/$1.zsk echo "Done." |
Do note that this Bash script is a rough draft, and represents only about ten minutes of coding and referencing man pages. I’ve licensed it under the AGPL if anyone wants to make a copy for themselves.

[...] your zone file, sign it (if you use DNSSEC), and do an 1rndc [...]
This is exactly what I was searching for on google, I guess I got my answer! lol