LINUXMAKER, OpenSource, Tutorials

Configuration of DNSSEC on BIND9

Setting up DNSSEC is to be demonstrated here in BIND9 on a Debian Linux system. Provided that a functioning DNS BIND server already exists as described here.

Requirements

All configuration files for Bind9 are in "/etc/bind/", on RedHat, Centos and Fedora Linux systems the filing structure is somewhat different from Debian. And the zone files are generally below "/var/cache/bind/" structured according to the TLD in their own directories such as "de", "com" etc.

Zone Walking and NSEC3

Zone walking (DNSSEC walking or zone enumeration) is known as a method by which attackers can read out the complete content of DNSSEC-signed DNS zones. In this way, confidential data (such as customer lists) and security-relevant information (server IP addresses) can be tapped.
DNSSEC automatically chains all labels in a ring in alphabetical order when signing a zone using NSEC Resource Records. It looks like this using the example of the zone example.tld
    example.tld. NSEC name1
    name1         NSEC name2
    name2         NSEC name5
    name5         NSEC example.tld.

On the left is the label (canonical name) and on the right a reference to the next lexographic label. In this way, the non-existence of names can be proven. So if a client asks for the non-existent name name3, then the DNS server replies with the NSEC entry name2 NSEC name5 and thus signals that there is no further entry between name2 and name5. The attacker takes advantage of this chaining by starting with the first name of a zone (this is always the name of the zone itself) and running through the chain through successive queries. Thanks to this technically quite simple process, he can read out the entire zone content within a few seconds.

Defense with NSEC3

Zone walking makes it significantly more difficult with the alternative to NSEC, namely NSEC3. NSEC3 no longer displays the names in plain text, but as a cryptographic hash value. Although NSEC3 makes zone walking more difficult, attacks on the hash function cannot completely avoid zone walking. Therefore the following configuration should be done with NSEC3.

DNSSEC, KSK, ZKS and RRSIG

First, here is the view of DNSSEC, KSK, ZKS and RRSIG.

For each zone that is to be secured, a separate zone key (zone signing key) consisting of a public and a private key is generated. The public part of the ZSK then exists in the respective zone file as a DNSKEY resource record. With the private key, however, each individual RR in the zone is then digitally signed.

In addition to the key for the signature of the zone (ZSK), a syntactically identical key signature key KSK (Key Signing Key) is generated. The background to this is the fact that the zone keys (DNSKEY) can change more often and, in the case of a chain of trust, the parent zone would no longer trust the child zone. However, since in this case the KSK remains the same for a long period of time, the chain of trust between the parent and child zones is retained in the event of changes. Otherwise, the child zone would have to continuously provide the parent zone with new keys, which can be very inefficient and prone to errors.

Ultimately, the zone is signed using the DNSKEYs, while the resource records are signed using the RRSIGs.

Generate key signing key (KSK)

For the sake of better structuring, we first create a new directory within the Bind9 configuration directory.

mkdir -p /etc/bind/keys/
chown -R bind:bind /etc/bind/keys/

The KSK is generated within this new directory with the following command:

dnssec-keygen -3 -a RSASHA512 -b 4096 -n ZONE -r /dev/urandom -f KSK example.tld

  • -3 activates the desired NSEC3
  • -a determines the type of signature
  • -b indicates the desired block size
  • -n specifies the name type such as ZONE, HOST, USER
  • -f this flag must be set especially for KSK

There are now two files in the directory:

  • Kexample.tld.+010+64413.key (DNSKEY Record),
    which serves to verify the ZSKs and is signed by higher zones.

  • Kexample.tld.+010+64413.private,
    the private key to the signature of the public ZSK.

The DNSKEY record in the public key looks something like this:

