LINUXMAKER, OpenSource, Tutorials

Konfiguration von DNSSEC auf BIND9

Das Einrichten von DNSSEC soll hier in BIND9 auf einem Debian Linux-System demonstriert werden. Vorausgesetzt es existiert bereits ein funktionierender DNS-BIND-Server wie hier beschrieben.

Voraussetzungen

Alle Konfigurationsdateien für Bind9 liegen in "/etc/bind/", auf RedHat-, Centos- und Fedora-Linux-Systemen ist die Ablagestruktur etwas verschieden zu Debian. Und die Zonendateien liegen generell unterhalb von "/var/cache/bind/" strukturiert nach den TLD in eigenen Verzeichnissen wie "de", "com" etc.

Zone Walking und NSEC3

Zone Walking (DNSSEC Walking bzw. Zone Enumeration) ist als ein Verfahren bekannt, bei die Angreifer den vollständigen Inhalt von DNSSEC signierten DNS-Zonen auslesen können. So können vertrauliche Daten (wie Kundenlisten) und sicherheitsrelevante Informationen (Server-IP-Adressen) abgegriffen werden.
DNSSEC verkettet automatisch beim Signieren einer Zone mittels NSEC Resource Records alle Labels ringförmig in alphabetischer Reihenfolge. Am Beispiel der Zone example.tld sieht das so aus

    example.tld. NSEC name1
    name1         NSEC name2
    name2         NSEC name5
    name5         NSEC example.tld.

Auf der linken Seite steht jeweils das Label (kanonischer Name) und rechts davon ein Verweis auf das lexigrafisch nächste Label. Auf diese Weise kann die Nichtexistenz von Namen bewiesen werden. Fragt also ein Client den nichtexistierenden Namen name3 an, dan antwortet der DNS-Server mit dem NSEC-Eintrag name2 NSEC name5 und siganlisiert somit, dass zwischen name2 und name5 kein weiterer Eintrag existiert. Der Angreifer macht sich diese Verkettung zunutze, indem er mit dem ersten Namen einer Zone beginnend (das ist immer der Name der Zone selbst) die Kette durch sukzessive Abfragen durchläuft. Durch dieses technisch recht einfache Verfahren kann er innerhalb weniger Sekunden den gesamten Zoneninhalt auslesen.

Abwehr mit NSEC3

Das Zone Walking lässt mit der Alternative zu NSEC, nämlich NSEC3, deutlich erschweren. NSEC3 stellt die Namen nicht mehr im Klartext dar, sondern als einen kryptographischen Hashwert. NSEC3 erschwert zwar somit das Zone Walking, aber es kann Angriffe auf die Hash-Funktion das Zone Walking nicht komplett vermeiden. Deshalb soll die nachfolgende Konfiguration mit NSEC3 erfolgen.

DNSSEC, KSK, ZKS und RRSIG

Vorab hier noch die Erklärungen zu DNSSEC, KSK, ZKS und RRSIG.

So wird für jede Zone, die abgesichert werden soll, ein eigener Zonenschlüssel (Zone Signing Key) bestehend aus einem öffentlichen und einem privaten Schlüssel erzeugt. Der öffentliche Teil des ZSK existiert dann in der jeweiligen Zonendatei als DNSKEY Resource Record. Mit dem privaten Schlüssel jedoch, wird dann jeder einzelne RR in der Zone digital unterschrieben.

Zusätzlich wird zum Schlüssel für die Signatur der Zone (ZSK) ein syntaktisch identischer Schlüsselunterzeichnungs-Schlüssel KSK (Key Signing Key) generiert. Der Hintergrund dazu ist die Tatsache, dass sich die Zonenkeys (DNSKEY) öftere ändern können und bei einer Chain of Trust, die Parent-Zone der Child-Zone nicht mehr vertrauen würde. Nachdem aber für diesen Fall der KSK für einen langen Zeitraum der gleiche bleibt, bleiben somit bei Änderungen auch die Chain of Trust zwischen Parent- und Child-Zone erhalten. Andernfalls müsste die Child-Zone der Parent-Zone kontinuierlich neue Schlüssel mitteilen, was sich durchaus als sehr ineffizient und fehleranfällig gestalten kann.

Letztlich wird die Zone mittels der DNSKEYs signiert, während die Resource Records über die RRSIGs signiert werden.

Key Signing Key (KSK) generieren

