Installation et configuration de nsd, un serveur DNS (Domain Name Server) comme maître avec deux esclaves sous nsd et bind9 (named)

Introduction

Cette fiche opérationnelle (FICOP) décrit l'installation et la configuration d'un serveur de noms de domaines (DNS) sous nsd. En l'espèce nous utiliserons le domaine SCALAIRE.XYZ.

A la différence de bind/named, nsd ne fait que papa c'est-à-dire qu'il n'assure que la fonction de DNS d'autorité et ce pour les seules zones (domaines) déclarées sous sa responsabilité dans sa configuration, tandis que bind peut faire à la fois papa et maman, c'est-à-dire qu'il peut, en sus et en même temps, servir n'importe quelle zone en allant interroger ses DNS d'autorité s'il n'en est pas directement responsable. Ce mélange des genres n'est pas nécessairement le plus heureux en terme de sécurité.

nsd a été conçu pour être sûr et fiable, simple à configurer et à faible empreinte mémoire.

Naturellement, pour mieux le protéger, nsd peut aussi être utilisé comme maître « caché » depuis une machine non publiée ou non directement accessible depuis l'internet, qui alimentera les DNS « officiels », ceux publiés dans les enregistrements NS de la zone. Ainsi, seuls les serveurs esclaves connus seront exposés.

Nous préférons désormais nsd plutôt que bind. La fonction maman peut être réalisée par unbound développé exclusivement pour ce seul rôle dans le même esprit que nsd.

L'intégration de DNSSEC (DNS « sécurisé ») est traitée dans une autre FICOP.

Composants

On rappelle que la norme recommande (i) au moins deux DNS, (ii) situés sur deux sous-réseaux distincts, avec malheureusement encore une adresse IPv4 nécessaire et heureusement une adresse IPv6 possible, (iii) IPs qui doivent aussi se résoudre vers leurs noms par un enregistrement PTR du « reverse DNS ».

Nous utiliserons les ingrédients suivants :

Configuration du « registrar »

Ici GoDaddy, il suffit d'indiquer ns.scalaire.com et ns.scalaire.fr comme DNS ; la « glue » indiquant leurs adresses IP n'est pas nécessaire s'agissant de machines définies dans d'autres domaines que SCALAIRE.XYZ.

En revanche, en plus de leurs noms, il faudrait fournir les IPs des DNS se trouvant dans la zone qu'ils doivent servir afin de trancher le nœud gordien « pour accéder au domaine il faut d'abord l'IP de son DNS mais pour obtenir cette IP il faut d'abord pouvoir accéder à ce domaine ».

Configuration du maître

(La machine est une Debian 10 « Buster »)

