Le DNS
Posted on Fri 12 March 2021 in Hosting
Pierre angulaire d’une bonne partie des systèmes sur internet, le DNS – pour Domain Name System, système de nom de domaine – permet d’associer un nom à une machine, avec plein de subtilité autour, mais je vais pas détailler.
Il y a principalement 2 types de serveur DNS : les serveurs faisant autorité et qui vont décrire une zone de nom, et les résolveurs qui vont chercher l’information sur les bons serveurs faisant autorité. Dans mon cas présent, ce qui m’intéresse, c’est un serveur DNS faisant autorité sur la zone yapbreak.fr.
Je ne vais pas chercher bien loin pour le logiciel à utiliser, Bind9 fait ça très bien et a la volonté affichée de suivre complètement les standards édictés par l’IETF, Internet Engineering Task Force. De ce point de vue là, il me convient parfaitement. Pour ce qui est de son installation sur la Debian, rien de plus simple, il est présent dans les dépôts et il y a moult tutoriel sur internet pour la configuration. Je vous laisse avec celui-là qui m’a bien servi surtout pour les exemples en guise de rappel de syntaxe :
https://www.linuxbabe.com/debian/authoritative-dns-server-debian-10-buster-bind9
Je ne me lancerai pas dans une énième explication de chacun des champs d’une zone DNS, l’internet fourmille de ce genre de ressources. Attachons nous par contre à la sécurité et aux outils de diagnostiques.
DNSSEC
DNSSEC – pour Domain Name System Security Extensions – est un protocole qui permet de signer cryptographiquement le contenu de chaque enregistrement d’une zone, les rendant inaltérables. Pour ce faire,il faut 2 paires de clés publique et privée : une pour la signature de la zone dans son entièreté, dite ZSK –Zone Signing Key – et une pour la signature de chacune des entrées de la zone, dite KSK – Key Signing Key.
# Assurons nous d’avoir les outils nécessaires à DNSSEC
apt install bind9utils
# Les paires de clés seront stockées dans /etc/bind/keys
mkdir -p /etc/bind/keys
cd /etc/bind/keys
# Génération de la paire ZSK
dnssec-keygen -a ECDSAP384SHA384 -n ZONE ${nom_de_la_zone}
# 2 fichiers sont générés, de la forme K{nom_de_la_zone}.+014+{keyId}.key et K{nom_de_la_zone}.+014+{keyId}.private
# je les renomme pour plus de simplicité en {nom_de_la_zone}.zsk.key et {nom_de_la_zone}.zsk.private
mv K*.key ${nom_de_la_zone}.zsk.key
mv K*.private ${nom_de_la_zone}.zsk.private
# Génération de la paire KSK
dnssec-keygen -f KSK -a ECDSAP384SHA384 -n ZONE ${nom_de_la_zone}
# 2 fichiers sont générés, de la même forme que précédemment, et comme tout à l’heure, je les renomme avec ksk dans le suffixe
mv K*.key ${nom_de_la_zone}.ksk.key
mv K*.private ${nom_de_la_zone}.ksk.private
On ajoute ensuite à la fin de la définition de la zone les liens vers ces nouvelles clés :
; Définition de la zone, fichier /etc/bind/db.{nom_de_la_zone}
...
; DNSSEC keys
$include /etc/bind/keys/{nom_de_la_zone}.zsk.key
$include /etc/bind/keys/{nom_de_la_zone}.ksk.key
Une fois que tout est prêt, nous passons à la signature de la zone « pour de vrai » avec la commande suivante :
dnssec-signzone -e 20210413211253 \
-t -g \
-k "/etc/bind/keys/${nom_de_la_zone}.ksk.key" \
-o "${nom_de_la_zone}" \
/etc/bind/db.${nom_de_la_zone} \
/etc/bind/keys/${nom_de_la_zone}.zsk.key
Cette commande va donc signer la zone avec les clés de chiffrement, avec une validité allant jusqu’au 13 avril 2021 à 21h12 et 53 secondes (paramètre -e
). La zone signée est alors disponible dans le fichier /etc/bind/db.{nom_de_la_zone}.signed
qu’il faut référencer dans /etc/bind/named.conf.local
en lieu et place de la zone non signée.
Pour assurer la chaîne de validation complète, il est nécessaire d’enregistrer les clés publiques sur le serveur de niveau supérieur. Ceci se fait généralement via l’interface de votre registrar. Chez OVH, il suffit de renseigner le formulaire avec les KeyId (ils sont rappelés en commentaire sur la première ligne des fichiers *.key
), le bon flag (257 pour une clé KSK et 256 pour un clé ZSK), l’algorithme utilisé (dans mon cas, le 14 – ECDSAP384SHA384) et la clé publique en elle même :
L’automatisme
C’est bien beau toute ces commandes, mais si la génération de nouvelles clés et l’enregistrement DS n’est pas à refaire à chaque fois, il faut penser à re-signer la zone après chaque modification et assez régulièrement puisque la signature a une date d’expiration. Ajoutons à ça la mise à jour du numéro de série de la zone qui doit être strictement incrémentale… Ça fait un potentiel d’erreur assez élevé et donc, il y a forcément un script qui permet d’automatiser tout ça et d’éviter le plus possible les erreurs bêtes.
#!/usr/bin/env bash
if [ $# -ne 1 ]; then
echo "Usage:"
echo "$0 domain"
exit 1
fi
domain="${1}"
zonefile="/etc/bind/db.${domain}"
if [ ! -f "${zonefile}" ]; then
echo "Zone file ${zonefile} does not exists"
exit 1
fi
update_zone() {
local soa
local old_serial
local today
local new_serial
local index
soa=$(grep "SOA" "$zonefile")
old_serial=$(echo "$soa" | sed 's|^.*([ \t]*\([0-9][0-9]*\)[^0-9].*$|\1|g')
today=$(date +"%Y%m%d")
if echo "$old_serial" | grep "$today" > /dev/null; then
index=$(echo "${old_serial}" | sed 's|^.*\([0-9][0-9]\)$|\1|g;s|^0||')
index=$(( index + 1 ))
new_serial="${today}$(printf "%02d" ${index})"
else
new_serial="${today}01"
fi
sed -i "s|${old_serial}|${new_serial}|" "${zonefile}"
}
update_zone
newdate=$(date -d "32 days" +"%Y%m%d%H%M%S")
if ! named-checkzone "${domain}" "${zonefile}"; then
echo "Failed to validate zone file, abort."
exit 1
fi
echo "Ready to sign zone valid until $newdate"
if [ ! -f "/etc/bind/keys/${domain}.zsk.key" ]; then
echo "No ZSK key found. Abort."
echo "You can generate one with:"
echo "dnssec-keygen -a ECDSAP384SHA384 -n ZONE ${domain}"
echo "and rename output to /etc/bind/keys/${domain}.zsk.{key,private}"
exit 1
fi
if [ ! -f "/etc/bind/keys/${domain}.ksk.key" ]; then
echo "No KSK key found. Abort."
echo "You can generate one with:"
echo "dnssec-keygen -f KSK -a ECDSAP384SHA384 -n ZONE ${domain}"
echo "and rename output to /etc/bind/keys/${domain}.ksk.{key,private}"
exit 1
fi
dnssec-signzone -e"${newdate}" \
-t -g \
-k "/etc/bind/keys/${domain}.ksk.key" \
-o "${domain}" "${zonefile}" "/etc/bind/keys/${domain}.zsk.key"
echo "Restart bind9 service"
systemctl restart bind9.service
Pour que ce script fonctionne, il est nécessaire d’avoir le numéro de série sur la même ligne que SOA
de cette façon :
@ IN SOA ns01.yapbreak.fr. admin.yapbreak.fr. (2021031216 ; serial
J’utilise la convention suivante pour les numéros de série afin d’assurer l’incrément : le numéro est composé de la date courante au format AAAAMMJJ, suivi de 2 chiffres d’index allant donc de 01 à 99. On peut donc modifier une zone au maximum 98 fois par jours, ce qui est déjà pas mal.
La zone est ensuite signée pour les 32 jours qui viennent.
Vérification
Pour vérifier que tout est bien en place, que tout est cohérent, voici deux outils bien pratique. Je les notes ici, comme ça, je n’ai pas à redemander à chaque fois à Stéphane Bortzmeyer :
- ZoneMaster supporté par l’Afnic entre autre, et qui donne une bonne vue d’ensemble de tous les problèmes potentiels
- DnsViz plus spécialisé dans les problèmes de DNSSEC.