Aller au contenu principal
Xsec

Créer un serveur DNS sur Debian

Publié le 17 min de lecture

Mis à jour le

Partie 3 sur 6
Dans cette série41 min de lecture au total
  1. Installer Docker sur Debian
  2. Installer un certificat auto-signé OpenSSL avec nginx
  3. Créer un serveur DNS sur Debian
  4. Installer Nginx + Webdav sur Debian 11
  5. Créer un serveur OpenVPN sur Debian
  6. Connexion SSH avec clé publique

Un serveur DNS traduit des noms en adresses. Plutôt que de retenir que le NAS est à 172.16.30.30, on tape nas.it.fr et le serveur fait la correspondance. Ce lab construit ce service de bout en bout avec Bind9 sur Debian : une machine qui répond pour son propre domaine, dans les deux sens, et qui relaie vers l’extérieur ce qu’elle ne connaît pas.

RésuméCe que vous saurez faire à la fin
  • Préparer une machine Debian pour qu’elle puisse porter un service DNS.
  • Installer Bind9 et savoir à quoi sert chacun de ses fichiers.
  • Écrire une zone directe, qui traduit les noms en adresses.
  • Écrire une zone inverse, qui traduit les adresses en noms.
  • Déclarer ces zones et rediriger vers l’extérieur ce qui sort du domaine.
  • Valider la configuration avant de redémarrer le service, et diagnostiquer une panne.

Ce que fait un serveur DNS et ce que nous construisons

Une résolution se déroule en trois temps. Le client interroge le serveur DNS qu’on lui a désigné. Si le nom demandé appartient à une zone dont ce serveur détient la copie de référence, il répond directement et fait alors autorité. Sinon, il transmet la question à un autre serveur, appelé redirecteur, et renvoie sa réponse.

Notre serveur remplira les deux rôles : autorité sur it.fr, redirecteur vers l’extérieur pour tout le reste.

Voici la configuration de ce lab. Ces valeurs reviennent dans tous les fichiers, remplacez-les partout par les vôtres.

ParamètreValeurOù elle réapparaît
Adresse du serveur172.16.10.10/etc/hosts, resolv.conf, zones
Masque de sous-réseau255.255.0.0, soit /16interface réseau, nom de la zone inverse
Nom de la machinedns/etc/hostname, /etc/hosts, zones
Nom de domaineit.frpartout
Zone directeit.fr dans /etc/bind/db.it.frnamed.conf.local
Zone inverse16.172.in-addr.arpa dans /etc/bind/db.it.fr.invnamed.conf.local

Trois machines seront déclarées dans la zone :

Nom completAdresseRôle
dns.it.fr172.16.10.10le serveur DNS lui-même
client.it.fr172.16.20.20un poste client
nas.it.fr172.16.30.30un serveur de fichiers
Un problème avec sudo ?
DangerN'utilisez pas le compte root

Si vous configurez votre serveur directement en tant que root, n’oubliez pas de retirer sudo de chaque commande. Si vous définissez un mot de passe pour le compte root, la commande sudo ne sera pas acceptée. Connectez-vous directement en tant que root pour exécuter les commandes. Vous pouvez aussi réinstaller votre système en laissant le mot de passe root vide lors de l’installation. sudo s’installera et fonctionnera correctement.

Un serveur DNS annonce sa propre adresse aux clients. Cette adresse doit donc être connue et stable avant d’installer quoi que ce soit.