apt-get install haveged nsd
haveged est un démon qui accumule de l'entropie afin de ne pas bloquer /dev/random en cas de forte consommation d'aléas. Nous générons un secret qui sera partagé par les serveurs (/dev/urandom n'est pas bloquant)
dd if=/dev/random count=1 bs=40 2> /dev/null | base64
mopUXiaeBBNoQYwybGuu8hhTZW1zEm6btRYC+gVaqHtGNbqsdn3ZEg==
Créer un répertoire pour centraliser les zones (ici nous préparons la ségrégation avec de futures zones signées en DNSSEC). Y créer la zone SCALAIRE.XYZ, ici minimaliste.

Note : les $ sont protégés contre leur interprétation par le shell par un \. En cas de copier/coller dans le fichier, il faudra les enlever.

mkdir /etc/nsd/unsigned_zones
chown nsd:nsd /etc/nsd/unsigned_zones
chmod 0700 /etc/nsd/unsigned_zones
F=/etc/nsd/unsigned_zones/SCALAIRE.XYZ
cat  > $F <<EOD.................
\$TTL    3600
\$ORIGIN scalaire.xyz.
@ IN SOA ns.scalaire.com. postmaster.scalaire.com. (
        2018101101 ; Serial
            1H ; Refresh
            600 ; Retry
            4W ; Expires
            3H ) ; Min
        NS ns.scalaire.com.
        NS ns.scalaire.fr.
        ; NS sing.scalaire.fr -- hidden master
        MX 10 smtp.scalaire.com.
myself  A   127.17.12.4
; AWS Singapour 08/10/2018
base    A    18.141.110.96
ouebe   AAAA 2406:da18:fa7:9200::8080
EOD.................
chown nsd:nsd $F
Editer le fichier de configuration de nsd, normalement vide à l'installation. Un mécanisme de « macro » permet de factoriser des données dans un pattern: qui seront rappelées par son name:.

cat /etc/nsd/nsd.conf
server:
    debug-mode: yes
    verbosity: 2
    # logfile: "/dev/stderr" # default to syslog

# server-count: 3 # multi-cores/CPUs : nums - 1 ip-address: 2406:da18:fa7:9200::5353 # usefull for multi-IPs servers # ip-transparent: yes # should the IPs go up only after nsd startup reuseport: yes # identity: "sing.scalaire.fr" # overwrite /etc/hostname (multi-IPs server) hide-version: yes zonesdir: "/etc/nsd/unsigned_zones"

key: # dd if=/dev/urandom count=1 bs=40 2> /dev/null | base64 name: "ploof" algorithm: hmac-sha256 secret: "mopUXiaeBBNoQYwybGuu8hhTZW1zEm6btRYC+gVaqHtGNbqsdn3ZEg=="

pattern: name: "slaves-of-this-master" outgoing-interface: 2406:da18:fa7:9200::5353 # NS.SCALAIRE.FR notify: 2001:41d0:305:2100::9e91 ploof provide-xfr: 2001:41d0:305:2100::9e91 ploof # NS.SCALAIRE.COM notify: 2001:41d0:1008:26d8::53 ploof provide-xfr: 2001:41d0:1008:26d8::53 ploof

zone: name: "SCALAIRE.XYZ" # case sensitive for the %s filename zonefile: "%s" include-pattern: "slaves-of-this-master"

Configuration de l'esclave bind9/named

Créer le fichier du secret partagé

F=/etc/bind/ploof.key
cat  > $F <<EOD.................
key "ploof" {
    algorithm hmac-sha256 ;
    secret "mopUXiaeBBNoQYwybGuu8hhTZW1zEm6btRYC+gVaqHtGNbqsdn3ZEg==" ;
};
EOD.................
chown bind:bind $F
chmod 0640 $F
et rajouter une zone esclave à la configuration en adaptant éventuellement le chemin du fichier de stockage automatique de la zone esclave
F=/etc/bind/named.conf.local
cat  >> $F <<EOD.................
zone "scalaire.xyz" {
    type slave;
    file "/var/cache/bind/scalaire.xyz";
    masters { 2406:da18:fa7:9200::5353 key "ploof" ; };
};
EOD.................
Si cet esclave gére d'autres zones reçues de ce même maître, on peut canoniser la clef en rajoutant cette section dans named.conf.options
server 2406:da18:fa7:9200::5353 {
    keys { "ploof" ; };
};
et la charger dans named.conf par un include "/etc/bind/ploof.key";

et alors se contenter d'un masters { 2406:da18:fa7:9200::5353 ; };

S'assurer que named.conf.options contienne une section

options {
    ...
    listen-on-v6 { ...; 2001:41d0:1008:26d8::53; };
    ...
avec une adresse identique à celle autorisée dans le maître nsd.

Configuration de l'esclave nsd

Avec nsd tout tient dans un seul fichier

F=/etc/nsd/nsd.conf
cat  >> $F <<EOD.................
key:
    name: "ploof"
    algorithm: hmac-sha256
    secret: "mopUXiaeBBNoQYwybGuu8hhTZW1zEm6btRYC+gVaqHtGNbqsdn3ZEg=="
zone:
    name: "scalaire.xyz"
    outgoing-interface: 2001:41d0:305:2100::9e91 # should this server have multiple public IPs
        # hidden master
    allow-notify: 2406:da18:fa7:9200::5353 ploof
    request-xfr: AXFR 2406:da18:fa7:9200::5353 ploof
EOD.................

Mise en service

Relancer les serveurs sur toutes les machines en terminant par le maître qui doit envoyer les notification aux esclaves, lesquels ouvrent en retour une connexion pour le transfert de la zone.

En cas d'erreur utiliser journalctl -xe, consulter les journaux et/ou vérifier la gousse d'ail.

Note : entre deux pairs nsd on peut ignorer les erreurs suivantes

Depuis une machine tierce,

On doit obtenir une en-tête du style

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20321
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 5
;; WARNING: recursion requested but not available
aa indique une « Authoritative Answer »

Sur le maître, on peut aussi effectuer une mise à jour en incrémentant le serial de la SOA de la zone, ici à 2019122002, puis en rechargeant nsd

systemctl reload nsd ; tail -f /var/log/syslog | grep -F nsd

Sur le maître

Dec 20 08:03:08 sing nsd[26748]: new control connection from 127.0.0.1
Dec 20 08:03:08 sing nsd[26748]: control cmd:  reload
Dec 20 08:03:08 sing nsd[26759]: zone SCALAIRE.XYZ read with success
Dec 20 08:03:08 sing nsd[26759]: zone SCALAIRE.XYZ written to db
Dec 20 08:03:08 sing nsd-control[31283]: ok
Dec 20 08:03:08 sing systemd[1]: Reloaded Name Server Daemon.
Dec 20 08:03:08 sing nsd[31285]: axfr for scalaire.xyz. from 2001:41d0:305:2100::9e91
Dec 20 08:03:09 sing nsd[31285]: axfr for scalaire.xyz. from 2001:41d0:1008:26d8::53

Sur l'esclave bind

Dec 20 09:03:08 ns named[10549]: client 2406:da18:fa7:9200::5353#59579/key ploof: received notify for zone 'scalaire.xyz': TSIG 'ploof'
Dec 20 09:03:08 ns named[10549]: zone scalaire.xyz/IN: notify from 2406:da18:fa7:9200::5353#59579: serial 2019122002
Dec 20 09:03:08 ns named[10549]: zone scalaire.xyz/IN: Transfer started.
Dec 20 09:03:09 ns named[10549]: transfer of 'scalaire.xyz/IN' from 2406:da18:fa7:9200::5353#53: connected using 2001:41d0:1008:26d8::53#39548
Dec 20 09:03:09 ns named[10549]: transfer of 'scalaire.xyz/IN' from 2406:da18:fa7:9200::5353#53: resetting
Dec 20 09:03:09 ns named[10549]: transfer of 'scalaire.xyz/IN' from 2406:da18:fa7:9200::5353#53: connected using 2001:41d0:1008:26d8::53#39030
Dec 20 09:03:09 ns named[10549]: zone scalaire.xyz/IN: transferred serial 2019122002: TSIG 'ploof'
Dec 20 09:03:09 ns named[10549]: transfer of 'scalaire.xyz/IN' from 2406:da18:fa7:9200::5353#53: Transfer status: success
Dec 20 09:03:09 ns named[10549]: transfer of 'scalaire.xyz/IN' from 2406:da18:fa7:9200::5353#53: Transfer completed: 1 messages, 8 records, 347 bytes, 0.179 secs (1938 bytes/sec)
Dec 20 09:03:09 ns named[10549]: zone scalaire.xyz/IN: sending notifies (serial 2019122002)
La dernière ligne indique que bind propage la notification de la modification aux autres NS, voir ci-après

Sur l'esclave nsd

191220 09:03:08 daemon.info nsd[13722]:  notify for scalaire.xyz. from 2406:da18:fa7:9200::5353 serial 2019122002
191220 09:03:08 daemon.info nsd[13712]:  xfrd: zone scalaire.xyz committed "received update to serial 2019122002 at 2019-12-20T09:03:08 from 2406:da18:fa7:9200::5353 TSIG verified with key ploof"
191220 09:03:08 daemon.info nsd[13713]:  zone scalaire.xyz. received update to serial 2019122002 at 2019-12-20T09:03:08 from 2406:da18:fa7:9200::5353 TSIG verified with key ploof of 269 bytes in 0.000213 seconds
191220 09:03:08 daemon.info nsd[13712]:  zone scalaire.xyz serial 2019122001 is updated to 2019122002.
191220 09:03:09 daemon.info nsd[13778]:  notify for scalaire.xyz. from 2001:41d0:1008:26d8::53 refused, no acl matches.
191220 09:03:10 daemon.info nsd[13778]:  notify for scalaire.xyz. from 151.80.26.216 refused, no acl matches.
191220 09:03:10 daemon.info nsd[13778]:  notify for scalaire.xyz. from 2001:41d0:1008:26d8::53 refused, no acl matches

Les lignes refused, no acl matches indiquent les tentatives de bind d'envoyer des notifications. En effet, par défaut ou par configuration, celui-ci cherche toujours à informer les autres NS de la zone, et ce à partir de toutes ses IPs (d'où, ici, celle en IPv4 151.80.26.216 obligatoire de part la norme), or notre esclave n'est configuré que pour les accepter de la part de son maître, pas de ses pairs.

Si l'on souhaite réduire ces « erreurs justes » :

Finalisation