/ Linux

Déployer un serveur DNS autoritaire avec NSD/DNSSEC via Docker

Vous voulez monter un serveur DNS autoritaire sur votre domaine avec le support de DNSSEC en moins de 10 minutes montre en main ? Suivez ce guide !

Par contre, je vous préviens tout de suite, cet article s'adresse à des personnes qui connaissent déjà ou qui ont déjà des notions sur le fonctionnement du DNS et du protocole DNSSEC. N'hésitez pas à regarder cet article de l'afnic et de regarder mon tutoriel sur mondedie.fr, j'explique assez brièvement le fonctionnement de DNSSEC.

J'ai créé récemment une image docker avec tout le nécessaire dedans pour déployer un petit serveur DNS autoritaire avec NSD.

NSD est un serveur DNS autoritaire seulement (il ne fait que distribuer des zones, ce n'est pas un résolveur comme unbound) qui a
l'avantage d'être léger et performant par rapport à Bind par exemple.

Donc on commence par télécharger l'image depuis le hub officiel :

docker pull hardware/nsd-dnssec

Le téléchargement devrait être rapide, l'image ne fait que 5MB (merci AlpineLinux). Une fois l'image téléchargée, mettez la zone DNS de votre domaine sous :

/mnt/docker/nsd/zones/db.domain.tld

Voici un exemple d'une zone DNS (bind-style) :

$ORIGIN domain.tld.
$TTL 7200

; SOA

@       IN      SOA    ns1.domain.tld. hostmaster.domain.tld. (
                                        2016020202 ; Serial
                                        7200       ; Refresh
                                        1800       ; Retry
                                        1209600    ; Expire
                                        86400 )    ; Minimum

; NAMESERVERS

@                   IN                NS                   ns1.domain.tld.
@                   IN                NS                   ns6.gandi.net.

; A RECORDS

@                   IN                A                    IPv4
hostname            IN                A                    IPv4
ns1                 IN                A                    IPv4

; CNAME RECORDS

www                 IN                CNAME                hostname

; MAIL RECORDS

@                   IN                MX          10       hostname.domain.tld.

...

N'oubliez pas de définir la valeur de $ORIGIN sinon la commande de signature de la zone ne fonctionnera pas, on verra ça juste après.

On va maintenant s'occuper de la configuration de NSD, copier le contenu suivant dans un fichier nommé nsd.conf :

# /mnt/docker/nsd/conf/nsd.conf

server:
  server-count: 1
  ip4-only: yes
  hide-version: yes
  identity: ""
  zonesdir: "/zones"

remote-control:
  control-enable: yes

zone:
  name: domain.tld
  zonefile: db.domain.tld
  notify: ip_of_secondary_server NOKEY
  provide-xfr: ip_of_secondary_server NOKEY

La plupart des options sont assez claires, je vais tout de même m'attarder sur le block remote-control. La directive control-enable permet l'utilisation de la commande nsd-control pour avoir un contrôle plus dynamique sur le daemon de NSD. Avant le version 4, il fallait redémarrer complètement le serveur DNS pour modifier sa configuration ou ajouter une nouvelle zone.

Maintenant un simple appel à nsd-control reconfig/reload/notify permet de reconstruire à chaud la configuration de NSD, des zones DNS et de prévenir par la même occasion les serveurs secondaires (slaves) d'un changement dans la zone (notification par comparaison du serial) et ainsi transférer les zones via le protocole AXFR (53/tcp).

Lorque la directive control-enable est configurée à yes, le daemon de NSD écoute par défaut depuis l'interface locale (127.0.0.1) sur le port 8952 (ceci peut-être changé via les directives control-interface et control-port).

N'oubliez pas de remplacer la mention ip_of_secondary_server par l'adresse ip de votre serveur DNS secondaire, dans mon cas j'ai choisi ns6.gandi.net comme mon registrar c'est Gandi mais j'aurais très bien pu monter un second serveur NSD en mode esclave.

Les autres options sont décrites dans la doc officielle de NSD.

On peut maintenant démarrer le conteneur avec cette commande :

docker run -d \
  --name nsd \
  -p 53:53 \
  -p 53:53/udp \
  -v /mnt/docker/nsd/conf:/etc/nsd \
  -v /mnt/docker/nsd/zones:/zones \
  -v /mnt/docker/nsd/db:/var/db/nsd \
  hardware/nsd-dnssec

Ou via docker-compose :

# docker-compose.yml

nsd:
  image: hardware/nsd-dnssec
  container_name: nsd
  ports:
    - "53:53"
    - "53:53/udp"
  volumes:
    - /mnt/docker/nsd/conf:/etc/nsd
    - /mnt/docker/nsd/zones:/zones
    - /mnt/docker/nsd/db:/var/db/nsd

Puis docker-compose up -d nsd

Vérifier que le conteneur est bien démarré et en écoute sur 53/udp et 53/tcp :

docker ps

IMAGE                 COMMAND     PORTS
hardware/nsd-dnssec   "startup"   0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp

Si ce n'est pas le cas, jeter un coup d'oeil avec :

docker logs nsd

Bon, actuellement vous avez un serveur DNS autoritaire pleinement fonctionnel, vous pouvez le tester avec dig par exemple :

# Permet d'obtenir tous les enregistrements
dig ANY +norec +short domain.tld. @ns1.domain.tld

# Permet d'obtenir la valeur de la directive identity présente dans nsd.conf
dig CH TXT ID.SERVER @ns1.domain.tld

Ne pas oublier de changer les NS depuis l'interface de votre registrar et d'ajouter l'enregistrement Glue.

En effet, quand un domaine est délégué à un serveur de nom qui appartient à ce sous-domaine (par exemple, dans notre cas il s'agit de ns1.domain.tld), il est nécessaire de fournir également l'adresse IP de ce serveur pour éviter les références circulaires, exemple chez Gandi.

Il ne reste plus qu'à ajouter le support de DNSSEC !

On commence par génerer les clés cryptographiques. Je rappel qu'il existe deux types de clés avec DNSSEC :

  • La clé de signature de la zone (Zone Signing Key - ZSK)
  • La clé de signature des clés (Key Signing Keys - KSK)

Pour les générer il suffit de faire :

docker exec -ti nsd keygen domain.tld

Pour la génération des clés, j'ai choisi l'algorithme ECDSAP384SHA384 avec des clés d'une longueur de 384 bits, c'est plus rapide à générer qu'avec RSA donc plus sympa pour les petites VM, j'aurais pu mettre haveged dans le conteneur pour accélérer le processus de génération, peut-être que j'ajouterai ça plus tard.

Vous devriez maintenant avoir 4 nouveaux fichiers dans le même répertoire que votre zone :

/zones/
      Kdomain.tld.zsk.key
      Kdomain.tld.zsk.private
      Kdomain.tld.ksk.key
      Kdomain.tld.ksk.private

On passe maintanant à la signature de la zone DNS :

docker exec -ti nsd signzone domain.tld [YYYYMMDDhhmmss]

La commande ci-dessus permet de signer la zone DNS du domaine domain.tld, une nouvelle zone db.domain.tld.signed est créée dans le répertoire /zones au même niveau que la zone de base.

Vous pouvez indiquer une date d'expiration, par défaut les signatures (RRSIG RR) expirent au bout d'un mois (ce qui rend la zone invalide et le domaine injoignable avec un résolveur validant les signatures DNSSEC, comme ceux de chez free par exemple).

Donc pensez à signer votre zone avant expiration, Stéphane Bortzmeyer a fait un article à ce sujet.

Ensuite, modifier le fichier de configuration de NSD pour utiliser la nouvelle zone signée précédemment :

# /mnt/docker/nsd/conf/nsd.conf

zone:
  name: domain.tld
  zonefile: db.domain.tld.signed
  ...

On redémarre le tout :

docker exec -ti nsd nsd-control reconfig 
docker exec -ti nsd nsd-control reload domain.tld
docker exec -ti nsd nsd-control notify domain.tld

Voila notre serveur DNS/DNSSEC est prêt !

Enfin, pas tout à fait. Il ne reste plus qu'à fournir le condensât (fingerprint) de votre clé KSK à votre registrar pour qu'il puisse le rajouter au registre du domaine parent.

Ce coup ci, ça varie en fonction du registrar, certains demandent la clé publique KSK (Gandi), d'autres l'enregistrement DS directement (GoDaddy). Peu importe, la commande ci-dessous devrait vous donner assez d'informations à communiquer à votre registar :

docker exec -ti nsd ds-records domain.tld

Aller on va dégainer dig pour vérifier tout ça :

# Permet d'obtenir vos clé publiques DNSSEC (256 = ZSK, 257 = KSK)
dig DNSKEY domain.tld. @ns1.domain.tld +multiline +norec

# Permet d'obtenir le condensât (fingerprint) depuis la zone parent
dig DS +trace +short domain.tld. | egrep '^DS'

# Permet d'obtenir tous les enregistrements avec les signatures DNSSEC correspondantes
dig ANY +dnssec +norec +short domain.tld. @ns1.domain.tld

Nous en avons fini, n'hesitez pas à vérifier votre configuration DNS avec les sites suivants

Si vous avez une question, une remarque ou une suggestion, n'hésitez pas à poster un commentaire en bas de la page.

Déployer un serveur DNS autoritaire avec NSD/DNSSEC via Docker
Share this