cat Kexample.tld.+010+64413.key
; This is a key-signing key, keyid 64413, for example.tld.
; Created: 20200313175118 (Fri Mar 13 18:51:18 2020)
; Publish: 20200313175118 (Fri Mar 13 18:51:18 2020)
; Activate: 20200313175118 (Fri Mar 13 18:51:18 2020)
example.tld. IN DNSKEY 257 3 10 AwEAAaoJiFk+Xj+9v[...]KTMN4QNqRm8l1RgnDq/2GvrxmSPXfGKyWm fjvSJot4EX2i97ER

Generate Zone Signing Key (ZSK)

The zone signing key is then generated as follows, followed by a reassignment of the file attributes.

dnssec-keygen -3 -a NSEC3RSASHA1 -b 2048 -n ZONE -r /dev/urandom example.tld
chown -R bind:bind /etc/bind/keys/

Now there are two more files in the directory:

  • Kexample.tld.+007+40385.key,
    the public key (DNSKEY record), which is used to verify the DNS responses.
  • Kexample.tld.+007+40385.private,
    the private key for signing the resource records.

The content of this ZSK is roughly as follows.

cat Kexample.tld.+007+40385.key
; This is a zone-signing key, keyid 40385, for example.tld.
; Created: 20200313175211 (Fri Mar 13 18:52:11 2020)
; Publish: 20200313175211 (Fri Mar 13 18:52:11 2020)
; Activate: 20200313175211 (Fri Mar 13 18:52:11 2020)
example.tld. IN DNSKEY 256 3 7 AwEAAauXGNQMitXTRPKAkme9[...]Mqi3ZvO 0yn19+nxfb8=

Sign the zones yourself

Now the zone in the respective zone file can be prepared for the signature by adding the public key using the $ INCLUDE directive. On the one hand, this can be easily done using a loop

for key in `ls Kexample.tld.*.key`
do
echo "\$INCLUDE /etc/bind/keys/$key">> /var/cache/bind/tld/db.example.tld
done

or individually per zone file with a vi function:

:r! ls /etc/bind/keys/Kexample.tld.*.key

Signing creates a new zone file with the suffix ".signed".

dnssec-signzone -3 `head -c 512 /dev/urandom | sha1sum | cut -b 1-16` -z -H 330 -K /etc/bind/keys -t -o example.tld /var/cache/bind/tld/db.example.tld

Verifying the zone using the following algorithms: NSEC3RSASHA1 RSASHA512.
Zone fully signed:
Algorithm: NSEC3RSASHA1: KSKs: 0 active, 0 stand-by, 0 revoked
                         ZSKs: 1 active, 0 stand-by, 0 revoked
Algorithm: RSASHA512: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 0 active, 0 stand-by, 0 revoked
/var/cache/bind/tld/db.example.tld.signed
Signatures generated:                       26
Signatures retained:                         0
Signatures dropped:                          0
Signatures successfully verified:            0
Signatures unsuccessfully verified:          0
Signing time in seconds:                 0.315
Signatures per second:                  82.418
Runtime in seconds:                      0.358

chown -R bind:bind  /var/cache/bind/

However, it should now be noted that after every change in the zone file, it must also be re-signed.
In addition, the signed zones are only valid for 30 days by default. You can give dnssec-signzone your own end date for the validity of the signed zone file with "-e YYYYMMDDHHMMSS".

Activate DNSSEC in BIND9

In the global options of BIND9 you activate DNSSEC with the following entries in /etc/bind/named.conf.options

dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;

key-directory "/etc/bind/keys/";

In the file /etc/bind/named.conf.local you only change the file of in the zone declarations

zone "example.tld" {
        type master;
        file "tld/db.example.tld";
        allow-transfer {
                "slaves";
        };
        notify yes;
};

to

zone "example.tld" {
        type master;
        file "tld/db.example.tld.signed";
        allow-transfer {
                "slaves";
        };
        notify yes;
};

and restart the BIND9

systemctl restart bind9.service

Provide the DNSSEC key to the registrar

