Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 419 minIntermédiaire

Serveur DNS BIND 9 sous Debian 13 : zone primaire et secondaire

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • installer BIND et configurer un serveur qui ne fait qu'autorité ;
  • déclarer une zone primaire et écrire son fichier ;
  • vérifier et recharger une zone avec named-checkzone et rndc ;
  • monter un serveur secondaire avec des transferts signés par TSIG ;
  • construire un split DNS avec les vues de BIND.

4 exercices corrigés

BIND 9 (Berkeley Internet Name Domain) est le serveur DNS libre le plus répandu sous Linux, maintenu par l'ISC ; il fait autorité pour des zones, résout pour des clients, ou les deux. Ce chapitre installe BIND 9.20 sur Debian 13 pour publier la zone publique sorbier.example depuis la DMZ, avec un serveur secondaire, des transferts signés et les commandes de contrôle. C'est l'alternative Linux au DNS de Windows Server, à connaître pour comparer les deux en épreuve.

Le projet : un serveur faisant autorité dans la DMZ

Jusqu'ici, la zone publique de Sorbier était gérée dans l'interface web de l'hébergeur. Antoine Mercier, le responsable informatique, veut la maîtriser lui-même : un serveur primaire ns1 dans la DMZ, et le serveur de l'hébergeur en secondaire. Si le site de Sorbier est coupé d'Internet, le secondaire continue de répondre pour la zone (et donc de publier le MX : les courriels attendent au lieu d'être rejetés).

ÉlémentValeur
Serveurns1, VM Debian 13 dans la DMZ (VLAN 60), 192.168.10.230/28, passerelle 192.168.10.238
PublicationLe pare-feu redirige UDP et TCP 53 de 203.0.113.17 vers 192.168.10.230
RôlePrimaire de sorbier.example, sans récursion
Secondairedns2.hebergeur.example (198.51.100.53), qui copie la zone par transfert signé

Installer BIND

bash
sudo apt update
sudo apt install bind9 bind9-utils bind9-dnsutils
named -v                    # BIND 9.20.x (Debian 13 fournit la branche 9.20)
systemctl status named      # le service s'appelle named, bind9 en est un alias

Le paquet crée l'utilisateur système bind, sous lequel le service tourne, et une configuration découpée en fichiers :

Fichier ou dossierContenu
/etc/bind/named.confFichier principal : il inclut les trois suivants, rien d'autre
/etc/bind/named.conf.optionsBloc options : écoute, récursion, sécurité
/etc/bind/named.conf.localTes zones et tes clés
/etc/bind/named.conf.default-zonesZones fournies (racine, localhost, zones inverses locales) : n'y touche pas
/var/lib/bind/Fichiers de zone que BIND doit pouvoir modifier : zones primaires signées, zones dynamiques
/var/cache/bind/Dossier de travail : copies des zones secondaires, cache

Les options : un serveur qui fait autorité, et rien d'autre

text
// /etc/bind/named.conf.options
options {
    directory "/var/cache/bind";

    listen-on { 127.0.0.1; 192.168.10.230; };
    listen-on-v6 { none; };

    // Serveur faisant autorité pour Internet : aucune récursion, pour personne
    recursion no;
    allow-query { any; };

    // Par défaut, personne ne copie les zones ; chaque zone ouvre ce qu'il faut
    allow-transfer { none; };

    // Ne pas afficher la version exacte de BIND à qui la demande
    version none;
};
DirectiveRôle
listen-onAdresses sur lesquelles BIND écoute (port 53 par défaut)
recursion noLe serveur ne répond que pour ses zones. C'est la règle pour un serveur public : un serveur qui ferait aussi la récursion pour Internet serait un résolveur ouvert
allow-query { any; }Tout le monde peut interroger les zones publiques : c'est leur raison d'être
allow-transfer { none; }Interdit les transferts de zone, sauf exception par zone
version noneRefuse de répondre à la question version.bind, qu'un attaquant pose pour chercher les failles connues de ta version

Pour un résolveur interne sous BIND, ce serait l'inverse : recursion yes, et allow-recursion { 192.168.10.64/26; 192.168.10.128/27; 192.168.10.160/27; 192.168.10.208/28; 127.0.0.1; }; pour limiter la récursion aux réseaux internes. Liste les VLAN internes un par un : chez Sorbier, 192.168.10.0/24 contient aussi le VLAN des visiteurs (.0/26) et la DMZ (.224/28), qui n'ont pas à utiliser ce résolveur. La directive dnssec-validation auto; (valeur par défaut) fait valider DNSSEC par le résolveur.

Déclarer la zone primaire

text
// /etc/bind/named.conf.local
include "/etc/bind/transfert-sorbier.key";

