The Perfect BIND DNS Server DNSSEC enabled

Trunet's Place - Portfolio
Jump to: navigation, search

This guide was tested on an Ubuntu distribution. Some notes will be added to make it work on RedHat/CentOS though this is untested.

Description

"The Domain Name System (DNS) is a hierarchical naming system built on a distributed database for computers, services, or any resource connected to the Internet or a private network. Most importantly, it translates domain names meaningful to humans into the numerical identifiers associated with networking equipment for the purpose of locating and addressing these devices worldwide." Wikipedia DNS Page

On this guide we'll configure BIND to run an Authoritative name server with option to enable Recursive and caching name server with DNSSEC enabled.

Package Installation

I had problems with versions prior to 9.5. I recommend to install the distribution packages as it'll receive security updates when needed. You have the possiblity to compile and install bind from source. This will not be covered on this page.

# aptitude update && aptitude install bind9


RedHat/CentOS: On RedHat/CentOS the package bind97-chroot exists and it makes possible to run bind on a chroot environment. This increases security but it'll not be covered on this guide.

# yum install bind97


Initial configuration

We'll basically enable DNSSEC and if you want, enable recursion. Recursion is what makes you DNS query things to you.

The default configuration files stays on /etc/bind. Note that ubuntu split named.conf on some files. named.conf.options per example contains your options {}.

options {
	...
	dnssec-enable yes;
};

If you want to enable recursion, add dnssec-validation:

options {
	...
	dnssec-enable yes;
	dnssec-validation yes;

RedHat/CentOS: The default configuration file is /etc/named.conf.

Create your zone files

Here is where the magic begins.

First, create your zone file. This depends on your general infra-structure so I'll provide a simple template. Note that this template has IPV6 on AAAA record types that you can remove if you don't have it on your server. Also this zone is configured with 300 seconds(5 minutes) TTL.

/etc/bind/db.mydomain.com

$TTL 300
@	IN	SOA	ns1.mydomain.com.	myemail.gmail.com. (
			2011080101 	; Serial
			10800		; Refresh
			3600		; Retry
			648000		; Expire
			10800 )		; Minimum
 
mydomain.com.    IN      NS      ns1.mydomain.com.
mydomain.com.    IN      NS      ns2.mydomain.com.
ns1             IN      A       1.2.3.4
ns1		IN	AAAA	2000:1234::a
ns2             IN      A       2.3.4.5
ns2		IN	AAAA	2100:1234::a
 
@		IN	A	1.2.3.4
@		IN	AAAA	2000:1234::f03c:91ff:fe93:af1a
www		IN	A	1.2.3.4
www		IN	AAAA	2600:3c03::f03c:91ff:fe93:af1a

Helper scripts

I created some pre-made scripts that will create necessary keys and sign your zones when needed.

/etc/bind/scripts/gen-ksk.sh

#!/bin/sh
ZONE=$1
 
cd /etc/bind/ksk
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 4096 -n ZONE -f KSK ${ZONE}


/etc/bind/scripts/gen-zsk.sh

#!/bin/sh
ZONE=$1
 
cd /etc/bind/zsk
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 1024 -n ZONE /etc/bind/zsk/${ZONE}


/etc/bind/scripts/sign-zone.sh

#!/bin/bash
if [ -z "$1" ]
then
	echo "Usage: sign-zone.sh ZONE_NAME"
	exit 1
fi
ZONE=$1
 
update_serial() {
	DATENOW=$(date +%Y%m%d)
	SERIAL=$(head /etc/bind/db.${ZONE} | grep -i serial | sed 's/[\ |\t]//g' | awk -F';' '{print $1}')
	SERIALDATE=$(echo $SERIAL | cut -b1-8)
	SERIALID=$(echo $SERIAL | cut -b9-10)
 
	if [ $SERIALDATE -lt $DATENOW ]; then
		sed -i -e 's/'$SERIALDATE''$SERIALID'/'$DATENOW'01/g' /etc/bind/db.${ZONE}
	else
		sed -i -e 's/'$SERIAL'/'`((SERIAL++)) ; echo $SERIAL`'/g' /etc/bind/db.${ZONE}
	fi
}
 
update_serial
 
cd /etc/bind
/usr/sbin/dnssec-signzone -o $ZONE -k /etc/bind/ksk/K${ZONE}.*.key /etc/bind/db.${ZONE} /etc/bind/zsk/K${ZONE}.*.key
 
exit 0


Create directories and set execute permissions:

mkdir /etc/bind/zsk /etc/bind/ksk
chmod 755 /etc/bind/scripts/*.sh


Create DNSSEC keys and sign your zone

Creating the keys

Now, we'll create our keys. This can be made using the helper scripts up in this page.

/etc/bind/scripts/gen-zsk.sh mydomain.com
/etc/bind/scripts/gen-ksk.sh mydomain.com


Adding the public keys to your zone

You'll have to add the public keys to you domain zone:

cat /etc/bind/zsk/Kmydomain.com.*.key /etc/bind/ksk/Kmydomain.com.*.key >> /etc/bind/db.mydomain.com


Signing the zone

/etc/bind/scripts/sign-zone.sh mydomain.com


This will create on /etc/bind, two files: db.mydomain.com.signed and dsset-mydomain.com.

Activate your zone on BIND

Edit your bind configuration file and add:

...
zone "mydomain.com" {
    type master;
    file "/etc/bind/db.mydomain.com.signed";
};
...

This will make BIND load the signed file you created. Restart your bind service and you're ready to go.

Loading DS keys on registrar

Final step is to load your DS keys on your domain register. I will add an examples using godaddy. For this you'll need the /etc/bind/dsset-mydomain.com. file keys. This keys will be loaded.

GoDaddy

Open "Domain Manager", and click on domain you're configuring(eg. mydomain.com). It'll load a "Domain Detail" page. On nameservers, you'll see a link "Manage DS Records".

You'll see:

Dnssec godaddy 1.png

Next, "Add new DS record":

Dnssec godaddy 2.png

You dsset file has two lines. One is your KSK and one is your ZSK. First, load the KSK key. Key Tag is the 4th field(a number between 1 and 65535), 5th field is Algorithm(number 5 normally), 6th field is Digest type(number 1 for ZSK, number 2 for KSK) and Digest is the rest.

Repeat this for the second line, note that Digest type will change to 2 and your key on DSSET is like this: "6695CD1AEBDCFD2E0530361234564E67F9D4202BBE34FD719B8EB97F 3B12345F" note that you NEED to remove the space or you'll not be able to click next.

And you're done. You'll have two keys on your DS records page:

Dnssec godaddy 3.png

How to test?

Troubleshoot

Q: I'm receiving truncated reply from my DNS server:

trunet@neo:~host -t dnskey my_dnssec_enabled_domain.com 1.2.3.4
;; Truncated, retrying in TCP mode.
Using domain server:
Name: 1.2.3.4
Address: 1.2.3.4#53
Aliases: 
 
my_dnssec_enabled_domain.com has DNSKEY record 257 3 5 AwEAAeg1rCONAw2ko1Gs/P1gYjMX8cTzKetNDhZLXdF2ExJZQpo/hl/7 seWulKj42+8FfXDKfW9+GWNHpDk7o8MJI3DhU1WfTDmQiaPfAWr+Nikp ajwrnCcw84h0ZMsIi1sqodOD9LTda4eNYDuhDtTn9LM1obdZGyaHpVdP EZxyXNTmmoQSTHigmfnkQ5rsbTjAvRktMtTaKyICdY123456wQz9C9Ly KWtJy8SgRidKCsokHROIKs3pcCTE3i2tyAh1G8EwLGJzyX6K0EkU20aa jVAKN/fDCHvXsFd15KsyBZ5/KANJWiwiICf5+TQ3CtmJe9YTYzCUFv8l MzEBQ2eUHZnapwP4jRT9cNpEolMkqebfgFbMaZRAtS9QP26IaXEfSMQj cUYweb15xiiQ8gelAHvjNwbdjUUgeZRc6KOQLsBto0ZYwkwm3v+Bwpr+ G+md6q/v2hximAvwrxuE9AazFOlwkVgfULZaqto5vpEBE2NTe8Jhl3to S+PLwCZU3/lJsEnd4CWrGGRdsaZr5d698qWQe1iC/CkLR0v3x/4vQ1qW nP0I7Mb+IEaTRZvsOHBLV5+Wthe8R4W4cD5DjHWu7aX0fyiaDmW2onkt M7wCVWibelziMNwaGDUMlA4I8qnRaJFGShUA7fPP9LHMZkhtciaZCbqC /HA70RgO5ggxnZ7r
my_dnssec_enabled_domain.com has DNSKEY record 256 3 5 AwEAAdM8rlG4B6h7w8vFQq5aLbOMY6AfRUG8bzW123456L8auxXL/xYV pAXWvy0y/HsJdvY8DzCef5PybO5ldBmzdQZLADre3rJOUVgiSLpG4MsN oR7rtVfYchT2BR2/n98MffkbEGs0/5lkuOitTt1JeVcV7yPVFuGo4r4T oOgqbsfJ

A: On the past, DNS were limited to 512 bytes on UDP, everything that pass this limit comes in TCP mode. To circunvent this, IETF approved on 1999 an Extension mechanisms for DNS also know as EDNS0. It allows larger packets to be delivered correctly. I have some problems with Cisco PIX firewalls, adding "fixup protocol dns maximum-length 4096" to the firewall configuration resolved the problem.

Help/Support

My forum is open to all of you looking for answers or wanting to comment this article.