Finally, the DNSSEC must be activated with your own registrar. This happens on their web portals by entering the DNSKEY RR to match the zone and also DS Record. To do this, wait until the AXFR of the registrar's name server has taken place and a positive query

dig DNSKEY example.tld

returns the DNSKEY. Then you know that the zones have synchronized. The DNSSEC is displayed for both the zone key (256) and the key signature key (257). The registrar must be entered with the flag 257. In addition, the delegation signer record (DS-RR) - this contains the digest of the KSK public key - must be entered. The latter is in an additional file "dsset-example.tld." in the directory from which you started "dnssec-signzone", the contents of which can be adopted:

cat dsset-example.tld.

example.tld.            IN DS 40385 7 1 CDD805F6E544091910FF821AEB6D83756F02A23E
example.tld.            IN DS 40385 7 2 75D763812727198BD0B5FD4F5FCA59B96262D0EF390A435829FC66E8 9492D462
example.tld.            IN DS 64413 10 1 43DF817F6558611A58617C8017338F76E6015AE5
example.tld.            IN DS 64413 10 2 096EEEFF5E66BA5DC03930D3A567BE57247FEDDFBAFB5142508B24CB B2B153F8

Testing the DNSSEC

If you now query the DNS server or other name servers, provided that you have already activated the DNSSEC with your registrar, you will get this information.

dig example.tld dnskey +noall +answer +multiline

; <<>> DiG 9.11.5-P4-5.1-Debian <<>> example.tld dnskey +noall +answer +multiline
;; global options: +cmd
example.tld.            86400 IN DNSKEY 257 3 10 (
                                AwEAAaoJiFk+Xj+9vRrKq2pdaFkwCKaGy1QNMbn/aQYT
                                G5czj9aO/o400mS8YfEMGC3U+AY0INliajs7sfeVuuFv
                                JYbmkLpJGIbF1/3Tr/8jzENJSEqxCh6y5iFz7HdgMat8
                                +TekfyaDf30reM61l8G1BN3fcaFHf2DRv0+AkD/eY/kd
                                Id+ngvQ1ifzk3tZNxIjeClEdQ7D2OTAazagcDl+vSKWh
                                zo3iSwyjMnboAo0RdHMKSuxgSDkMOch9DIih5SVKRZy5
                                zq9kJfuCPpgVAnjjB2oZ0K2rpKu2FPHhV5zV9T2m2cBw
                                YpldTobuAN8Ouj8m72y4RdrI5ik1GOA4HzlUg0zKnaLh
                                L1Y+Mxo2Qz9hJMJ+rKifpcY72e5/FX9addolaqOjBX44
                                FvHJWaxcAjVVqFfPfgkMLMtcJY0YVMr694rNecfAFfVh
                                n8UwQk9epq1xDI3D1pH8/HzmEdM7lK9FLIx++fDtkpXq
                                V7f5dorwm92kGZpdtZ/LeCnFGpfLNeu4heQJ587pnwap
                                j/wbNUF4IPuTkuEpKJReQzWQ0gWp0yU3kDn7vcXD7Eee
                                +3Atoobq6wwOsrkUXl1FVaF3rOm6L82S3dvtB/SSuHCF
                                jcdy33tlv1nE5cjaBZHRChKTMN4QNqRm8l1RgnDq/2Gv
                                rxmSPXfGKyWmfjvSJot4EX2i97ER
                                ) ; KSK; alg = RSASHA512 ; key id = 64413