Zunächst legen wir der besseren Strukturierung halber ein neues Verzeichnis innerhalb des Bind9-Konfigurationsverzeichnisses an.

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

Innerhalb dieses neuen Verzeichnisses wird der KSK mit folgenden Befehl erzeugt:

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

  • -3 aktiviert das gewünschte NSEC3
  • -a bestimmt den Typ der Signatur
  • -b gibt die gewünschte Blockgröße an
  • -n spezifiziert den Nametyp wie ZONE, HOST, USER
  • -f speziell für KSK muss diese Flag gesetzt werden

In dem Verzeichnis liegen jetzt zwei Dateien:

  • Kexample.tld.+010+64413.key (DNSKEY Record),
    der  dem Verifizieren der ZSKs dient und von höheren Zonen signiert wird.

  • Kexample.tld.+010+64413.private,
    dem privaten Schlüssel zur Signatur des öffentlichen ZSK.

Der DNSKEY Record im öffentlichen Schlüssel sieht etwa so aus:

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

Zone Signing Key (ZSK) generieren

Den Zone Signing Key erzeugt man im Anschluß daran wie folgt, gefolgt von einer Neuzuordnung der Dateiattribute.

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

Jetzt liegen zwei weitere Dateien in dem Verzeichnis:

  • Kexample.tld.+007+40385.key,
    der öffentliche Schlüssel (DNSKEY Record), der dem Verifizieren der DNS-Antworten dient.
  • Kexample.tld.+007+40385.private,
    der private Schlüssel zum Signieren der Resource Records.

Der Inhalt dieses ZSK stellt sich in etwa so dar.

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=

Signieren der Zonen selber

Jetzt kann die Zone in der jeweiligen Zonendatei durch das Hinzufügen der öffentlichen Schlüssel mittels der $INCLUDE-Direktive für die Signatur vorbereitet werden. Das lässt zum Einen einfach über eine Schleife erledigen

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

oder einzeln pro Zonendatei mit einer vi-Funktion:

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

Durch das Signieren wird gleichzeitig eine neue Zonendatei mit dem Suffix ".signed" erzeugt.

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/

Allerdings ist jetzt zu beachten, dass nach jeder Änderung in der Zonendatei, diese auch neu signiert werden muss.
Zusätzlich sind die signierten Zonen per Default nur 30 Tage lang gültig. Ein eigenes Enddatum für die Gültigkeit der signierten Zonendatei kann man dnssec-signzone mit "-e YYYYMMDDHHMMSS" mitgeben.

DNSSEC in BIND9 aktivieren

In den globalen Options von BIND9 aktiviert man DNSSEC mit folgenden Einträgen in /etc/bind/named.conf.options

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

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

In der Datei /etc/bind/named.conf.local ändert man nur in den Zonendeklarationen das file von

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

nach

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

und startet den BIND9 neu

systemctl restart bind9.service

Den DNSSEC-Schlüssel beim Registrar bekanntgeben

Abschliessend ist das DNSSEC bei dem eigenen Registrar zu aktivieren. Das geschieht meistens auf deren Webportalen, indem man den DNSKEY RR passend zur Zone eingeben muss und zusätzlich DS Record. Dazu wartet man bis das AXFR der Nameserver des Registrars erfolgt sind und eine Abfrage

dig DNSKEY example.tld

positiv den DNSKEY liefert. Dann nämlich weiß man, dass sich die Zonen synchronisiert haben. Man bekommt den DNSSEC sowohl für den Zonenschlüssel (256) als auch den Schlüsselunterzeichnungs-Schlüssel (257) angezeigt. Beim Registrar einzutragen ist Letzterer mit dem Flag 257. Zusätzlich wird der Delegation Signer Record (DS-RR) - dieser enthält den Digest des KSK Public Keys - einzutragen sein. Letzerer befindet sich in einer zusätzlichen Datei "dsset-example.tld." in dem Verzeichnis, von dem man "dnssec-signzone" gestartet hat, deren Inhalte man dazu übernehmen kann:

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

Testen des DNSSEC

Wenn man jetzt den DNS-Server abfragt oder andere Nameserver, sofern man das DNSSEC bei seinem Registrar bereits aktiviert hat, so erhält man diese Informationen.

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

Wenn man in dig die Option +dnssec mit nutzt, dann werden auch die RRSIG Records angezeigt:

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=

Online lassen die DNSSEC Konfigurationen ebenfalls prüfen. So zum Beispiel der DNSSEC-Debugger von Verisign Labs.