If you are searching for a DNSSEC validating DNS server, you can use BIND to do that. In fact, with a current version of BIND, e.g. version 9.10, the dnssec-validation is enabled by default. If you are already using BIND as a recursive or forwarding/caching server, you’re almost done. If not, this is a very basic installation guide for BIND with DNSSEC validation enabled and some notes on how to test it.
I am using a fresh Ubuntu 16.04 LTS installation with BIND 9.10.3-P4, that is:
1 2 3 |
sudo apt-get update sudo apt-get install bind9 sudo service bind9 start |
The configuration files are stored in “/etc/bind/“. To allow DNS queries for the local clients, edit the options ( sudo nano named.conf.options ), add your subnets, e.g.:
1 |
allow-recursion { localhost; 192.168.0.0/16; 2003:51:6012:100::/56; }; |
and restart the server: sudo service bind9 restart.
DNSSEC by Default
The interesting part is that the DNSSEC validation is enabled by default. ;) The “dnssec-validation auto;” option is already present and the “dnssec-enable yes;” option is not needed, because its default is already “yes”. (See here: DNS BIND Security Statements.)
Furthermore, the directory option is already present, too:
1 |
directory "/var/cache/bind"; |
That is, the managed keys are stored here: /var/cache/bind/managed-keys.bind .
Test with Dig
A basic test with dig against a DNSSEC secured domain will show the “ad” flag (authenticated data, see DNS Header Flags), in the header:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
weberjoh@jw-nb12:~$ dig weberdns.de ; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> weberdns.de ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34885 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;weberdns.de. IN A ;; AUTHORITY SECTION: weberdns.de. 180 IN SOA ns1.weberdns.de. webmaster.weberdns.de. 2016051901 14400 1800 604800 180 ;; Query time: 19 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Thu May 19 14:03:59 CEST 2016 ;; MSG SIZE rcvd: 90 |
More relevant, a failure in a DNSSEC secured domain will result in a SERVERFAIL without an answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
weberjoh@jw-nb12:~$ dig sigfail.verteiltesysteme.net ; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> sigfail.verteiltesysteme.net ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 64793 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;sigfail.verteiltesysteme.net. IN A ;; Query time: 58 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Thu May 19 14:04:38 CEST 2016 ;; MSG SIZE rcvd: 57 |
To test (!) the failure, the cd flag (check disabled) can be sent with dig, which reveals the answer, but of course with the cd flag again and not with the ad flag in the answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
weberjoh@jw-nb12:~$ dig sigfail.verteiltesysteme.net +cd ; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> sigfail.verteiltesysteme.net +cd ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39420 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 5 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;sigfail.verteiltesysteme.net. IN A ;; ANSWER SECTION: sigfail.verteiltesysteme.net. 60 IN A 134.91.78.139 ;; Query time: 20 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Thu May 19 14:04:45 CEST 2016 ;; MSG SIZE rcvd: 197 |
Online Test for Clients
More interesting for the clients is an online test whether DNSSEC validation works or not. I am using the one at http://dnssec.vs.uni-due.de. If a client uses the just configured BIND server, the test looks like that:
Congrats! You are now validating domain names.
Stats ‘n Cache
To view some statistics of BIND, execute the following shell command:
1 |
sudo rndc stats |
This appends the statistics into this file: /var/cache/bind/named.stats . Note the “+++ Statistics Dump +++ (1471872885)” beginning of each new dump, while the number in brackets is the unixtime. In my case, for example, this looks like that:
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
+++ Statistics Dump +++ (1471872885) ++ Incoming Requests ++ 611719 QUERY ++ Incoming Queries ++ 64716 A 1 NS 131 SOA 484641 PTR 22 MX 40 TXT 61880 AAAA 279 SRV 9 ANY ++ Outgoing Queries ++ [View: default] 140942 A 53 NS 110 CNAME 154 SOA 143244 PTR 23 MX 2 TXT 134638 AAAA 206 SRV 104142 DS 17265 DNSKEY 2 ANY [View: _bind] ++ Name Server Statistics ++ 416710 IPv4 requests received 195009 IPv6 requests received 328 requests with EDNS(0) received 33 TCP requests received 609642 responses sent 46 truncated responses sent 328 responses with EDNS(0) sent 479303 queries resulted in successful answer 89521 queries resulted in authoritative answer 509101 queries resulted in non authoritative answer 29451 queries resulted in nxrrset 11020 queries resulted in SERVFAIL 89868 queries resulted in NXDOMAIN 152697 queries caused recursion 1881 duplicate queries received 196 queries dropped 611686 UDP queries received 33 TCP queries received ++ Zone Maintenance Statistics ++ ++ Resolver Statistics ++ [Common] [View: default] 363641 IPv4 queries sent 177140 IPv6 queries sent 346942 IPv4 responses received 168436 IPv6 responses received 24977 NXDOMAIN received 4212 SERVFAIL received 32 FORMERR received 118 EDNS(0) query failures 34758 truncated responses received 2516 lame delegations received 87670 query retries 26471 query timeouts 69897 IPv4 NS address fetches 72415 IPv6 NS address fetches 870 IPv4 NS address fetch failed 41590 IPv6 NS address fetch failed 249786 DNSSEC validation attempted 123250 DNSSEC validation succeeded 125845 DNSSEC NX validation succeeded 177 DNSSEC validation failed 180114 queries with RTT < 10ms 223124 queries with RTT 10-100ms 104360 queries with RTT 100-500ms 5988 queries with RTT 500-800ms 1457 queries with RTT 800-1600ms 83 queries with RTT > 1600ms 31 bucket size 7363 REFUSED received [View: _bind] 31 bucket size ++ Cache Statistics ++ [View: default] 5706174 cache hits 3570 cache misses 996705 cache hits (from query) 933523 cache misses (from query) 0 cache records deleted due to memory exhaustion 414200 cache records deleted due to TTL expiration 18385 cache database nodes 8319 cache database hash buckets 11143805 cache tree memory total 7815275 cache tree memory in use 8389020 cache tree highest memory in use 655360 cache heap memory total 263168 cache heap memory in use 271360 cache heap highest memory in use [View: _bind (Cache: _bind)] 0 cache hits 0 cache misses 0 cache hits (from query) 0 cache misses (from query) 0 cache records deleted due to memory exhaustion 0 cache records deleted due to TTL expiration 0 cache database nodes 64 cache database hash buckets 287392 cache tree memory total 29608 cache tree memory in use 29608 cache tree highest memory in use 262144 cache heap memory total 1024 cache heap memory in use 1024 cache heap highest memory in use ++ Cache DB RRsets ++ [View: default] 4045 A 5685 NS 102 CNAME 3751 PTR 1300 AAAA 455 DS 3380 RRSIG 1963 NSEC 301 DNSKEY 4 !A 214 !AAAA 1135 !DS 240 NXDOMAIN [View: _bind (Cache: _bind)] ++ ADB stats ++ [View: default] 1021 Address hash table size 4710 Addresses in hash table 1021 Name hash table size 3925 Names in hash table [View: _bind] 1021 Address hash table size 1021 Name hash table size ++ Socket I/O Statistics ++ 341815 UDP/IPv4 sockets opened 164252 UDP/IPv6 sockets opened 21867 TCP/IPv4 sockets opened 12897 TCP/IPv6 sockets opened 1 Raw sockets opened 341813 UDP/IPv4 sockets closed 164251 UDP/IPv6 sockets closed 21866 TCP/IPv4 sockets closed 12928 TCP/IPv6 sockets closed 36 UDP/IPv4 socket bind failures 6 UDP/IPv6 socket bind failures 21 TCP/IPv6 socket connect failures 341777 UDP/IPv4 connections established 164245 UDP/IPv6 connections established 21699 TCP/IPv4 connections established 12822 TCP/IPv6 connections established 3 TCP/IPv4 connections accepted 33 TCP/IPv6 connections accepted 252 UDP/IPv4 recv errors 1 TCP/IPv6 recv errors 2 UDP/IPv4 sockets active 1 UDP/IPv6 sockets active 6 TCP/IPv4 sockets active 35 TCP/IPv6 sockets active 1 Raw sockets active ++ Per Zone Query Statistics ++ --- Statistics Dump --- (1471872885) |
To view the current cache of BIND, run the following command:
1 |
sudo rndc dumpdb -cache |
This dumps the whole cache into this file: /var/cache/bind/named_dump.db .
It can be listed/grepped as normal, e.g.:
1 2 3 4 5 6 7 8 9 10 |
weberjoh@jw-vm08-int-dns:~$ cat /var/cache/bind/named_dump.db | grep ubuntu ubuntu.com. 172675 NS ns1.p27.dynect.net. de.archive.ubuntu.com. 492 CNAME ubuntu.mirror.tudos.de. ntp.ubuntu.com. 475 A 91.189.89.198 security.ubuntu.com. 492 A 91.189.88.149 ubuntu.mirror.tudos.de. 10692 \-AAAA ;-$NXRRSET 0.ubuntu.pool.ntp.org. 1371 \-AAAA ;-$NXRRSET 1.ubuntu.pool.ntp.org. 1372 \-AAAA ;-$NXRRSET 2.ubuntu.pool.ntp.org. 23 A 5.9.80.113 3.ubuntu.pool.ntp.org. 1374 \-AAAA ;-$NXRRSET |
To delete (= flush) the cache, execute one of the following commands. The first one completely flushes the cache while the second only deletes a certain name:
1 2 |
sudo rndc flush sudo rndc flushname <name> |
Final notes: A much more detailed post about BIND as a caching server is here. And yes, I know that some security people don’t like the usage of BIND for a mere forwarding DNS server. The blog post about Unbound is coming soon. ;) Cheers.
Featured image “Daelim Motorrad Leichtkraftrad FOR SALE nur 9810km!” by naufragoenlasopa is licensed under CC BY-NC-ND 2.0.
hi,
nice blog!
as you use to the bind-tool “dig” you could also mention their tool “delv”?
maybe you could explain why it’s usually imposible to ask the NS server of a domain for a DNSSEC signed answer.
Regards!
Stefan
Yep, thx for the hint. I already did a blog post solely about “delv”: https://weberblog.net/dive-into-delv-dnssec-validation/
“maybe you could explain why it’s usually impossible to ask the NS server of a domain for a DNSSEC signed answer” –> by design, the authoritative name server *never* answers with the “ad” flag, but only with the “aa” flag. That is: it does *not* validate its own zones, because it knows it has the single source of truth concerning its own zones. No need to validate its own data. The authoritative server hands out the signed data (of course), but it does not the validation process.
Does this help?
Ciao
Johannes