By default DNSSEC uses the next secure (NSEC) resource record “to provide authenticated denial of existence for DNS data”, RFC 4034. This feature creates a complete chain of all resource records of a complete zone. While it has its usage to prove that no entry exists between two other entries, it can be used to “walk” through a complete zone, known as zone enumeration. That is: an attacker can easily gather all information about a complete zone by just using the designed features of DNSSEC.
For this reason NSEC3 was introduced: It constructs a chain of hashed and not of plain text resource records (RFC 5155). With NSEC3 enabled it is not feasible anymore to enumerate the zone. The standard uses a hash function and adds the NSEC3PARAM resource record to the zone which provides some details such as the salt.
In this post I will show how to create the KSK and ZSK keys that are NSEC3-capable and how to insert the NSEC3PARAM parameters to the zone. (For an introduction of DNSSEC with BIND refer to this blog post or note the DNSSEC category on my blog.) For now I am using another test domain:
sshfp.net. I will also show some dig commands for verifying the NSEC3 hashes.
NSEC3-Capable Algorithm
The first step to sign the zone is the creation of appropriate keys. The command line interface tool
dnssec-keygenprovides the
-3option: “Use an NSEC3-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. Note that RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256 and ECDSAP384SHA384 algorithms are NSEC3-capable.” I decided to use the RSASHA512 algorithm, so here are my commands for the generation of the KSK and the ZSK, as well as the correct permissions (refer to my lasts posts):
cd /etc/bind/keys/ sudo dnssec-keygen -a RSASHA512 -b 2048 -3 -f KSK -r /dev/urandom sshfp.net sudo dnssec-keygen -a RSASHA512 -b 2048 -3 -r /dev/urandom sshfp.net sudo chmod g+r *.private sudo rndc loadkeys sshfp.net
(I also tried the algorithm number 14, ECDSAP384SHA384, but this did not work at all. rndc was not responding anymore. Maybe this is related to a bug in my BIND version?)
Note that up to this point the mere NSEC is still used for signing the zone. To enable NSEC3, follow the next step:
Adding the Salt
To tell the zone to use NSEC3, the NSEC3PARAM resource record must be inserted. This is done with
rndc signing -nsec3param: “rndc signing -nsec3param sets the NSEC3 parameters for a zone. […] Parameters are specified in the same format as an NSEC3PARAM resource record: hash algorithm, flags, iterations, and salt, in that order.”
There is only one registered hash function that is used for NSEC3, namely SHA1, refer to DNSSEC NSEC3 Hash Algorithms. (Why aren’t there any better hash functions yet? Short discussion here.) SHA1 has value number 1 listed within the nsec3param section. The flags parameter is left by 0. For the hash iterations I chose 10. (Some notes are here.) This sets the cost of computing a dictionary for the attacker, as well as the cost for signing the zone. To my mind 10 is a good starting point but it could be increased if needed.
Finally, a salt must be set to prevent precomputed dictionary attacks. Choose a random salt, e.g., by using a password generator. Some other tutorials recommend a salt length of 8 hexadecimal digits, but it can be much longer. However, I used 8 digits, too. (“The salt SHOULD be at least 64 bits long and unpredictable, so that an attacker cannot anticipate the value of the salt and compute the next set of dictionaries before the zone is published”, RFC 5155 section 12.1.1.)
In the end this is my rndc command to use NSEC3 for my zone called “sshfp.net”:
sudo rndc signing -nsec3param 1 0 10 5053851B sshfp.net.
Without any other commands BIND is now using NSEC3 with the just defined parameters.
Test with Dig
The first step to test is the presence of the nsec3param record. Answer in line 15:
weberjoh@jw-nb12-lx:~$ dig sshfp.net nsec3param +noadditional +noauthority ; <<>> DiG 9.10.3-P4-Ubuntu <<>> sshfp.net nsec3param +noadditional +noauthority ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45143 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;sshfp.net. IN NSEC3PARAM ;; ANSWER SECTION: sshfp.net. 0 IN NSEC3PARAM 1 0 10 5053851B ;; Query time: 5 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Fri Nov 11 15:54:13 CET 2016 ;; MSG SIZE rcvd: 59
The more interesting test case is querying a non-existent domain. With mere NSEC, some plain text FQDNs would be revealed. Not so with NSEC3 which shows many (and long …) hashes, as well as the DNSSEC signatures (which are even longer in my case since I used the SHA512 hash for signing …):
weberjoh@jw-nb12-lx:~$ dig foobar.sshfp.net +dnssec ; <<>> DiG 9.10.3-P4-Ubuntu <<>> foobar.sshfp.net +dnssec ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 24021 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;foobar.sshfp.net. IN A ;; AUTHORITY SECTION: sshfp.net. 159 IN SOA ns1.weberdns.de. webmaster.weberdns.de. 2016090128 3600 900 2419200 180 sshfp.net. 159 IN RRSIG SOA 10 2 86400 20161208021634 20161108011634 31055 sshfp.net. kCY+TA1Q/RdjdzpMc1CHihGB+t4ou8QZPwuhzvkRkrYxicdXY320b+dO akTIcddJinI6dGo70OrRq+cWV9A9IAK7aak0Nonj/V20mHUzCVeaRrqp iBD1RjnKxNRqX5rb+fvf6S4NuzynGP57PWnntLqB/AnDljHcrBhN9IHe i87K0JsK/cmGzPCq9Dz50Tg4/7Pq3kI9p5pfdeRwLXyzIu4cb0BNIDvl MchVhTx/m44UbLdRlA9dzbZQuAZj5k5HqiDZFbwidK98w8AeMMbRy71P D16GvKnoIsOm3Ew+EcX0gCBWqcmccExm5zeiQkLf7KmDdDRVMvdd5uyK yZIE4w== NA9D0NB498S0ROOIF2NGLHQF85HQLKJP.sshfp.net. 159 IN RRSIG NSEC3 10 3 180 20161207204758 20161107195347 31055 sshfp.net. GLqlvFaWiemLree+4WQeR+0ANSEYeuLW/KEWZw9mZPUJ1bcb1OQCxp43 7DNdPCSmS/RqJGiVGtSW8xsGoRgUwOdczL8s4j/z3pVi8wDlhw2jXE0k fGBiOshH+3VjZV4eLlDmDixZ3WmA9gzf0G+qAwRP9tjps2+vqRfXOpoj /UffmcMgZODEDGonHAOX/k35sBL+zIP4k6i6Kq/lpPZd8oxsxCwyxAYl E1oMxeE14TnRZoqCZdAEgvrViF91z/tnMbYAY/JNWYK4iREOuuWTLOox C0hKBsymi3fyLjwZ1NV1Bh3lqYN0rr1uo8ZSZmGrfLdg4l+hO4Xl6kG6 JTn27Q== NA9D0NB498S0ROOIF2NGLHQF85HQLKJP.sshfp.net. 159 IN NSEC3 1 0 10 5053851B PF2TNEL79K4HTCBINCDBE9FPBU5I04KD A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM TYPE65534 PTBUDK4PK9HRK5HKTF5JVSULBP75V0AK.sshfp.net. 159 IN RRSIG NSEC3 10 3 180 20161208011815 20161108010731 31055 sshfp.net. h3TaJpQU9JXAMY7Eu4cjS28rdXxiPpm9VDjugpr71ilpSGo6UCowXaoE 44FMQWqRXj57yXrRyjFS2BDKBa6r5FIG5hM3jye04ksJxoT95ZgH9dVN wXf45oc/vh0v9BFaQi2a/7CFmTeUf36qaEdS1duTaQOMuV9fqLhQhzwQ nga40LIHCFqHJYmOPK2R41fn8VfpxD2fI95oCYCtLr6HQkmQ2uGWGSvF fxi+zAs0I1O5zyoc6JedbX7mFVs63/6B2Q9H9rYZbPnm92Py/OKTCR9Z kX1/6NA2DQZuTJKaZf7q/qKOdSmmkX7Np8Nc52Evdzw6yTFKT031SN8X L9UNWQ== PTBUDK4PK9HRK5HKTF5JVSULBP75V0AK.sshfp.net. 159 IN NSEC3 1 0 10 5053851B 4B37B7ENKCCOB0IM83C004NA76LA3V4T A RRSIG ;; Query time: 1 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Fri Nov 11 15:58:09 CET 2016 ;; MSG SIZE rcvd: 1198
In fact, no other DNS leaves are revealed with this query. Great!
Changing the Salt
“The salt SHOULD be changed periodically to prevent pre-computation using a single salt”, RFC 5155 section C.1.
Ok, so let’s change the salt exemplary. This is really simple because it only requires the single rndc command I already showed. For this example I increased the size of the salt to 32 bytes (128 bits) as well as the hash iteration from 10 to 20:
sudo rndc signing -nsec3param 1 0 20 80637d8af055b5eeca2a621edaaa3c5e sshfp.net.
Without any problems BIND signed the complete zone with this new parameters. Here is the new nsec3param answer:
weberjoh@jw-nb12-lx:~$ dig sshfp.net nsec3param ; <<>> DiG 9.10.3-P4-Ubuntu <<>> sshfp.net nsec3param ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48904 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 4 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;sshfp.net. IN NSEC3PARAM ;; ANSWER SECTION: sshfp.net. 0 IN NSEC3PARAM 1 0 20 80637D8AF055B5EECA2A621EDAAA3C5E ;; AUTHORITY SECTION: sshfp.net. 172800 IN NS ns1.weberdns.de. sshfp.net. 172800 IN NS ns3.weberdns.de. sshfp.net. 172800 IN NS ns2.weberdns.de. ;; ADDITIONAL SECTION: ns1.weberdns.de. 86400 IN A 80.154.108.230 ns1.weberdns.de. 86400 IN AAAA 2003:51:6012:110::a07:53 ns2.weberdns.de. 86400 IN A 213.61.29.182 ;; Query time: 150 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Mon Nov 14 11:20:00 CET 2016 ;; MSG SIZE rcvd: 196
And the NSEC3 answer for a non-existent domain which also shows the new salt, etc. Note that some NXDOMAIN answeres have 3 different NSEC3 records, refer to RFC 7129, section 5 (a litte bit complicated though). Furthermore note that for the following listing I wrapped the lines in the output to see the whole big bunch of the answer :
weberjoh@jw-nb12-lx:~$ dig foobar.sshfp.net +dnssec ; <<>> DiG 9.10.3-P4-Ubuntu <<>> foobar.sshfp.net +dnssec ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 12968 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;foobar.sshfp.net. IN A ;; AUTHORITY SECTION: sshfp.net. 180 IN SOA ns1.weberdns.de. webmaster.weberdns.de. 2016090133 3600 900 2419200 180 sshfp.net. 180 IN RRSIG SOA 10 2 86400 20161214101931 20161114091931 31055 sshfp.net. jh67fVaz7t9W5JGtgd+Ac3IxmT6hVVIHGzvzpikZ01ITZmtR6vE/A1/Y AZidYoTtSbVOO396cwewtMR+VjS8zP/LrYzZoKSmHVY7sqLYKhV7Cw/O xcDxwIo3/EWPSuu2xNzONGVwlZ9MPvFk7PIql7O1/mFNRNygP3oZWLIW 7yTEs28LRmFl/4l3jrFXGoZtk/IxaWCVONrqW0ThfUzppN1U6bSiFLkA PT2NajPPQaUoSHBME7PNy8fQMEUzijqfD1p+++KSQlChUN6ccedm0AXK 2Cf42k7g4zSPlDenSNYNWZ9M09Pl3Ctkw17LN0wYqqE70jtyR8Y9qVJ7 fNlqcA== 1009PRUOMI99TQ7NKVD75UH5KSVG82EV.sshfp.net. 180 IN RRSIG NSEC3 10 3 180 20161214094443 20161114091931 31055 sshfp.net. Z305JjP/bCNjuLhbgx0UheRQq0ZyZgzwYiy59D0Dnxb9NO3B/caVlM0S OnqM6zjkM+xpX8QGGMVrM4xVfya/4ajOFf7/c6CL03i0v+UQ6nyPcZ5j 17hpetBW1RpTkLXnpXTfaGtNYbBC4scMj41kU9Gxj2jophQ34dgcZkJ9 lBsLQjfKva1IQOyUTBrWVo8+zjj0k07P3n3ocEp3UXf62LZEurCaMmaM iQvOsWtVDOVjsI8lmQR3d3jelCuRkXBEa7tFfFsf0jWKZ6lbTLoSXGMz RQGKQqOy7yQUjxQbuQ6vBf+N6mAe0YGH56sm1+Z/SScgpnpTAviDF9nx rj4Sow== 1009PRUOMI99TQ7NKVD75UH5KSVG82EV.sshfp.net. 180 IN NSEC3 1 0 20 80637D8AF055B5EECA2A621EDAAA3C5E 3J6JP5RLFGU7E10AMBAKNT7UGEBP6IUI A RRSIG F5AFOMBUT7BNO1I94Q43Q6F1KJAKEJB5.sshfp.net. 180 IN RRSIG NSEC3 10 3 180 20161214092455 20161114091931 31055 sshfp.net. nCAgLDaro/t1MixVVIg2ClnnGuZ8C8YVVt1VwKJWfJr7N8JFKILJGjkM GKvvRltQAfNtTpBmUYYwP7HXDISoL3X3ruM5PNZwBNjJ0x+E7LU9MCb7 uBhuoE9eKP69L9IGefUWzL5UZYW+T288V1bjayVNZi4UsZY7TwY2WDcJ Ef25HuvZskBooTgePf5+++kZti8Qm13rwh65jSSzQQPP2OjdwZJic1HP bwqGjnu2RzzxzSfHLQvyz9Xny43uT9IImZCSwTJW/bhsghhRiv79HK8o dPqWW+l5xqdbgTTwM9Rw52k6MboU+pD1z4HAFxEjZ5iq6H81WRZLfnOq ig59OA== F5AFOMBUT7BNO1I94Q43Q6F1KJAKEJB5.sshfp.net. 180 IN NSEC3 1 0 20 80637D8AF055B5EECA2A621EDAAA3C5E QOERG35FBV9KBEKT0HHJ603KARPRHA6E A RRSIG VLQ247QI8P1TT3A8CGMD7GLFNDTIGSDU.sshfp.net. 180 IN RRSIG NSEC3 10 3 180 20161214092455 20161114091931 31055 sshfp.net. f62YeWWFM9+d+jqVRJWVHkkgLL740EO6fCv5sQghuRCCJTzZbehRN365 3X5YNvOFvbZtR7i41SGV2+XXV5U8JgqzW0jc9+bw2k8lK2cQF/nfodLN RSoxymiqN6mNesEsb3ovCDTamB5gSCs7bj+iT7pS8NqtctkhTRYDPJAT lAId0H6cmL486msfeziU2fAelHx++Tc29II7PhYN87VOgtWQV02omkG1 Ysp8NCm4KQbuXQnXZ9aF6nFIIB70sA95kyND4dt0WNXkRwR0CUrv53sM X2Pvcop56jl3ssdgLqb79BlYU/dZrfhUjpLXfAXaRFp3jSvukSj9qcYu bsS6bQ== VLQ247QI8P1TT3A8CGMD7GLFNDTIGSDU.sshfp.net. 180 IN NSEC3 1 0 20 80637D8AF055B5EECA2A621EDAAA3C5E 1009PRUOMI99TQ7NKVD75UH5KSVG82EV A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM TYPE65534 ;; Query time: 9 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Mon Nov 14 11:21:14 CET 2016 ;; MSG SIZE rcvd: 1614
That’s it. Good luck.
Links
- RFC 5155: DNS Security (DNSSEC) Hashed Authenticated Denial of Existence
- RFC 7129: Authenticated Denial of Existence in the DNS
- ISC Knowledge Base: In-line Signing With NSEC3 in BIND 9.9+ — A Walk-through
- IANA: Domain Name System Security (DNSSEC) Algorithm Numbers
- IANA: Domain Name System Security (DNSSEC) NextSECure3 (NSEC3) Parameters
- Long-term Memory: DNSSEC – the NSEC and NSEC3 record
- [DE] Blog von Emanuel Duss:DNS Zonen mit DNSSEC signieren (mit Bind)
Featured image: “Chain” by Astro is licensed under CC BY 2.0.