zone "sorbier.example" {
    type primary;
    file "/var/lib/bind/db.sorbier.example";
    allow-transfer { key "transfert-sorbier"; };
    also-notify { 192.168.10.233; };    // le secondaire de la maquette, absent des NS
};

zone "230.10.168.192.in-addr.arpa" {
    type primary;
    file "/var/lib/bind/db.192.168.10.230";
};

La seconde zone est un détail utile : ns1 répond à la résolution inverse de sa propre adresse, ce que les outils de test apprécient. Elle ne sert qu'à l'intérieur ; la vraie zone inverse de 203.0.113.17 est chez le fournisseur d'accès (chapitre 2).

Les mots primary et secondary remplacent master et slave depuis BIND 9.16 ; les anciens mots sont encore acceptés, mais écris les nouveaux.

Le fichier de zone

dns
; /var/lib/bind/db.sorbier.example
$TTL 3600
$ORIGIN sorbier.example.
@         IN SOA  ns1.sorbier.example. hostmaster.sorbier.example. (
                  2026110301 ; serial AAAAMMJJnn
                  7200       ; refresh
                  3600       ; retry
                  1209600    ; expire
                  3600 )     ; TTL négatif
          IN NS   ns1.sorbier.example.
          IN NS   dns2.hebergeur.example.
          IN MX   10 mail.sorbier.example.
          IN A    203.0.113.17
          IN TXT  "v=spf1 mx -all"
          IN CAA  0 issue "letsencrypt.org"
ns1       IN A    203.0.113.17
www       IN A    203.0.113.17
suivi     IN A    203.0.113.17
mail      IN A    198.51.100.25
_dmarc    IN TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@sorbier.example"
dns
; /var/lib/bind/db.192.168.10.230
$TTL 3600
@         IN SOA  ns1.sorbier.example. hostmaster.sorbier.example. (
                  2026110301 7200 3600 1209600 3600 )
          IN NS   ns1.sorbier.example.
@         IN PTR  ns1.sorbier.example.

Les fichiers doivent appartenir au groupe bind :

bash
sudo chown root:bind /var/lib/bind/db.sorbier.example /var/lib/bind/db.192.168.10.230
sudo chmod 644 /var/lib/bind/db.sorbier.example /var/lib/bind/db.192.168.10.230

Vérifier avant de recharger

BIND fournit deux vérificateurs. Lance-les à chaque modification, avant tout rechargement : un serveur qui redémarre avec une erreur de syntaxe ne charge pas la zone, et tout le domaine devient introuvable.

bash
# Syntaxe de toute la configuration (aucune sortie = aucune erreur)
sudo named-checkconf

# Contenu d'une zone
sudo named-checkzone sorbier.example /var/lib/bind/db.sorbier.example
# zone sorbier.example/IN: loaded serial 2026110301
# OK

# Recharger la configuration et toutes les zones, sans couper le service
sudo rndc reload

# Ou une seule zone, après modification de son fichier
sudo rndc reload sorbier.example

named-checkzone détecte les erreurs de syntaxe, un CNAME à côté d'autres données, un MX ou un NS qui pointe vers un nom sans adresse dans la zone, et il affiche le serial chargé : vérifie qu'il a bien augmenté.

Tester le serveur

bash
# Depuis ns1 lui-même : la réponse doit porter le drapeau aa
dig @127.0.0.1 sorbier.example SOA +norec
dig @127.0.0.1 mail.sorbier.example A +short
# 198.51.100.25

# La récursion doit être refusée pour un nom extérieur
dig @127.0.0.1 www.service-public.fr
# status: REFUSED, et dig affiche « WARNING: recursion requested but not available »

# Un transfert sans la clé doit échouer
dig @127.0.0.1 sorbier.example AXFR
# ; Transfer failed.

Le drapeau +norec envoie une requête sans demande de récursion, comme le ferait un résolveur d'Internet : c'est la bonne façon de tester un serveur faisant autorité.

Transferts de zone sécurisés avec TSIG

TSIG (Transaction SIGnature, RFC 8945) signe chaque message entre deux serveurs avec une clé secrète partagée : le primaire n'envoie la zone qu'à qui présente la clé, et le secondaire vérifie que la zone vient bien du primaire. Générer la clé :

bash
tsig-keygen -a hmac-sha256 transfert-sorbier | sudo tee /etc/bind/transfert-sorbier.key
sudo chown root:bind /etc/bind/transfert-sorbier.key
sudo chmod 640 /etc/bind/transfert-sorbier.key

Le fichier contient un bloc de cette forme, qui se transmet à l'hébergeur par un canal sûr (jamais par courriel en clair) :