example.tld.            86400 IN DNSKEY 256 3 7 (
                                AwEAAauXGNQMitXTRPKAkme9Gs7MvrHgNeNJddafYO7F
                                5i/TsLre8zitWD/+bJZXx0Vu89QTjKX9zQwhSRegwFvH
                                4gfe4Hvo0SHt9YsMGwA1LDW9RfFXDCGWEemDnAxX0NV9
                                330BSYyQ2fVrPpJoyB+et/BrLi/IzBrrFXB+O24jkBYW
                                TK0khA9c1lAk//nWEVstarXZgmz2WlF4//aPUpGqOnDL
                                jbv1gXo3vUfcSBN2EcAaXAyTSGTaJUA6I6BEFbN1id2g
                                bFI/RsVa0dYo3imvn46IgroVmDhx+LbKlMq71GhePyaW
                                zaZX8Bmi8Y9IxlJV5+UizMqi3ZvO0yn19+nxfb8=
                                ) ; ZSK; alg = NSEC3RSASHA1 ; key id = 40385

If you use the +dnssec option in dig, the RRSIG records are also displayed:

dig A www.example.tld +dnssec

; <<>> DiG 9.11.5-P4-5.1-Debian <<>> A www.example.tld +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45983
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 7, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
; COOKIE: e6717cb28dcc8637149ebe435e6f790ddf6237e8cfc03713 (good)
;; QUESTION SECTION:
;www.example.tld.               IN      A
;; ANSWER SECTION:
www.example.tld.        86400   IN      A       79.143.191.49
www.example.tld.        86400   IN      RRSIG   A 7 3 86400 20200415110953 20200316110953 40385 example.tld. DYnaFMQaVpOO3VA8ZYg7K3YKHMgl4+UFLXjgUt35GLYLrUwO5XKQwr+T LKlBukkIgC2zUVVZSuIGoDv8rDGCeBED2d0KrnVjdQjqS00ZUOCGUU27 vagd/u6DuHUF0VVWgHU8fjWG1+S4rqRov3pSQ0gCq5JaYFOZZXeKCcq4 cmcL/9dQbdL5h1JArqxJoNtQOnlKw7JtifWAHRtWPX7eQ4tbq6TA9fR3 SQ/nde4ZP6dRDyv2OcO3lpfhc/JDbeyksu11nfp8WLjjDTsY5D2mC4bA a0kL9H357OiKtLiwLSCOM/zYa/gq+2wUDOSnG/zX7jfKvDr+rQWKcAvV l1/apg==
www.example.tld.        86400   IN      RRSIG   A 10 3 86400 20200415110953 20200316110953 64413 example.tld. kCA+W2mn/Hvgx50L51DJzMqRluiYp/m2Gb8DLHqNmu7kSNmFYmpq+jvk caEcBroZaoyalsGAFJas+NlYHQGZFyzJKav1dujb0I8nUDsG7TGnmH70 lVpP6qqvo2pveZYeq50q7BKt49mIoEiYMbFyGW4i6oR0w+ueshb/BgqN FlMzDOk99aKRBwV+JmxImcVKZIfYtQ/Q7z20z7rZVBUcL9yUsCSo7J4N OmABeSxwH2Y63eChTDCuFfy5ngnCD+Iqr2HT9X+Y2oz7g3hsuUPP9PHD s4ingQo+aQ2PPzO6endmwsq27XBJ8M0jurEA2oSmoj4d5qZvcknlJ/Us YIZmF8Q/uKSqg9Z4wF+okYo/meC3wRtdsDWoW7irO47Ion0whVvj16X8 fiVn9eHBa1SNf+D+EpRRog8dlEuaK2ScFJDVdzx4JX3ps9b1hVPqlpPa b1uMYRQJpKfc2IZjwkiAcwcTW95tasuvpg8t1ZUOHgumf2f7eS5VwLsv cR2GRn+NGO9o9TrjYRddArSkodDecOY0Ac4OEgq2allTTw7IPMYabyXz 5UzVKQVJ2NXfvZyfR000yf1etx2jXcdB7yBXcTyfyE+C+sUIB72d5TKg z+/bcO/7Zgryp9ixvwM/qFexFqYHD5WuEuAbOGf1sq7gZF2HxnCK+DuI Swpt61A34V0=

he DNSSEC configurations can also be checked online. For example the DNSSEC debugger from Verisign Labs.