Difference between revisions of "DNSSEC TSIG BIND9"
(One intermediate revision by the same user not shown) | |||
Line 203: | Line 203: | ||
<pre> | <pre> | ||
#!/bin/sh | #!/bin/sh | ||
+ | ################################################################################ | ||
+ | # | ||
+ | # 2014-12-08 -- jontow@zenbsd.net | ||
+ | # | ||
+ | # Sign [or re-sign] a given DNSSEC enabled zone. | ||
+ | # | ||
+ | ################################################################################ | ||
if [ "$1" = "" ]; then | if [ "$1" = "" ]; then | ||
Line 214: | Line 221: | ||
/usr/local/sbin/dnssec-signzone -K /var/named/etc/keys $ZONE | /usr/local/sbin/dnssec-signzone -K /var/named/etc/keys $ZONE | ||
− | echo "" | + | # Hidden argument, for non-interactive use. |
− | echo "Now edit named.conf and change '$ZONE' to '${ZONE}.signed' in the file clause." | + | if [ "$2" != "-q" ]; then |
− | echo "Then 'rndc reconfig'" | + | echo "" |
− | echo "" | + | echo "Now edit named.conf and change '$ZONE' to '${ZONE}.signed' in the file clause." |
+ | echo "Then 'rndc reconfig'" | ||
+ | echo "" | ||
+ | fi | ||
</pre> | </pre> | ||
Line 226: | Line 236: | ||
2014122100 ; AUTOSERIAL | 2014122100 ; AUTOSERIAL | ||
+ | This script is meant to be run from a crontab(5) file rarely, on an interval such<br/> | ||
+ | as once per month.<br/> | ||
<pre> | <pre> | ||
#!/bin/sh | #!/bin/sh |
Latest revision as of 22:26, 21 December 2014
Overview
I recently had some time to get an item off my long-term TODO list: setting up
DNSSEC signing on my zones, validation on my resolvers, and TSIG XFER between
masters/slaves. The latter I've done before, the two former items were a total
mystery to me. Less so, now.
I'm using ISC BIND 9.9.x on OpenBSD 5.4 for these, installed from ports/packages.
Seems like times change quickly in DNSSEC land, so this may or may not become
irrelevant in short order, like so much of the web documentation on DNSSEC.
OpenBSD Challenges/Prerequisites
As of OpenBSD 5.4, an in-tree copy of BIND 9.4.2 is shipped, and it doesn't do any
DNSSEC related bits. However, someone was kind enough to build a port/package for
a more modern version that does: package name is 'isc-bind', and can be installed
as a binary package in the normal ways.
Configuration for it uses the shipped /var/named/ tree, and if you have a previously
configured copy in use on your system, the conversion is pretty easy.
Edit /etc/rc.conf.local and comment out the following line, if it exists:
named_flags=
Add the following to your "pkg_scripts" line. If you don't have that line, now is a
fine enough time to add one. It enables the "new" rc.d style pkg start scripts. The
line should look something like one of the below:
pkg_scripts="isc_named" pkg_scripts="mysql munin-node isc_named"
Once that's finished, simply kill the old BIND and start the new one:
$ sudo pkill -9 named $ sudo /etc/rc.d/isc_named start
Have a look in /var/log/daemon to see if everything is as expected. If so, you now have
an upgraded copy of BIND9 capable of DNSSEC signing/validation.
Keep in mind, you'll still have some system-shipped 'dnssec-*' binaries hanging out
in /usr/sbin that will probably be preferred by your $PATH -- Easy solution is to
rename them:
$ sudo mv /usr/sbin/dnssec-signzone /usr/sbin/dnssec-signzone.dist $ sudo mv /usr/sbin/dnssec-keygen /usr/sbin/dnssec-keygen.dist
DNSSEC validating resolvers
Easy enough, right? Well, I'll leave the nonsense chain-of-trust explanations to
the rest of the web, thats a detail thats consistantly explained by everyone, and
in a few cases fairly well. This is more of a how-to than a why-for.
I'll use '/var/named' as the BIND root for this; if you follow my OpenBSD crap above
you'll see that is the system I'm running on primarily.
First, edit /var/named/etc/named.conf and add a few lines inside "options { ... }":
dnssec-enable yes; dnssec-validation yes; dnssec-lookaside auto; managed-keys-directory "dynamic";
Then, add a line outside options, in the 'global' scope:
include "etc/bind.keys";
Then, you'll probably need to actually retrieve the most current bind.keys
file for your version of BIND. A brief explanation of what this file is can be found at
the above URL. It's a transition shim, ultimately a temporarily permanent fixture.
Place the file on your system as /var/named/etc/bind.keys so the above 'include' can find
it. Relative paths (inside /var/named) worked for me, you may not be so lucky.
Now, you'll need to create the 'dynamic' directory and fix permissions:
$ sudo mkdir /var/named/dynamic $ sudo chown named:named /var/named/dynamic
At this point, restart BIND and pay attention to /var/log/daemon to see how it went.
You probably have a usable DNSSEC validating resolver now. If not, good luck.
TSIG XFER between servers
It's nice to have some level of security and confidence in your zone transfers,
and IP based allow/deny is a bit weak. For this reason, I chose to setup TSIG
for authenticating servers attempting to transfer (XFER) zones.
The drawback of this is that you need to generate and distribute keys to your
other nameservers; but it's a one time deal.
Generating Keys
We'll generate a key pair on the master, let's say "ns1.example.com". Our other
nameserver is "ns2.example.com", setup as a slave for all zones involved. We're
going to use a key naming convention that I like, because this is my documentation.
Pick something you like, but stick with it for your own sanity.
My naming scheme is like this: master-slave. For this doc, we're using this like so:
"ns1.example.com-ns2.example.com". It's long, but you don't type it *THAT* much,
and the clarity is great later.
We're going to make a directory specifically for all of our keys. I use the same
one for DNSSEC signing keys and TSIG keys.
ns1$ sudo mkdir /var/named/etc/keys
Now let's generate the TSIG host key:
ns1$ cd /var/named/etc/keys ns1$ dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST -r /dev/urandom ns1.example.com-ns2.example.com
This generates a pair of files in the current directory, one ending in '.key' (public)
and the other in '.private' (...private, wouldn't have guessed it, right?). You need
to grab the contents of one field in the private key:
ns1$ grep '^Key' Kns1.example.com-ns2.example.com.+XXX+YYYYY.private
The relevant data is what's after ": ", a hash string. You need to add it to your BIND
config, which we'll do in a separate file, because clarity, mhm.
ns1$ vi /var/named/etc/tsig.keys
Make the contents of the file look like this:
key "tsig-ns1.example.com-ns2.example.com" { algorithm HMAC-SHA512; secret "rEAllybiglongencryptedhashstringhmacsha512etcetcg=="; };
Now include this in your named.conf, in the global scope. If you went through with
the procedure way above of adding bind.keys, you can add it right around that.
include "etc/tsig.keys";
Now you can pick one of your zones and set it up with the new keys. Don't worry
about reloading the BIND config yet, we'll get there. Don't be hasty.
Find the zone config in named.conf, and find the "allow-transfer" section. There
should be an IP address there for ns2.example.com, and we're going to replace it
with the new TSIG key.
allow-transfer { key "tsig-ns1.example.com-ns2.example.com"; };
Now you may be hasty: restart BIND9 (or 'rndc reconfig'). The logs should show no
obvious errors, unless they were preexisting or you botched something just now.
Let's move on to ns2.example.com's config. We need to add a similar "tsig.keys"
file there, with the contents looking like this:
key "tsig-ns1.example.com-ns2.example.com" { algorithm HMAC-SHA512; secret "rEAllybiglongencryptedhashstringhmacsha512etcetcg=="; }; /* 1.2.3.4 == ns2.example.com */ server 1.2.3.4 { keys { tsig-ns1.example.com-ns2.example.com; }; };
The astute observationinst will notice the "secret" is the same one we put in the
config file on ns1: this is no coincidence, it is the entire idea.
Now add the same line for the tsig.keys file into named.conf:
include "etc/tsig.keys";
You need make no changes to your slave zone definitions: the IP address must remain
there, but should match the "server" bit in tsig.keys that we defined earlier.
Now restart/reconfig BIND and pay attention to the logs:
03-Mar-2014 23:06:42.237 general: zone example.com/IN: transferred serial 2014030301: TSIG 'tsig-ns1.example.com-ns2.example.com'
This indicates successful work: anything else probably doesn't!
Zone Signing
Scripts
'zonekeys'
#!/bin/sh if [ "$1" = "" ]; then echo "Syntax: zonekeys <zonename>" exit fi ZONE=$1 cd /var/named/etc/keys dnssec-keygen -f KSK $ZONE KEYFILE1=`ls K${ZONE}*.key` dnssec-keygen $ZONE KEYFILE2=`ls K${ZONE}*.key | grep -v $KEYFILE1` echo "Now add the following to /var/named/master/$ZONE (after '\$ORIGIN ${ZONE}.')" echo "" echo "\$include ../etc/keys/$KEYFILE1 ; KSK" echo "\$include ../etc/keys/$KEYFILE2 ; ZSK" echo "" echo "Then 'signzone $ZONE'"
'signzone'
#!/bin/sh ################################################################################ # # 2014-12-08 -- jontow@zenbsd.net # # Sign [or re-sign] a given DNSSEC enabled zone. # ################################################################################ if [ "$1" = "" ]; then echo "Syntax: signzone <zonefile>" exit fi ZONE=$1 cd /var/named/master /usr/local/sbin/dnssec-signzone -K /var/named/etc/keys $ZONE # Hidden argument, for non-interactive use. if [ "$2" != "-q" ]; then echo "" echo "Now edit named.conf and change '$ZONE' to '${ZONE}.signed' in the file clause." echo "Then 'rndc reconfig'" echo "" fi
'cron.signzone'
This script requires that the serial number in the zonefile be specified with a
comment after it like this:
2014122100 ; AUTOSERIAL
This script is meant to be run from a crontab(5) file rarely, on an interval such
as once per month.
#!/bin/sh ################################################################################ # # 2014-12-08 -- jontow@zenbsd.net # # Meant to be run every $interval (~1month?) via cron from the primary # nameserver for a group of zones. Relies on 'signzone' script, # found in this same directory. # ################################################################################ ZONEDATA=/var/named/master NEWSERIAL=`date +"%Y%m%d00"` cd $ZONEDATA ZONELIST=`ls | grep '.signed' | sed '1,$s/\.signed//g'` for ZONE in $ZONELIST; do if [ -f $ZONE.$NEWSERIAL ]; then echo "Backup $ZONE.$NEWSERIAL already exists.. Bailing before we do anymore damage." exit fi if [ ! -f $ZONE ]; then echo "Missing zonefile $ZONE" else # Backup zonefile cp $ZONE $ZONE.$NEWSERIAL # Bump serial number echo "Bumping serial number for zone $ZONE to $NEWSERIAL" TMPFILE=`mktemp /tmp/$ZONE.XXXXXX` sed "1,\$s/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\ \;\ AUTOSERIAL/$NEWSERIAL\ \;\ AUTOSERIAL/g" $ZONE >$TMPFILE mv $TMPFILE $ZONE /usr/local/sbin/je.signzone $ZONE fi done rndc reload
Procedure
- zonekeys
- edit zonefile, add includes
- signzone
- edit named.conf, rename zone zone.signed
- rndc reload
Obtain DS Record
dnssec-dsfromkey -f zonefile
Install DS Record at Registrar
Godaddy
placeholder, mention formatting difference
Testing
placeholder.
External Resources
placeholder.