text
key "transfert-sorbier" {
	algorithm hmac-sha256;
	secret "base64-de-32-octets-genere-par-tsig-keygen=";
};

Côté secondaire, ici une VM de ta maquette, 192.168.10.233, dans le même réseau que ns1 (l'hébergeur, lui, joint le primaire par l'adresse publique 203.0.113.17) :

text
// named.conf.local du secondaire
include "/etc/bind/transfert-sorbier.key";

server 192.168.10.230 {
    keys { "transfert-sorbier"; };
};

zone "sorbier.example" {
    type secondary;
    file "/var/cache/bind/db.sorbier.example";
    primaries { 192.168.10.230; };
};

Le bloc server dit au secondaire de signer avec la clé tous les messages vers le primaire. Le secondaire écrit sa copie dans /var/cache/bind/, où il a le droit d'écrire. Quand la zone change sur le primaire, BIND envoie un NOTIFY à tous les serveurs listés dans les NS de la zone (sauf lui-même) et aux adresses de also-notify : le secondaire demande aussitôt un transfert incrémental (IXFR). Le secondaire de la maquette n'est pas dans les NS publics de la zone : sans la ligne also-notify du primaire, il ne verrait les changements qu'à l'expiration du refresh du SOA.

Pour vérifier un transfert à la main, depuis le secondaire :

bash
dig @192.168.10.230 sorbier.example AXFR -k /etc/bind/transfert-sorbier.key
sudo rndc zonestatus sorbier.example     # serial chargé, prochain refresh, expiration
journalctl -u named --since "10 min ago" | grep -i transfer

Les vues : le split DNS dans un seul serveur

Une vue (view) est un jeu de zones servi à une liste de clients. Un même BIND peut ainsi répondre 192.168.10.225 aux réseaux internes et 203.0.113.17 à Internet pour suivi.sorbier.example. Chez Sorbier, le DNS interne est celui de l'annuaire, mais une PME sans Active Directory construit souvent son split DNS ainsi.

text
acl "reseaux-internes" { 192.168.10.64/26; 192.168.10.128/27; 192.168.10.160/27; 192.168.10.208/28; 127.0.0.1; };

view "interne" {
    match-clients { "reseaux-internes"; };
    recursion yes;
    zone "sorbier.example" {
        type primary;
        file "/var/lib/bind/db.sorbier.example.interne";
    };
    include "/etc/bind/named.conf.default-zones";
};

view "externe" {
    match-clients { any; };
    recursion no;
    zone "sorbier.example" {
        type primary;
        file "/var/lib/bind/db.sorbier.example";
        allow-transfer { key "transfert-sorbier"; };
    };
};

Trois règles : dès qu'une vue existe, toutes les zones doivent être dans une vue (retire l'include de named.conf.default-zones du fichier principal et place-le dans la vue interne) ; les vues sont lues dans l'ordre, la première dont match-clients correspond gagne ; et chaque vue a son propre fichier de zone, donc son propre serial à tenir.

BIND ou DNS de Windows Server ?

CritèreDNS de Windows Server 2025BIND 9.20 sur Debian 13
Stockage des zonesDans l'annuaire (zones intégrées) ou en fichiersFichiers texte
RéplicationPar l'annuaire, multimaîtrePrimaire et secondaires, par transfert de zone (NOTIFY, IXFR, TSIG)
Mises à jour dynamiquesSécurisées par Kerberos, natives pour les membres du domainePossibles, signées par TSIG
AdministrationConsole Gestionnaire DNS, PowerShell (DnsServer)Fichiers, named-checkconf, rndc
DNSSECOui (signature de zone, validation)Oui, signature automatique avec dnssec-policy
Split DNSStratégies DNS et étendues de zone, ou zones cibléesVues
Usage typeDNS interne d'un domaine Active DirectoryServeur public faisant autorité, résolveur Linux, hébergeurs

Le choix suit le rôle : l'annuaire impose le DNS de Windows pour la zone interne, et un serveur public en DMZ sur Linux limite la surface d'attaque (pas de compte du domaine sur une machine exposée).

Exercices

Exercice 1 sur 4 Lire une configuration Réussi À revoir

Voici l'extrait d'un named.conf.options trouvé sur un serveur public d'une autre entreprise :

text
options {
    directory "/var/cache/bind";
    recursion yes;
    allow-query { any; };
    allow-transfer { any; };
};
  1. Quels sont les deux problèmes de sécurité ?
  2. Quelles attaques rendent-ils possibles ?
  3. Corrige la configuration pour un serveur qui ne fait qu'autorité.
