DNSSEC

DNS Secuity Extensions (DNSSEC) est une spécification qui sert à garantir l'intégrité des données transmises par le DNS. DNSSEC va donc signer les enregistrements DNS d'une zone.

Tout d'abord, pour activer l'utilisation de DNSSEC dans notre bind9, il faut aller dans /etc/bind/named.conf.options et ajouter les lignes suivantes dans l'options { }:

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

On va ensuite créer un biclé pour signer la zone (ZSK pour Zone Signing Key) :

dnssec-keygen -a ECDSAP256SHA256 -b 2048 -n ZONE salo.pe

La commande va créer un biclé :

Generating key pair.
Ksalo.pe.+001+01010

On va également créer un biclé pour signer notre clé précédente (KSK pour Key Signing Key) :

dnssec-keygen -f KSK -a ECDSAP256SHA256 -b 2048 -n ZONE salo.pe
Generating key pair.
Ksalo.pe.+002+02020

On va maintenant créer 4 clés publiques / privées. Il faut maintenant ajouter les clés publiques (qui contiennent des enregistrements DNSKEY) à notre fichier de zone :

for key in $(ls Ksalo.pe*.key); do
    echo "\$INCLUDE $key" >> salo.pe.zone
done

Il faut maintenant signer le fichier de zone avec :

dnssec-signzone -3 $(head -c 1024 /dev/urandom | sha1sum | cut -b 1-16) -N INCREMENT -o salo.pe -t salo.pe.zone
Verifying the zone using the following algorithms:
- ECDSAP256SHA256
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: x active, x stand-by, x revoked
                            ZSKs: x active, x stand-by, x revoked
                            salo.pe.zone.signed
                            Signatures generated:                       xx
                            Signatures retained:                         x
                            Signatures dropped:                          x
                            Signatures successfully verified:            x
                            Signatures unsuccessfully verified:          x
                            Signing time in seconds:                 x.xxx
                            Signatures per second:                 xxx.xxx
                            Runtime in seconds:                      x.xxx

La commande a généré un fichier signé, nommé dans notre cas salo.pe.zone.signed. Ce dernier contient maintenant les enregistrements RRSIG. Il ne reste plus qu'à dire à bind9 que le fichier de zone a changé (dans /etc/bind/named.conf.local) :

zone "salo.pe." {
    type master;
    file "/var/lib/bind/salo.pe.zone.signed";
    notify no;
};

On va recharger bind9 :

service bind9 reload

Et on va tester notre enregistrement DNSKEY :

dig DNSKEY salo.pe. @locahost
; <<>> DiG 9.16.23 <<>> DNSKEY salo.pe @pi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6915
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (good)
;; QUESTION SECTION:
;salo.pe.           IN  DNSKEY

;; ANSWER SECTION:
salo.pe.        300 IN  DNSKEY  257 3 14 N2IdneSgXq9qtbI7tkbdJn1eNpMrCp1ahWQkXllcshQMoR5n38bdVigy BIpkQE2urSvAsh3sDLziREvlbVbTD+tjqadvIzjAFJd+/R4xd7EqPNiK XMONjcjsf5Eld5S8
salo.pe.        300 IN  DNSKEY  256 3 14 WEW+NXfKvEoYHknb3AV5FitgFUzhaf6ztPIMCyvFhhrjkrwANfFIThcw 8LXbLqghVkhJhoTdp7cMHbn2VoIbcoo2nypNH2xIYojlpcG8IDR4+FfL 912Qpemm5hhYqid1

;; Query time: xx msec
;; SERVER: xxx.xxx.xxx.xxx#xxx(xxx.xxx.xxx.xxx)
;; WHEN: Sat Nov 27 08:04:06 CET 2021
;; MSG SIZE  rcvd: xxx

On va également tester la présence de l'enregistrement RRSIG :

dig A wiki.salo.pe @localhost +dnssec
; <<>> DiG 9.16.23 <<>> A wiki.salo.pe @pi +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24670
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (good)
;; QUESTION SECTION:
;wiki.salo.pe.          IN  A

;; ANSWER SECTION:
wiki.salo.pe.       300 IN  A   xxx.xxx.xxx.xxx
wiki.salo.pe.       300 IN  RRSIG   A 14 3 300 20211227055627 20211127055627 64607 salo.pe. q3oc64GzeiDmN1qIoRSa64fb/UxGdDAO7gYIP34JUEfluchSYcU3yml1 W2aHznpkQRggy2es/whFljsOq84Q2p60KmO6tmbPBB/ptSpEN0jnlSTt FTxsJWD5Bdkcf9Lo

;; Query time: xx msec
;; SERVER: xxx.xxx.xxx.xxx#xxx(xxx.xxx.xxx.xxx)
;; WHEN: Sat Nov 27 08:04:47 CET 2021
;; MSG SIZE  rcvd: xxx

Voici un script pour générer le fichier de zone signé (ici dans Ansible) :

#!/bin/sh

DIR="<chemin vers un dossier>"
REGEX_ALL_KEYS="<regex pour les clés>"              # avec l'exemple, Ksalo.pe*
REGEX_PUBLIC_KEYS="<regex pour les clés publiques>" # Ksalo.pe.*.key
ZONE_FILE="<fichier de zone>"                       # salo.pe.zone
SIGNED_ZONE_FILE="<fichier de zone signé>"          # salo.pe.zone.signed
DOMAIN="<domaine>"                                  # salo.pe

# On va utiliser notre fichier de zone (salo.pe.zone) et en faire un
# fichier de base, qui sera copié à chaque execution.
# cp salo.pe.zone salo.pe.zone.base
BASE_ZONE_FILE="<fichier de zone d'origine>"

rm $DIR/$REGEX_ALL_KEYS $DIR/$ZONE_FILE $DIR/$SIGNED_ZONE_FILE

set -e

dnssec-keygen -K $DIR -a ECDSAP256SHA256 -b 2048 -n ZONE $DOMAIN
dnssec-keygen -K $DIR -f KSK -a ECDSAP256SHA256 -b 2048 -n ZONE $DOMAIN

cp "$DIR/$BASE_ZONE_FILE" "$DIR/$ZONE_FILE"

for key in $(ls $DIR/$REGEX_PUBLIC_KEYS); do
    echo "\$INCLUDE $key" >> "$DIR/$ZONE_FILE"
done

dnssec-signzone -A -3 $(head -c 2048 /dev/urandom | sha1sum | cut -b 1-16) -K $DIR -N INCREMENT -o $DOMAIN -t $DIR/$ZONE_FILE