dnsworkshop.de
14 Feb 2018

Installing Stubby on Fedora Linux 27

DNS-over-TLS Part 1: Stubby

Stubby (https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby) is a DNS privacy stub resolver. Stubby, among other things, does support DNS-over-TLS (RFC 7858 "Specification for DNS over Transport Layer Security (TLS)" https://tools.ietf.org/html/rfc7858).

This document describes the installation from source on Fedora Linux 27:

Install the dependencies

sudo dnf install -y make gcc libtool libyaml-devel openssl-devel wget 

Building Stubby from source

Below are the commands to check-out the stubby source code and compile and install stubby. This has been tested on Fedora Linux 27, but it might work also on other recent Linux versions:

mkdir ~/src
cd ~/src
git clone https://github.com/getdnsapi/getdns.git
cd getdns
git checkout develop
git submodule update --init
libtoolize -ci
autoreconf -fi
mkdir build
cd build
../configure --without-libidn --enable-stub-only \
   --with-ssl --with-stubby
make
sudo make install

SELinux fixes

Fedora Linux uses SELinux by default. To be able to use stubby, the security label on the binary needs to be set:

sudo restorecon -v /usr/local/bin/stubby

review the Stubby default configuration

Stubby configuration is written in YAML (https://en.wikipedia.org/wiki/YAML). Review the default configuration and adapt where needed:

sudo $EDITOR /usr/local/etc/stubby/stubby.yml

Stubby testrun

This command will start Stubby on the commandline in foreground. This is a test if the configuration is valid. After the test, terminate Stubby with CTRL+C.

sudo /usr/local/bin/stubby -l

change stub-resolver configuration

Stubby is listening on port 53 on the loopback IP-Address for DNS-queries from applications. The resolver configuration in /etc/resolv.conf must point to the loopback address.

In this example a very direct way is used by re-writing /etc/resolv.conf and making it immutable with an extended attribute. In production environments, it is cleaner to change the resolver information in Network-Manager

echo "nameserver 127.0.0.1" > /etc/resolv.conf
chattr +i /etc/resolv.conf

test DNS queries

dig dnsworkshop.org a

Systemd-Startunit

Now that Stubby has been successfully tested, stop the running stubby process with CTRL+C and create a new unit configuration for systemd in /etc/systemd/system/stubby.service

[Unit]
Description=Stubby DNS-over-TLS Stub-Resolver
After=network.target

[Service]
ExecStart=/usr/local/bin/stubby -l

[Install]
WantedBy=multi-user.target

start end enable Stubby

register the new unit file in systemd and start Stubby

systemctl daemon-reload
systemctl enable --now stubby
systemctl status stubby

Now the enhanced security of privacy of stubby is available for all applications on the system.

28 Feb 2014

Delve deep into DNSSEC

BIND 9.10 is the new version of the BIND 9 DNS server from ISC http://isc.org (not to confuse with BIND 10, which is a different DNS server product). I will report in a series of articles about the new features in BIND 9.10. The first beta version of BIND 9.10 has been released this week and can be found at ftp://ftp.isc.org/isc/bind9/9.10.0b1/.

BIND 9.10 contains a new command-line tool to test DNSSEC installations. The tool is called delve and it works very much like the already know dig. It is like dig with special DNSSEC validation powers.

delve checks the DNSSEC validation chain using the same code that is used by the BIND 9 DNS server itself. Compared with the DNSSEC testing function in dig +sigchase, delve is much closer to what really happen inside a DNS server.

1.1 A simple lookup

shell> delve dnsworkshop.org
; fully validated
dnsworkshop.org.        3600    IN      A       91.190.147.212
dnsworkshop.org.        3600    IN      RRSIG   A 8 2 3600 20140318181408 20140216173922 63654 dnsworkshop.org. qS9/slk/jvcMc7+HSTMFD1D7GfuW5LIgBj0J1vCCCP5X+g9puhDdRSMM dURzelY6wsPVaUgtx44azEoJYHmNwFJlSsALPnekC6DWjKYMhzYilpUl OKAIZQh5lZxs3oimZHe6GEpEfkZ3ZV0IDTLLe4pIKRXoxDQ2eRJ543GD iTk=

Without extra arguments, delve will query the local DNS server (taken from /etc/resolv.conf) for an IPv4-Address record at the given domain name. It tries to validate the answer received, prints the result of the validation, the requested data and the RRSIG Record (DNSSEC signature) used to verify the data.

1.2 pretty-printing

As with dig, resource record types and network classes can be given in almost any order on the commandline. The switch +multi (for multiline) enables pretty printing; human readable output that is nearly formatted for a 78 column screen.

shell> delve dnsworkshop.org soa +multi
; fully validated
dnsworkshop.org.        3600 IN SOA ns1.myinfrastructure.org. hostmaster.strotmann.de. (
                                86         ; serial
                                86400      ; refresh (1 day)
                                7200       ; retry (2 hours)
                                3542400    ; expire (5 weeks 6 days)
                                3600       ; minimum (1 hour)
                                )
dnsworkshop.org.        3600 IN RRSIG SOA 8 2 3600 (
                                20140321030247 20140219020247 63654 dnsworkshop.org.
                                O8mmiuNdXIWG6huaLiQrvKabDY3qivQ3R5qRUZ1IG3wp
                                bd0UBnvpazpG01ntk8uZ7wEStScmiY7oYtvRGIHG37mG
                                8GFI60CUx3pdXJIpmodfoUBk8cfGsJXFQODIZCTUQiyk
                                Pv9I6+wjyseDJJTYlrsBCvAEabPExFKZc7v+L+k= )

and IPv6

shell> delve dnsworkshop.org AAAA +multi
; fully validated
dnsworkshop.org.        7200 IN AAAA 2001:470:1f08:f1d::2
dnsworkshop.org.        7200 IN RRSIG AAAA 8 2 7200 (
                                20140321025727 20140219020247 63654 dnsworkshop.org.
                                gqkc1Xq/UveKrhcXpqOwDsN5HFSqMsPkxXOyCqu9bMyx
                                dtnkh0J0Iqukv+uHL/dDQLnPcxjdFqs3N5Jf3BFHdgkG
                                tf0UPhNKsuhlsRdo2H5O+TqmLvA1zCsYhH/72vVvxslR
                                MiiuZ1ILGpLA2EOyiZu70/ZIU3Ypc3nb8+ydgx4= )

1.3 tracing DNSSEC validation

delve comes with a set of trace switches that can help troubleshoot DNSSEC validation issues. The first switch, +rtrace, prints the extra DNS lookups delve performs to validate the answer:

delve dnsworkshop.org mx +multi +rtrace
;; fetch: dnsworkshop.org/MX
;; fetch: dnsworkshop.org/DNSKEY
;; fetch: dnsworkshop.org/DS
;; fetch: org/DNSKEY
;; fetch: org/DS
;; fetch: ./DNSKEY
; fully validated
dnsworkshop.org.        3600 IN MX 100 mail.strotmann.de.
dnsworkshop.org.        3600 IN RRSIG MX 8 2 3600 (
                                20140308193355 20140206183355 63654 dnsworkshop.org.
                                hCOcPJrDCXpcVS82FgGEdUhaUmW3XkxXEuEa4AFvzkzi
                                mDcokYNjrW/Hay4NclSWV0jrBwrXABXik5dh7w7KsPkD
                                WKhw/qVvkuiFCm+T5lb9OVkGQAuPhBOplbVgdbZce9L7
                                N2IVTQTLMECKfzCTfKeOtwupJAMPXCt/Xskd5o4= )

In this example, in addition to the MX-Record (Mail-Exchanger) Record, the DNSKEY record (DNSSEC public key) and the DS record (Delegation signer) for dnsworkshop.org, as well as the DNSKEY and DS records for ORG and the DNSKEY for the root-zone "." have been requested. The trust-anchor for the Internet Root-Zone is compiled into delve and acts as the starting trust anchor for the validation.

The switch +mtrace prints the content of any additional DNS records that have been fetched for validation.

+vtrace prints out the DNSSEC chain of validation:

shell> delve _443._tcp.dnsworkshop.org TLSA  +multi +vtrace
;; fetch: _443._tcp.dnsworkshop.org/TLSA
;; validating _443._tcp.dnsworkshop.org/TLSA: starting
;; validating _443._tcp.dnsworkshop.org/TLSA: attempting positive response validation
;; fetch: dnsworkshop.org/DNSKEY
;; validating dnsworkshop.org/DNSKEY: starting
;; validating dnsworkshop.org/DNSKEY: attempting positive response validation
;; fetch: dnsworkshop.org/DS
;; validating dnsworkshop.org/DS: starting
;; validating dnsworkshop.org/DS: attempting positive response validation
;; fetch: org/DNSKEY
;; validating org/DNSKEY: starting
;; validating org/DNSKEY: attempting positive response validation
;; fetch: org/DS
;; validating org/DS: starting
;; validating org/DS: attempting positive response validation
;; fetch: ./DNSKEY
;; validating ./DNSKEY: starting
;; validating ./DNSKEY: attempting positive response validation
;; validating ./DNSKEY: verify rdataset (keyid=19036): success
;; validating ./DNSKEY: signed by trusted key; marking as secure
;; validating org/DS: in fetch_callback_validator
;; validating org/DS: keyset with trust secure
;; validating org/DS: resuming validate
;; validating org/DS: verify rdataset (keyid=33655): success
;; validating org/DS: marking as secure, noqname proof not needed
;; validating org/DNSKEY: in dsfetched
;; validating org/DNSKEY: dsset with trust secure
;; validating org/DNSKEY: verify rdataset (keyid=21366): success
;; validating org/DNSKEY: marking as secure (DS)
;; validating dnsworkshop.org/DS: in fetch_callback_validator
;; validating dnsworkshop.org/DS: keyset with trust secure
;; validating dnsworkshop.org/DS: resuming validate
;; validating dnsworkshop.org/DS: verify rdataset (keyid=24209): success
;; validating dnsworkshop.org/DS: marking as secure, noqname proof not needed
;; validating dnsworkshop.org/DNSKEY: in dsfetched
;; validating dnsworkshop.org/DNSKEY: dsset with trust secure
;; validating dnsworkshop.org/DNSKEY: verify rdataset (keyid=2611): success
;; validating dnsworkshop.org/DNSKEY: marking as secure (DS)
;; validating _443._tcp.dnsworkshop.org/TLSA: in fetch_callback_validator
;; validating _443._tcp.dnsworkshop.org/TLSA: keyset with trust secure
;; validating _443._tcp.dnsworkshop.org/TLSA: resuming validate
;; validating _443._tcp.dnsworkshop.org/TLSA: verify rdataset (keyid=63654): success
;; validating _443._tcp.dnsworkshop.org/TLSA: marking as secure, noqname proof not needed
; fully validated
_443._tcp.dnsworkshop.org. 3544 IN TLSA 3 0 1 (
                                3E5E70BBA957CA0DAFCB799F15F6236133C0F6C73FA7
                                3762BFFBCA4AF92389CA )
_443._tcp.dnsworkshop.org. 3544 IN RRSIG TLSA 8 4 3600 (
                                20140309145739 20140207135739 63654 dnsworkshop.org.
                                JYkLiFqvrjqiIlm/bA4CaffJ3Iikos31bfEVb2njjIR+
                                /7dudq9pAj898OVZrtqIjmfD7knyCT2nt6Gp/yFYif4k
                                Tt7W2XMhnWecwRnFexhVYp1zg2dkZSw4XcBRMz/F2NkM
                                0xziG9dNFg/6AAs/0ehMurLvRj1ula/UIO/wU5w= )

delve is a very useful tool, not only for BIND 9 admins, but for everyone who needs to troubleshoot and fix DNS- and DNSSEC related issues.

08 Feb 2014

Compiling BIND 9.9.5 on OpenBSD

while compiling BIND 9 Version 9.9.5 on OpenBSD, I've got

making all in /usr/src/bind-9.9.5/lib/lwres/unix/include/lwres
gcc  -I/usr/src/bind-9.9.5 -I./unix/include  -I. -I./include -I./include
- -I/usr/src/bind-9.9.5/lib/isc/include  -I../../lib/isc
- -I../../lib/isc/include  -I../../lib/isc/unix/include
- -I../../lib/isc/nothreads/include  -I../../lib/isc/x86_32/include
- -g -O2   -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings
- -Wformat -Wpointer-arith -fno-strict-aliasing  -c gethost.c
gethost.c: In function `copytobuf':
gethost.c:307: error: `uintptr_t' undeclared (first use in this function)
gethost.c:307: error: (Each undeclared identifier is reported only once
gethost.c:307: error: for each function it appears in.)
*** Error code 1

Stop in /usr/src/bind-9.9.5/lib/lwres.
*** Error code 1

Stop in /usr/src/bind-9.9.5/lib (line 103 of Makefile).
*** Error code 1

Stop in /usr/src/bind-9.9.5 (line 107 of Makefile).

adding

#ifdef HAVE_INTTYPES_H
#include <inttypes.h> /* uintptr_t */
#endif


to the file <bind9-source>/lib/lwres/gethost.c fixes this issue (type "uintptr\t" not known). This issue has been reported upstream to ISC and will be fixed in the next BIND 9 release.

22 Dec 2013

a local, augmented root-zone with DNSSEC

Sunday Dec 22, 2013

Table of Contents

Why a local root zone

Sometimes I get this question in my DNSSEC training classes: "now DNSSEC seems to be a good technology, but the root-zone is controlled by the US government. Because of that, can we trust DNSSEC?".

My answer is not to mix technology (DNSSEC) with implementation (the DNS system of the Internet).

Both are separate. While I can understand that some people do not trust the organisations in control of the Internet DNS root-zone, I see no flaw in DNSSEC (at this moment).

One way to solve the trust issue with the Internet root-zone is to host your own root-zone for the Internet. Then you are in full control of that zone. Have that zone in your own network, or on your Laptop computer und use it for the starting.point of all DNSSEC validation (the trust anchor) for DNS.

Besides the trust question, there might be another reason to operate a local root-zone: some organisations have created an internal, private top-level domain (TLD)1. A local, dnssec-signed root-zone enables the operator to remove or add any delegations, while still being able to validate all DNSSEC signed data in the Internet, as well as data that is stored in their own private DNS namespace.

The following tutorial explains the steps required to generate a local augmented and DNSSEC signed root-zone. The tutorial requires some understanding of DNS concepts and basic knowledge on DNSSEC. A good starting point to learn about DNSSEC (besides a training) is the book DNSSEC mastery by Michael W. Lucas.

All the tools used are part of the BIND DNS Server for ISC (Internet Systems Consortium). This tutorial has been tested using BIND 9.9.4-P1. Older or newer versions of BIND might require a different setup.

The setup

We need one or more authoritative servers to host the augmented root-zone. For production deployments in an internal network, at least two authoritative servers are required. For a local root-zone on a mobile device (Laptop etc.), one single authoritative server might be good enough.

We also need at least one caching DNS server (smart resolver). This cannot be the same DNS server instance as the authoritative server, however it is possible to run both (caching and authoritative server) on the same machine, but have them listen to different IP addresses. In this tutorial, I will use two separate machines:

  • authoritative server: a.myroot-server.loc:192.0.2.53
  • caching server: cache.loc:192.0.2.153

On both servers, the BIND configuration file will be in /etc/named.conf and the BIND "data" directory will be /var/named.

The operating-system used is Debian 7.x.

Authoritative Server (DNS root-server)

Root-Zone

The starting point is the official root-zone. The "F" root-server allows zone transfer of the full root-zone (alternatively, the root-zone can be downloaded by ftp from ftp.internic.net).

shell> mkdir -p /var/named/root
shell> cd /var/named/root
shell> dig @f.root-servers.net . axfr +onesoa | grep -v DNSKEY > root.zone
shell> named-checkzone . root.zone

The grep command will remove the public DNSSEC keys (the DNSKEY records) from the zone, as we will use our own DNSSEC keys for signing the root zone.

The command named-checkzone will test if the zone is completely transferred and will load. Expect to see a couple of "glue record" warnings from the tool, we can ignore them.

Next, we create a new Zone-Signing-Key (ZSK) and a Key-Signing-Key (KSK) for the root-zone:

shell> dnssec-keygen -K /var/named/keys/ -a RSASHA256 -b 2048 -n ZONE .
shell> dnssec-keygen -K /var/named/keys/ -a RSASHA256 -b 4096 -f KSK  -n ZONE .

Now we copy the new DNSKEY records into the root-zone file2:

shell> cat ../keys/K.+008+*.key >> root.zone

The official Internet root-zone authoritative servers have names in the root-servers.net domain. As we do not have the private key for that name, and we cannot enter a DS record (delegation signer) for our internal root-server into the .net zone, we need to change the NS records and the SOA record. In my example, the hostname of the local root-server is in the myroot-servers.loc domain. That name is stored inside the loc. TLD, which we will also host on our authoritative server.

With an text editor, we change the SOA record and the NS record(s) to point to our own authoritative servers. We also need to add proper glue records for every hostname used in the NS records:

.                       86400   IN      SOA     a.myroot-servers.loc. hostmaster.loc. 2013122200 1800 900 604800 86400
.                       518400  IN      NS      a.myroot-servers.loc.
loc.                    86400   IN      NS      a.myroot-servers.loc.
a.myroot-servers.loc.   86400   IN      A       192.0.2.53

Make sure that all other NS records for the root zone "." have been removed.

Now we can sign our zone:

shell> dnssec-signzone -o . -t -R -S -K /var/named/keys/ root.zone
Fetching ZSK 15795/RSASHA256 from key repository.
Fetching KSK 50434/RSASHA256 from key repository.
Verifying the zone using the following algorithms: RSASHA256.
Zone fully signed:
Algorithm: RSASHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 1 active, 0 stand-by, 0 revoked
root.zone.signed
Signatures generated:                      528
Signatures retained:                         0
Signatures dropped:                          3
Signatures successfully verified:            0
Signatures unsuccessfully verified:          0
Signing time in seconds:                85.686
Signatures per second:                   6.161
Runtime in seconds:                     89.025

The -R switch removed all signatures created by the DNSSEC keys of the real root zone. The -t switch prints out some benchmark information. Your signing process is probably faster, as I tested this on a Rasberry Pi.

the augmented ".loc" TLD-Zone

Below is the content of the zone-file for the .loc TLD zone. It contains the same NS records as we have seen in the root-zone for the delegation of the .loc zone:

$TTL 86400
loc.                    86400   IN      SOA     a.myroot-servers.loc. (
                                                hostmaster 1 1d 2h 41d 1h )
loc.                    86400   IN      NS      a.myroot-servers.loc.
a.myroot-servers.loc.   86400   IN      A       192.0.2.53

The .loc TLD should also be DNSSEC secured, so we create a set of keys for this zone as well:

shell> dnssec-keygen -K /var/named/keys/ -a rsasha256 -b 2048 \
              -n ZONE loc
shell> dnssec-keygen -K /var/named/keys/ -a rsasha256 -b 4096 \
              -f KSK -n ZONE loc

The BIND configuration file

This is the BIND configuration file named.conf for the authoritative server. It loads both the root-zone and the .loc private TLD. Both zones are configured as dynamic zones. After loading the zones into the BIND DNS Server, you cannot change the zone content with an text editor anymore. You need to use nsupdate instead. I highly recommend nsupdate, as it catches a number of errors that can occur when editing zone file manually:

options {
        directory "/var/named";
        key-directory "keys";
        dnssec-enable yes;
        dnssec-validation auto;
        dnssec-lookaside auto;
        recursion no;
};

zone "." {
        type master;
        file "root/root.zone.signed";
        update-policy local;
        auto-dnssec maintain;
};

zone "loc" {
        type master;
        file "master/loc.zone";
        update-policy local;
        auto-dnssec maintain;
};

This is the time to check the BIND configuration and all zone-files:

shell> named-checkconf -z
zone ./IN: loaded serial 2013122201 (DNSSEC signed)
zone loc/IN: loaded serial 1 

If named-checkconf does not report any errors, we start our DNS Server (from the command-line or using the start-script):

shell> named
shell> tailf /var/log/syslog
22-Dec-2013 14:39:27.405 starting BIND 9.9.4-P1 -g
22-Dec-2013 14:39:27.407 built with '--libdir=/usr/local/lib'
22-Dec-2013 14:39:27.409 ----------------------------------------------------
22-Dec-2013 14:39:27.411 BIND 9 is maintained by Internet Systems Consortium,
22-Dec-2013 14:39:27.412 Inc. (ISC), a non-profit 501(c)(3) public-benefit
22-Dec-2013 14:39:27.412 corporation.  Support and training for BIND 9 are
22-Dec-2013 14:39:27.412 available at https://www.isc.org/support
22-Dec-2013 14:39:27.412 ----------------------------------------------------
22-Dec-2013 14:39:27.414 using 1 UDP listener per interface
22-Dec-2013 14:39:27.418 using up to 4096 sockets
22-Dec-2013 14:39:27.471 loading configuration from '/etc/named.conf'
[...]
22-Dec-2013 14:39:28.143 zone ./IN: loaded serial 2013122200 (DNSSEC signed)
22-Dec-2013 14:39:28.148 all zones loaded
22-Dec-2013 14:39:28.150 running
22-Dec-2013 14:39:28.152 zone ./IN: sending notifies (serial 2013122200)
22-Dec-2013 14:39:28.159 zone ./IN: reconfiguring zone keys
22-Dec-2013 14:39:28.172 zone ./IN: next key event: 22-Dec-2013 15:39:28.159

The .loc TLD needs to be signed, we do that using rndc:

shell> rndc sign loc

As rndc sign does not report some types of errors, we check if the .log zone is now really signed:

shell> dig -t soa loc +dnssec +m @localhost
; <<>> DiG 9.9.4-P1 <<>> -t soa loc +dnssec +m @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31525
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;loc.                   IN SOA

;; ANSWER SECTION:
loc.                    86400 IN SOA a.myroot-servers.loc. hostmaster.loc. (
                                3          ; serial
                                86400      ; refresh (1 day)
                                7200       ; retry (2 hours)
                                3542400    ; expire (5 weeks 6 days)
                                3600       ; minimum (1 hour)
                                )
loc.                    86400 IN RRSIG SOA 8 1 86400 (
                                20140121142448 20131222132448 38865 loc.
                                cDBUly3QhZ0dm6HJboA/UQPYkMLFK3pWGOt8x98pzY+W
                                oD3cBult7trdxAqNgMuyl5nTZbciEU0o0HNKZlr9cJ75
                                sxqY2PbKjPyZ63t9837LRIoWQtce62M+uP9KLnbaBXrw
                                x9eeyUofy8hNFRstGwoTuDqT5s0GgcUBGjpOWS3vyQB2
                                zAj1cNvy8Mr9sTdxw84VdM7np30dn6z/9IrGurVD3Etz
                                YXo94QgZrNMExqV2u9vYE+tJWldeo+swbwctWH6f/oqC
                                jvOArSiR378h0XiHq11IzM4cjx0IwW0rsVYmD+dhwsEm
                                svLsY66mZRKqyskaXXbbIOUoXWrydwiv+Q== )

;; AUTHORITY SECTION:
[...]

Yes, we see a RRSIG signature for the SOA record, so the signing process was successful.

To create a full DNSSEC chain-of-trust from the .loc TLD to the local root-zone, we need to add the DS record (delegation signer) into out private root-zone. We create the DS-Record from the KSK of .loc

shell> dnssec-dsfromkey /var/named/keys/Kloc.+008+38611.key
loc. IN DS 38611 8 1 FBBBF41938C6CA0E286675F9BBD38C7719217B89
loc. IN DS 38611 8 2 52F2B009BCD019B9AE2470EAE321DAE74AE77B58F094778BCCD9A53AF38A30F8

… and use nsupdate to add the DS-Records to the root-zone:

# nsupdate -l
> ttl 86400
> add loc. IN DS 38611 8 1 FBBBF41938C6CA0E286675F9BBD38C7719217B89
> add loc. IN DS 38611 8 2 52F2B009BCD019B9AE2470EAE321DAE74AE77B58F094778BCCD9A53AF38A30F8
> send
> quit

Our authoritative server is now ready. Next is the caching server(s).

the Caching Server configuration

We start with a basic BIND named.conf configuration file for a caching, validating DNS Server:

acl myclients { 192.0.2.0/24; localhost; };

options {
        directory "/var/named";
        allow-recursion { myclients; };
        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;
};

logging {
    channel syslog { syslog daemon; severity info; };
    channel security { file "security.log" versions 10 size 50M; print-time yes; };
    channel query_log {
      file "query.log" versions 10 size 50M; severity debug; print-time yes;
    };
    category general       { syslog; };
    category security      { security; };
    category queries       { query_log; };
    category dnssec        { security; };
    category default       { syslog; };
    category resolver      { syslog; };
    category client        { syslog; };
    category query-errors  { query_log; };
    category edns-disabled { syslog; };
};

managed-keys {
  "." initial-key 257 3 8      "AwEAAcFN/moqnq1SxdGnZW9JigGYgmFx5WN68RKJ90Je
                                61LJVXi8pKFRz+rajcAu7g7hb0o56RGShWkIWJAosOGr
                                O4onzJ5t+h+rwRNe7EX++KI9XJobzHp+LQiOi/eo2cze
                                91oik9+9Tr+NzyJsssOEq9X/mm9hP44a8YgqSzR+rwCb
                                8jeB9WPhQk25Sp7qN3o8WLCfDxFy6ioOFa7MFirUa1dK
                                30B92X10JN0KA3d0UmOJ3GU50T0WSbWq15k28qX0et/M
                                W3Wl3T5CclG0goM19ET0iQPJh4mN3Gdw9bHqDyiPsqeP
                                MRJNzjb+EgK+MOp3eAqbQ1hlnr/ruwOMKz6oEIYviec8
                                QWvJShmeY4+rRCL5lzZuQ7AYOQq8QO4jUnqTe2/t/Oqy
                                o6yqOtiwsLjmgnsK11qZojJ9RSzjb1r5D5Icl5UHGNxG
                                O6/CQYJMHFsyksYzc1Brtg1PdyHc1zy/GFNI6QEQzlhQ
                                H1nTa+F2MnoZp3k1Z6PTh+GU1796jNtUhMgy4pN7dOqC
                                35hP3GzaP3/XkXtzWbpZRgcXNahbiKso8eqt3r45MCsK
                                AsW3r3hg+CzujTOjVBveKhGfb3nQvx702IdW6Jy62HWX
                                TvipTuG1Kqw+zWHofR2P0ugAszYQBL7G3Zo45VtEScwP
                                XaWavSbGNnHJH5OQQT6HnDvF8hZP";
};

zone "." {
        type hint;
        file "root.hint";
};

The managed-key is the DNSKEY record of our private root-zone. We get that record with the query:

shell> dig @192.0.2.53 . DNSKEY | grep 257

This will request the DNSKEY record set from the private root-server, the grep will filter out the key-signing-key (KSK) with the flag field of "257"3.

The file root.hint will contain the root-hints (NS records and A/AAAA records of our authoritative DNS servers for the private root-zone):

shell> dig @192.0.2.53 ns .

; <<>> DiG 9.9.4-P1 <<>> @192.0.2.53 ns .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3958
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.                              IN      NS

;; ANSWER SECTION:
.                       518400  IN      NS      a.myroot-servers.loc.

;; ADDITIONAL SECTION:
a.myroot-servers.loc.   86400   IN      A       192.0.2.53

;; Query time: 15 msec
;; SERVER: 192.0.2.53#53(192.0.2.53)
;; WHEN: Sun Dec 22 15:06:50 CET 2013
;; MSG SIZE  rcvd: 77

This data can be redirected into the file:

shell> dig @192.0.2.53 ns . > root.hint

Next, we check that the BIND configuration is error free …

shell> named-checkconf -z

and if no error is shown, we start the BIND DNS Server:

shell> named
shell> tail /var/log/syslog
Dec 22 18:19:13 raspidev named[2384]: automatic empty zone: 9.E.F.IP6.ARPA
Dec 22 18:19:13 raspidev named[2384]: automatic empty zone: A.E.F.IP6.ARPA
Dec 22 18:19:13 raspidev named[2384]: automatic empty zone: B.E.F.IP6.ARPA
Dec 22 18:19:13 raspidev named[2384]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
Dec 22 18:19:13 raspidev named[2384]: command channel listening on 127.0.0.1#953
Dec 22 18:19:13 raspidev named[2384]: command channel listening on ::1#953
Dec 22 18:19:13 raspidev named[2384]: managed-keys-zone: loaded serial 9
Dec 22 18:19:13 raspidev named[2384]: all zones loaded
Dec 22 18:19:13 raspidev named[2384]: running

Now, on the caching server, we should be able to validate out own root zone (watch for the AD-Flag):

; <<>> DiG 9.9.4-P1 <<>> @localhost soa . +adflag +m
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13316
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.                      IN SOA

;; ANSWER SECTION:
.                       86327 IN SOA a.myroot-servers.loc. nstld.verisign-grs.com. (
                                2013122200 ; serial
                                1800       ; refresh (30 minutes)
                                900        ; retry (15 minutes)
                                604800     ; expire (1 week)
                                86400      ; minimum (1 day)
;; AUTHORITY SECTION:
.                       518274 IN NS a.myroot-servers.loc.

;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 22 15:13:02 CET 2013
;; MSG SIZE  rcvd: 118

And we should also be able to validate other data out in the Internet, like the domain name for this blog (dnsworkshop.de or dnsworkshop.org):

; <<>> DiG 9.9.4-P1 <<>> dnsworkshop.de @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60851
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;dnsworkshop.de.                        IN      A

;; ANSWER SECTION:
dnsworkshop.de.         7200    IN      A       91.190.147.212

;; AUTHORITY SECTION:
dnsworkshop.de.         7200    IN      NS      ns2.myinfrastructure.org.
dnsworkshop.de.         7200    IN      NS      ns1.myinfrastructure.org.

;; Query time: 1230 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 22 15:14:16 CET 2013
;; MSG SIZE  rcvd: 115

And we can also validate our augmented .loc TLD that does not exist in the public Internet:

; <<>> DiG 9.9.4-P1 <<>> @localhost a.myroot-servers.loc +adflag
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15859
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a.myroot-servers.loc.          IN      A

;; ANSWER SECTION:
a.myroot-servers.loc.   86400   IN      A       192.0.2.53

;; AUTHORITY SECTION:
loc.                    86399   IN      NS      a.myroot-servers.loc.

;; Query time: 94 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 22 18:22:33 CET 2013
;; MSG SIZE  rcvd: 79

Voila, a DNSSEC signed local root-zone.

The root-zone is a busy place right now. New TLDs are added all the time. Make sure you follow these changes. A good way to get notice of updates in the root zone is to follow @diffroot on Twitter. Please remember, if you followed this tutorial, you need to add the changes using nsupdate, do not use a text editor on the zone files!

Footnotes:

1] I do not recomment hosting a private TLD, it is much easier and less error-prone to run a private DNS delegation on the second or third level of the DNS hierachy, such as private.example.com.

2] Be sure to use the double >> to append to the file, a single > will override the zonefile with the keys. Not what we want.

3] Always double check the key data, there is a slight chance that the sequence "257" will appear in the key material of the ZSK as well!

23 Jan 2013

Mirror - Mirror -- Resources on DNS reflection attacks

NCSC 2013 conference Presentation

RFC and BCP

DNS Monitoring

DNS reflection and amplification attacks

Open Resolvers

Minimal Responses

RateLimit

DNS DDoS

Older posts