Voir la réponseMasquer la réponse de l'exercice 1
  1. recursion yes avec allow-query { any; } : c'est un résolveur ouvert à tout Internet. Et allow-transfer { any; } laisse n'importe qui copier toutes les zones.

  2. Le résolveur ouvert sert de réflecteur pour des attaques par amplification (déni de service distribué contre une victime dont l'adresse est usurpée) et s'expose à l'empoisonnement de cache. Le transfert ouvert donne à un attaquant la liste complète des noms et adresses de la zone, utile pour préparer une attaque.

  3. Correction :

    text
    options {
        directory "/var/cache/bind";
        recursion no;
        allow-query { any; };
        allow-transfer { none; };
    };
    

    Puis, dans chaque zone, allow-transfer { key "<clé TSIG>"; }; pour le seul secondaire.

Tu avais trouvé ?

Exercice 2 sur 4 Ajouter un nom Réussi À revoir

Sorbier ouvre extranet.sorbier.example, publié sur 203.0.113.17 comme les autres sites.

  1. Écris la ligne à ajouter dans le fichier de zone, et la modification à faire dans le SOA (on est le 3 novembre 2026 et le serial actuel est 2026110301).
  2. Donne, dans l'ordre, les commandes pour vérifier et appliquer la modification.
  3. Comment vérifies-tu que le secondaire a bien reçu la nouvelle version ?
Voir la réponseMasquer la réponse de l'exercice 2
  1. extranet IN A 203.0.113.17 (ou IN CNAME www.sorbier.example.), et le serial passe à 2026110302.

  2. Les commandes :

    bash
    sudo named-checkzone sorbier.example /var/lib/bind/db.sorbier.example
    sudo rndc reload sorbier.example
    dig @127.0.0.1 extranet.sorbier.example +norec +short
    
  3. Comparer le serial des deux serveurs : dig @192.168.10.230 sorbier.example SOA +short et dig @198.51.100.53 sorbier.example SOA +short doivent afficher 2026110302. Sinon, lire les journaux du primaire (journalctl -u named) : NOTIFY envoyé ? transfert refusé ?

Tu avais trouvé ?

Exercice 3 sur 4 Le transfert qui échoue Réussi À revoir

Après la mise en place de TSIG, le secondaire ne se met plus à jour. Ses journaux contiennent : transfer of 'sorbier.example/IN' from 203.0.113.17#53: failed while receiving responses: REFUSED. Les journaux du primaire indiquent client @0x... 198.51.100.53#40211 (sorbier.example): zone transfer 'sorbier.example/AXFR/IN' denied.

  1. Qui refuse, et pourquoi ?
  2. Cite deux causes possibles côté secondaire.
  3. Quelle autre cause, liée au temps, produirait plutôt une erreur BADTIME ?
Voir la réponseMasquer la réponse de l'exercice 3
  1. C'est le primaire qui refuse : la requête de transfert ne présente pas une clé autorisée par allow-transfer { key "transfert-sorbier"; };.
  2. Le bloc server 192.168.10.230 { keys { "transfert-sorbier"; }; }; manque sur le secondaire (il demande le transfert sans signer), ou la clé n'a pas exactement le même nom, le même algorithme ou le même secret des deux côtés.
  3. Un écart d'horloge de plus de 5 minutes entre les deux serveurs : la signature est jugée trop ancienne ou trop récente. La solution est NTP sur les deux serveurs.

Tu avais trouvé ?

Exercice 4 sur 4 Vue interne et vue externe Réussi À revoir

Une PME sans Active Directory a un seul serveur BIND, 192.168.50.2, pour ses postes (192.168.50.0/24) et pour Internet. Son site www.pme.example est sur 192.168.50.10, publié sur l'adresse publique 203.0.113.40.

  1. Pourquoi faut-il deux vues ?
  2. Quelle vue doit être écrite en premier, et pourquoi ?
  3. Quelle valeur de recursion dans chaque vue ?
Voir la réponseMasquer la réponse de l'exercice 4
  1. Les postes internes doivent recevoir 192.168.50.10 (pour éviter le NAT en épingle), Internet doit recevoir 203.0.113.40. Un seul serveur, deux réponses : il faut deux vues, chacune avec son fichier de zone.
  2. La vue interne d'abord, avec match-clients { 192.168.50.0/24; 127.0.0.1; };. La vue externe a match-clients { any; };, qui correspond à tout le monde : placée en premier, elle capterait aussi les postes internes.
  3. recursion yes dans la vue interne (les postes ont besoin de résoudre Internet), recursion no dans la vue externe (sinon le serveur devient un résolveur ouvert).

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Sécuriser le DNS : DNSSEC, DNS over HTTPS et DNS over TLSRevoir le sommaire du cours