Étape 1 : figer l’identité réseau de la machine

  1. Nommer la machine

    Fenêtre de terminal
    sudo nano /etc/hostname
    /etc/hostname
    dns

    Ce fichier ne contient que le nom court, sans le domaine. Le nom complet dns.it.fr sera reconstitué par /etc/hosts deux étapes plus loin.

  2. Vérifier l'adresse de l'interface

    Fenêtre de terminal
    ip a
    ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever
    2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:cd:01:1a brd ff:ff:ff:ff:ff:ff
    altname enp11s0
    inet 172.16.10.10/16 brd 172.16.255.255 scope global ens192
    valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fecd:11a/64 scope link
    valid_lft forever preferred_lft forever

    L’interface ens192 porte bien 172.16.10.10/16. Si vous avez fixé l’adresse pendant l’installation de Debian, passez à l’étape suivante.

    AvertissementUne adresse dynamique condamne le service

    Le serveur inscrit sa propre adresse dans ses fichiers de zone, et les clients la mémorisent dans leur configuration. Un bail DHCP qui change d’adresse rend l’ensemble faux d’un coup, sans le moindre message d’erreur. L’adressage statique est une condition, pas une préférence.

  3. Passer l'interface en statique si nécessaire

    Éditer /etc/network/interfaces
    Fenêtre de terminal
    sudo nano /etc/network/interfaces
    /etc/network/interfaces
    # This file describes the network interfaces available on your system
    # and how to activate them. For more information, see interfaces(5).
    source /etc/network/interfaces.d/*
    # The loopback network interface
    auto lo
    iface lo inet loopback
    # The primary network interface
    allow-hotplug ens192
    iface ens192 inet static
    address 172.16.10.10
    netmask 255.255.0.0
    gateway 172.16.1.1
  4. Déclarer le nom complet dans /etc/hosts

    Fenêtre de terminal
    sudo nano /etc/hosts
    /etc/hosts
    172.16.10.10 dns.it.fr dns
    127.0.0.1 dns

    La syntaxe est IP_SERVEUR_DNS<tab>HOSTNAME.DOMAINE<tab>HOSTNAME.

    ExplicationPourquoi ce fichier compte avant même l'installation

    /etc/hosts est consulté avant le DNS par la résolution système. Il permet à la machine de connaître son propre nom complet alors que Bind9 n’est pas encore installé, et donc à des services de démarrer sans attendre un DNS qui n’existe pas. C’est ce qui évite les longues temporisations au démarrage.

  5. Désigner le résolveur à utiliser

    Fenêtre de terminal
    sudo nano /etc/resolv.conf
    /etc/resolv.conf
    domain it.fr
    search it.fr
    nameserver 172.16.10.10

    La ligne search it.fr permet de taper nas au lieu de nas.it.fr : le suffixe est ajouté automatiquement. La ligne nameserver désigne le serveur à interroger, ici la machine elle-même.

    AvertissementCe fichier est souvent réécrit

    Selon la configuration de Debian, resolvconf, systemd-resolved ou le client DHCP peuvent régénérer /etc/resolv.conf au démarrage et écraser vos lignes. Si le contenu disparaît après un redémarrage, il faut soit désinstaller le service responsable, soit déclarer les mêmes valeurs via dns-nameservers et dns-search dans /etc/network/interfaces.

    Danger

    Il est nécessaire de redémarrer la machine :

    Fenêtre de terminal
    sudo reboot

La machine a une adresse fixe, un nom complet et sait qui interroger. Le service peut maintenant être installé.

Étape 2 : installer Bind9

Fenêtre de terminal
sudo apt update && sudo apt install bind9 dnsutils

apt update rafraîchit la liste des paquets à partir de sources.list. bind9 est le serveur DNS proprement dit, dnsutils fournit les outils de diagnostic dig et nslookup, indispensables à la vérification finale.

L’installation dépose plusieurs fichiers dans /etc/bind. Savoir lequel fait quoi évite beaucoup de tâtonnements :

FichierRôleOn y touche ?
named.confinclut simplement les trois fichiers ci-dessousnon
named.conf.optionscomportement global : cache, redirecteurs, DNSSECoui, étape 4
named.conf.localdéclaration des zones dont ce serveur est responsableoui, étape 4
named.conf.default-zoneszones techniques (localhost, racine)non
db.local, db.127modèles de zone fournis, à copieron les copie
db.<domaine>contenu réel d’une zone, créé par vousoui, étape 3
Notenamed, bind9, deux noms pour le même service

Le démon s’appelle named (name daemon), le paquet s’appelle bind9. Les fichiers de configuration portent donc named, tandis que les commandes de service utilisent bind9. Ce n’est pas une incohérence, c’est un héritage historique.

Les fichiers de configuration sont là, mais aucun ne décrit encore it.fr.

Étape 3 : écrire les fichiers de zone

Une zone est un fichier qui liste les enregistrements dont ce serveur fait autorité. Il en faut deux : une pour traduire les noms en adresses, une pour l’opération inverse.

La zone directe

  1. Copier le modèle fourni

    Fenêtre de terminal
    sudo cp /etc/bind/db.local /etc/bind/db.it.fr

    db.local contient déjà un enregistrement SOA et un NS valides : partir de cette copie évite de réécrire une structure facile à casser.

  2. Remplacer le domaine d'exemple

    Le modèle utilise localhost partout. Un remplacement global suffit à le transformer en notre domaine.

    Fenêtre de terminal
    sudo sed -i 's/localhost/it.fr/g' /etc/bind/db.it.fr
    AstuceLes options de sed

    -i modifie le fichier sur place, s/ancien/nouveau/ est la commande de substitution, et le g final l’applique à toutes les occurrences d’une ligne et non seulement à la première. Sans -i, sed se contente d’afficher le résultat sans rien enregistrer, ce qui est d’ailleurs une bonne façon de vérifier avant d’appliquer.

  3. Compléter la zone

    Fenêtre de terminal
    sudo nano /etc/bind/db.it.fr
    /etc/bind/db.it.fr
    ;
    ; Zone directe pour it.fr
    ;
    $TTL 604800
    @ IN SOA dns.it.fr. root.it.fr. (
    2021102001 ; Serial
    604800 ; Refresh
    86400 ; Retry
    2419200 ; Expire
    604800 ) ; Negative Cache TTL
    ;
    @ IN NS dns.it.fr.
    @ IN A 172.16.10.10
    dns IN A 172.16.10.10
    client IN A 172.16.20.20
    nas IN A 172.16.30.30

    L’enregistrement A nommé client est ce qui permet d’atteindre 172.16.20.20 en tapant client.it.fr.

    DangerLe point final n'est pas décoratif

    Dans un fichier de zone, un nom qui ne se termine pas par un point se voit ajouter le nom de la zone. Écrire @ IN NS dns.it.fr sans point final produit dns.it.fr.it.fr., et la zone ne résout plus rien. Retenez la règle inverse : un nom court comme dns ou client s’écrit sans point, un nom complet comme dns.it.fr. s’écrit toujours avec.

    AvertissementDeux pièges hérités du modèle db.local

    La copie de db.local contient deux lignes à corriger et non simplement à recopier. Le NS pointe sur localhost., qu’il faut remplacer par le nom réel du serveur, sans quoi la zone désigne une machine qui n’existe pas. Et un @ IN AAAA ::1 publie l’adresse IPv6 de bouclage comme étant celle du domaine : un client compatible IPv6 essaiera de se connecter à lui-même. Supprimez cette ligne tant que vous n’avez pas d’adressage IPv6 réel.

    DéfinitionLire l'enregistrement SOA

    Le SOA (Start of Authority) ouvre toute zone et n’apparaît qu’une fois. Ses deux premiers champs sont le serveur de référence et l’adresse de contact, où le premier point remplace le @ : root.it.fr. signifie root@it.fr.

    ChampValeurRôle
    Serial2021102001numéro de version de la zone
    Refresh604800délai avant qu’un serveur secondaire revérifie
    Retry86400délai de nouvelle tentative si le primaire n’a pas répondu
    Expire2419200au-delà, un secondaire cesse de répondre pour la zone
    Negative Cache TTL604800durée de mise en cache d’une réponse « ce nom n’existe pas »

    Le Serial est le seul champ que vous modifierez souvent : il doit être incrémenté à chaque modification de la zone, sinon les serveurs secondaires et les caches conserveront l’ancienne version. La convention la plus répandue est AAAAMMJJNN, soit la date suivie d’un compteur à deux chiffres, ce qui donne un numéro toujours croissant et lisible.

Ajouter un enregistrement par la suite

Chaque nouvelle machine se déclare sur une ligne, selon le format nom IN type valeur :

NomClasseTypeValeur
imprimanteINA172.16.40.40
/etc/bind/db.it.fr
dns IN A 172.16.10.10
client IN A 172.16.20.20
nas IN A 172.16.30.30
imprimante IN A 172.16.40.40

Incrémentez le Serial, puis rechargez la zone avec sudo rndc reload it.fr, qui évite de redémarrer tout le service.

Voici les principaux types d’enregistrements et ce qu’ils associent :

TypeCe qu’il associeExemple
Aun nom à une adresse IPv4nas IN A 172.16.30.30
AAAAun nom à une adresse IPv6nas IN AAAA 2001:db8::30
CNAMEun nom à un autre nom, jamais à une adressewww IN CNAME dns.it.fr.
MXun domaine à son serveur de messagerie, avec une priorité@ IN MX 10 mail.it.fr.
TXTdu texte libre, utilisé par SPF, DKIM et les validations de domaine@ IN TXT "v=spf1 -all"
NSune zone au serveur qui en fait autorité@ IN NS dns.it.fr.
SOAles paramètres administratifs de la zone, un seul par zonevoir ci-dessus
SRVun service à un hôte et un port_ldap._tcp IN SRV 0 5 389 dns.it.fr.
PTRune adresse à un nom, l’inverse du type A10.10 IN PTR dns.it.fr.

Liste complète

La zone inverse

La zone directe répond à « quelle est l’adresse de nas.it.fr ». La question symétrique, « à quel nom correspond 172.16.30.30 », relève d’une zone séparée. Les serveurs de messagerie, les journaux système et de nombreux outils d’administration s’en servent pour afficher des noms plutôt que des adresses.

ExplicationPourquoi le nom de la zone est à l'envers

Un nom de domaine se lit du plus précis au plus général, de gauche à droite : nas dans it dans fr. Une adresse IP fait l’inverse, elle va du plus général au plus précis : le réseau 172.16 puis la machine. Pour que les deux se traitent avec le même mécanisme d’arborescence, l’adresse est inversée et placée sous le domaine spécial in-addr.arpa.

RéseauMasqueNom de la zone inverse
172.16.0.0/1616.172.in-addr.arpa
192.168.1.0/241.168.192.in-addr.arpa
10.0.0.0/810.in-addr.arpa

Notre réseau étant en /16, la zone couvre 16.172.in-addr.arpa et peut donc contenir les trois machines, qui vivent dans des sous-réseaux différents.

  1. Copier le modèle inverse

    Fenêtre de terminal
    sudo cp /etc/bind/db.127 /etc/bind/db.it.fr.inv
  2. Écrire les enregistrements PTR

    Fenêtre de terminal
    sudo nano /etc/bind/db.it.fr.inv
    /etc/bind/db.it.fr.inv
    ;
    ; Zone inverse pour 172.16.0.0/16
    ;
    $TTL 604800
    @ IN SOA dns.it.fr. root.it.fr. (
    2021102001 ; Serial
    604800 ; Refresh
    86400 ; Retry
    2419200 ; Expire
    604800 ) ; Negative Cache TTL
    ;
    @ IN NS dns.it.fr.
    10.10 IN PTR dns.it.fr.
    20.20 IN PTR client.it.fr.
    30.30 IN PTR nas.it.fr.

    La partie à gauche est ce qui reste de l’adresse une fois le nom de zone retiré, elle aussi inversée. Pour 172.16.20.20 dans la zone 16.172.in-addr.arpa, il reste 20.20. La valeur à droite est un nom complet : le point final est obligatoire.

    Astuce

    Sur un réseau en /24, il ne resterait qu’un seul octet à gauche. Pour 192.168.1.42 dans 1.168.192.in-addr.arpa, la ligne serait simplement 42 IN PTR nom.domaine..

Les deux zones existent sur le disque, mais Bind9 ne sait pas encore qu’elles le concernent.

Étape 4 : déclarer les zones et les redirecteurs

  1. Déclarer les zones

    Fenêtre de terminal
    sudo nano /etc/bind/named.conf.local
    /etc/bind/named.conf.local
    //
    // Do any local configuration here
    //
    // Consider adding the 1918 zones here, if they are not used in your
    // organization
    //include "/etc/bind/zones.rfc1918";
    zone "it.fr" {
    type master;
    file "/etc/bind/db.it.fr";
    allow-query { any; };
    };
    zone "16.172.in-addr.arpa" {
    type master;
    file "/etc/bind/db.it.fr.inv";
    allow-query { any; };
    };

    Chaque bloc associe un nom de zone à son fichier. type master signifie que ce serveur détient la copie de référence et n’a personne à interroger pour cette zone : c’est ce qui le rend autoritaire. allow-query { any; } autorise n’importe quelle machine à poser la question.

    AvertissementUne zone déclarée mais sans fichier empêche le démarrage

    Si le fichier référencé n’existe pas ou contient une erreur de syntaxe, Bind9 refuse de charger la zone et le service peut ne pas démarrer du tout. C’est exactement pour cette raison que la zone inverse a été écrite à l’étape précédente avant d’être déclarée ici, et non l’inverse.

    AstuceRestreindre allow-query en production

    any convient à un lab. Sur un réseau exposé, un résolveur ouvert peut être détourné pour amplifier des attaques par déni de service. Limitez alors la requête à vos réseaux internes, par exemple allow-query { 172.16.0.0/16; localhost; };.

  2. Configurer les redirecteurs

    Fenêtre de terminal
    sudo nano /etc/bind/named.conf.options
    /etc/bind/named.conf.options
    options {
    directory "/var/cache/bind";
    // If there is a firewall between you and nameservers you want
    // to talk to, you may need to fix the firewall to allow multiple
    // ports to talk. See http://www.kb.cert.org/vuls/id/800113
    forwarders {
    1.1.1.1;
    8.8.8.8;
    };
    //========================================================================
    // If BIND logs error messages about the root key being expired,
    // you will need to update your keys. See https://www.isc.org/bind-keys
    //========================================================================
    dnssec-validation auto;
    auth-nxdomain no; # conform to RFC1035
    version none;
    listen-on-v6 { any; };
    };

    forwarders liste les serveurs à qui transmettre les questions qui ne concernent pas it.fr. C’est ce qui permet aux machines du réseau d’atteindre Internet tout en n’ayant qu’un seul serveur DNS configuré.

    DangerNe mettez jamais le serveur lui-même dans forwarders

    Y inscrire 172.16.10.10, l’adresse de cette machine, crée une boucle : le serveur se transmet la question à lui-même, indéfiniment, jusqu’à épuisement du délai. Les redirecteurs ne doivent contenir que des résolveurs externes, par exemple 1.1.1.1 chez Cloudflare ou 8.8.8.8 chez Google. Le serveur sait déjà répondre pour ce qu’il héberge, il n’a pas besoin de se le demander.

    Explicationforward only ou forward first

    Sans mention explicite, Bind9 utilise forward first : il essaie les redirecteurs puis, en cas d’échec, interroge lui-même les serveurs racine. Ajouter forward only; lui interdit cette seconde tentative. C’est utile derrière un pare-feu qui bloque les requêtes sortantes directes, mais cela rend le service entièrement dépendant des redirecteurs. Notez aussi que forward only combiné à dnssec-validation auto échoue si le redirecteur ne transmet pas les enregistrements de signature.

    Noteversion none

    Cette ligne empêche le serveur d’annoncer son numéro de version dans ses réponses. C’est une mesure d’hygiène élémentaire : elle évite d’indiquer à un attaquant quelles vulnérabilités connues essayer en premier.

Tout est écrit. Reste à vérifier avant de mettre en service, ce qui est bien plus rapide que de diagnostiquer un service qui refuse de démarrer.

Vérifier et dépanner

Bind9 fournit deux commandes de contrôle qui analysent les fichiers sans toucher au service. Utilisez-les systématiquement avant tout redémarrage.

  1. Contrôler la syntaxe

    Fenêtre de terminal
    sudo named-checkconf
    sudo named-checkzone it.fr /etc/bind/db.it.fr
    sudo named-checkzone 16.172.in-addr.arpa /etc/bind/db.it.fr.inv
    Sortie attendue
    zone it.fr/IN: loaded serial 2021102001
    OK
    zone 16.172.in-addr.arpa/IN: loaded serial 2021102001
    OK

    named-checkconf ne renvoie rien du tout quand la configuration est correcte. Chaque named-checkzone doit se terminer par OK et afficher le numéro de série chargé.

  2. Redémarrer le service

    Fenêtre de terminal
    sudo systemctl restart bind9
    sudo systemctl status bind9
  3. Interroger le serveur

    Fenêtre de terminal
    dig @127.0.0.1 client.it.fr
    Extrait de la réponse
    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1
    ;; ANSWER SECTION:
    client.it.fr. 604800 IN A 172.16.20.20

    Le drapeau aa (authoritative answer) confirme que la réponse vient bien de notre zone et non d’un cache.

    Fenêtre de terminal
    dig @127.0.0.1 -x 172.16.20.20
    Extrait de la réponse
    ;; ANSWER SECTION:
    20.20.16.172.in-addr.arpa. 604800 IN PTR client.it.fr.
    Fenêtre de terminal
    dig @127.0.0.1 example.com

    Une réponse ici, sans drapeau aa, prouve que les redirecteurs fonctionnent.

Si l’un de ces tests échoue, le tableau ci-dessous couvre les causes les plus fréquentes.

SymptômeCause probableVérification
named-checkzone signale not at top of zoneun point final manquant ou en troprelire chaque nom complet de la zone
Le service refuse de démarrerzone déclarée dont le fichier est absent ou invalidesudo journalctl -u bind9 -n 50
SERVFAIL sur un nom du domainezone non chargée, ou fichier illisible par l’utilisateur bindnamed-checkconf, puis les droits de /etc/bind
NXDOMAIN sur un nom pourtant présentSerial non incrémenté, ancienne version encore en cacheincrémenter le Serial puis sudo rndc reload
Les noms internes répondent, l’extérieur nonredirecteurs absents, ou boucle sur l’adresse du serveurbloc forwarders de named.conf.options
Le client ne résout rien alors que dig @127.0.0.1 fonctionnele client n’interroge pas ce serveurnameserver dans son /etc/resolv.conf
AstuceToujours préciser le serveur interrogé pendant les tests

dig @127.0.0.1 nom force l’interrogation de notre serveur. Sans le @, dig utilise le résolveur du système, qui peut être un autre serveur et donner une réponse trompeuse. C’est la première chose à corriger quand un test « ne veut rien dire ».

Le service répond dans les deux sens pour it.fr et relaie le reste vers l’extérieur. Il pourra désormais servir de résolveur aux autres machines du réseau, à commencer par celles des articles suivants de la série.

Utiliser avec une IA

Actions