# [COURS] EXERCICES CORRIGÉS DNS - ULTRA DÉTAILLÉS

## [LIVRE] INTRODUCTION

Ce document contient **5 exercices pratiques corrigés** sur DNS (Domain Name System), allant du niveau débutant au niveau expert. Chaque exercice est conçu pour :

- **Renforcer** tes compétences en administration DNS
- **Consolider** les concepts théoriques
- **Simuler** des situations réelles en entreprise
- **Te préparer** à des projets professionnels

**Niveau de progression :**
- [VERT] Exercice 1 : Débutant
- [JAUNE] Exercice 2 : Intermédiaire
- [JAUNE] Exercice 3 : Intermédiaire
- [ROUGE] Exercice 4 : Avancé
- [ROUGE] Exercice 5 : Expert

**Chaque exercice contient :**
- [OK] Énoncé détaillé avec contexte
- [OK] Prérequis et objectifs pédagogiques
- [OK] Solution complète étape par étape
- [OK] Code commenté ligne par ligne
- [OK] Tests de validation
- [OK] Erreurs courantes et solutions
- [OK] Points clés à retenir
- [OK] Pour aller plus loin

**Conseils avant de commencer :**
1. Lis l'énoncé en entier avant de commencer
2. Essaie de résoudre par toi-même avant de regarder la solution
3. Tape chaque commande manuellement
4. Teste à chaque étape
5. Prends des notes sur ce que tu apprends

**Bon courage ! [RAPIDE]**

---

---

# [VERT] EXERCICE 1 : SERVEUR DNS BIND9 - CONFIGURATION DE BASE

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système dans une PME qui vient d'obtenir le nom de domaine `monentreprise.local` pour son réseau interne. La direction te demande de mettre en place un serveur DNS pour :
- Résoudre les noms de machines internes
- Éviter de dépendre uniquement des DNS publics
- Centraliser la gestion des noms de domaine

### Cahier des charges

Le serveur DNS doit :
- Gérer le domaine `monentreprise.local`
- Créer des enregistrements pour :
  - Serveur web : `www.monentreprise.local` -> `192.168.1.10`
  - Serveur mail : `mail.monentreprise.local` -> `192.168.1.20`
  - Serveur fichiers : `files.monentreprise.local` -> `192.168.1.30`
- Gérer la résolution inverse (IP -> nom)
- Forwarder les requêtes externes vers Google DNS (8.8.8.8)

### Contraintes techniques

- Serveur : Ubuntu 22.04 LTS
- DNS : BIND9 (Berkeley Internet Name Domain)
- Réseau : 192.168.1.0/24
- Temps estimé : 2-3 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Installer et configurer BIND9
- [OK] Comprendre la structure des fichiers de zone
- [OK] Créer une zone DNS directe
- [OK] Créer une zone de recherche inversée
- [OK] Configurer les enregistrements DNS (A, PTR, NS, SOA, MX, CNAME)
- [OK] Utiliser dig et nslookup pour tester
- [OK] Diagnostiquer les erreurs DNS courantes
- [OK] Comprendre le fonctionnement du cache DNS

---

## [DOCS] PRÉREQUIS

- Ubuntu 22.04 installé
- Accès root ou sudo
- Connaissances réseau de base (IP, masque de sous-réseau)
- Compréhension du rôle du DNS

---

## [GUIDE] RAPPEL THÉORIQUE : QU'EST-CE QUE LE DNS ?

### Le DNS en quelques mots

**DNS** = Domain Name System (Système de Noms de Domaine)

**Rôle principal :** Traduire les noms de domaine (faciles à retenir) en adresses IP (compréhensibles par les machines)

**Analogie :** Le DNS est comme l'annuaire téléphonique d'Internet
- Nom = "Dupont Jean" -> Numéro = "06 12 34 56 78"
- Domaine = "google.com" -> IP = "142.250.74.206"

---

### Comment fonctionne une requête DNS ?

```
1. Tu tapes "www.google.com" dans ton navigateur

2. Ton PC demande à ton DNS configuré (ex: 192.168.1.1)
   "Quelle est l'IP de www.google.com ?"

3. Si le DNS local ne connaît pas la réponse :
   a. Il interroge un serveur racine (.)
   b. Le serveur racine répond : "Demande au serveur .com"
   c. Le serveur .com répond : "Demande au serveur google.com"
   d. Le serveur google.com répond : "L'IP est 142.250.74.206"

4. Ton DNS local met en cache la réponse

5. Ton PC reçoit l'IP et se connecte au serveur Google
```

**Processus complet :** Résolution récursive

---

### Types d'enregistrements DNS principaux

| Type | Nom complet | Fonction | Exemple |
|------|-------------|----------|---------|
| **A** | Address | Nom -> IPv4 | `www.example.com -> 192.168.1.10` |
| **AAAA** | Address (IPv6) | Nom -> IPv6 | `www.example.com -> 2001:db8::1` |
| **PTR** | Pointer | IP -> Nom (inverse) | `192.168.1.10 -> www.example.com` |
| **CNAME** | Canonical Name | Alias de nom | `ftp.example.com -> www.example.com` |
| **MX** | Mail Exchange | Serveur mail | `example.com -> mail.example.com (priorité 10)` |
| **NS** | Name Server | Serveur DNS autoritaire | `example.com -> ns1.example.com` |
| **SOA** | Start of Authority | Métadonnées de zone | (numéro de série, TTL, etc.) |
| **TXT** | Text | Texte libre | SPF, DKIM, vérifications |

---

### Hiérarchie DNS

```
                    . (racine)
                    |
        ┌───────────┼───────────┐
        |           |           |
       com         net         org
        |
    ┌───┴───┐
    |       |
 google  amazon
    |
    └── www
```

**Nom complet (FQDN) :** `www.google.com.`

Le point final indique la racine (souvent omis).

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Planification de l'infrastructure

**Avant de commencer, planifions notre infrastructure DNS.**

**Informations du serveur :**
- Hostname : `ns1.monentreprise.local`
- IP : `192.168.1.100`
- Domaine géré : `monentreprise.local`
- Réseau : `192.168.1.0/24`

**Machines à enregistrer :**

| Nom | IP | Type |
|-----|-----|------|
| ns1.monentreprise.local | 192.168.1.100 | Serveur DNS |
| www.monentreprise.local | 192.168.1.10 | Serveur web |
| mail.monentreprise.local | 192.168.1.20 | Serveur mail |
| files.monentreprise.local | 192.168.1.30 | Serveur fichiers |
| ftp.monentreprise.local | Alias de www | Alias (CNAME) |

---

### ÉTAPE 2 : Installation de BIND9

```bash
# Mettre à jour la liste des paquets
sudo apt update

# Installer BIND9 et les utilitaires
sudo apt install bind9 bind9utils bind9-doc dnsutils -y
```

**Explication des paquets :**

**bind9**
- Paquet principal du serveur DNS BIND
- Contient le daemon `named` (Name Daemon)

**bind9utils**
- Utilitaires pour administrer BIND
- Commandes : `rndc`, `named-checkconf`, `named-checkzone`

**bind9-doc**
- Documentation de BIND
- Manuels et exemples

**dnsutils**
- Outils de diagnostic DNS
- Commandes : `dig`, `nslookup`, `host`

---

**Vérifier que BIND est installé :**

```bash
named -v
```

**Résultat :**

```
BIND 9.18.12-0ubuntu0.22.04.1 (Extended Support Version)
```

**[OK] BIND9 installé !**

---

**Vérifier le statut du service :**

```bash
sudo systemctl status bind9
```

**Résultat :**

```
[BLACK_CIRCLE] named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-12-16 10:00:00 UTC; 1min ago
   Main PID: 12345 (named)
      Tasks: 5 (limit: 4915)
     Memory: 15.2M
```

**[OK] BIND9 actif et en cours d'exécution !**

---

### ÉTAPE 3 : Comprendre la structure des fichiers BIND

**Arborescence des fichiers BIND :**

```
/etc/bind/
├── named.conf                  <- Configuration principale
├── named.conf.options          <- Options globales
├── named.conf.local            <- Zones locales
├── named.conf.default-zones    <- Zones par défaut (localhost, etc.)
├── db.root                     <- Serveurs racine
├── zones/                      <- Dossier pour nos zones (à créer)
│   ├── db.monentreprise.local       <- Zone directe
│   └── db.192.168.1               <- Zone inverse
└── rndc.key                    <- Clé pour rndc (gestion à distance)
```

**Fichiers clés :**

**named.conf**
- Fichier principal qui inclut les autres
- Rarement modifié directement

**named.conf.options**
- Options globales (forwarders, cache, ACL, etc.)

**named.conf.local**
- * C'est ici qu'on déclare nos zones personnalisées

**db.* (fichiers de zone)**
- Contiennent les enregistrements DNS
- Format texte standardisé (RFC 1035)

---

### ÉTAPE 4 : Configurer les options globales

```bash
sudo nano /etc/bind/named.conf.options
```

**Remplacer TOUT le contenu par :**

```bind
// ═══════════════════════════════════════════════════════════════
// CONFIGURATION GLOBALE DE BIND9
// ═══════════════════════════════════════════════════════════════

options {
    // ───────────────────────────────────────────────────────────
    // RÉPERTOIRE DE TRAVAIL
    // ───────────────────────────────────────────────────────────
    
    directory "/var/cache/bind";
    
    /*
     * directory :
     * Chemin où BIND stocke ses fichiers temporaires et cache
     * /var/cache/bind = Emplacement standard sur Debian/Ubuntu
     */
    
    // ───────────────────────────────────────────────────────────
    // FORWARDERS (REDIRECTIONS DNS)
    // ───────────────────────────────────────────────────────────
    
    forwarders {
        8.8.8.8;        // Google Public DNS
        8.8.4.4;        // Google Public DNS (secondaire)
    };
    
    /*
     * forwarders :
     * Liste des serveurs DNS vers lesquels BIND redirige
     * les requêtes qu'il ne peut pas résoudre lui-même
     * 
     * Exemple :
     * - Requête pour "monentreprise.local" -> BIND répond (zone locale)
     * - Requête pour "google.com" -> BIND forward vers 8.8.8.8
     * 
     * Pourquoi Google DNS ?
     * - Rapide et fiable
     * - Disponibilité mondiale
     * - Gratuit
     * 
     * Alternatives :
     * - Cloudflare : 1.1.1.1, 1.0.0.1
     * - Quad9 : 9.9.9.9
     * - OpenDNS : 208.67.222.222, 208.67.220.220
     * - DNS du FAI
     */
    
    // ───────────────────────────────────────────────────────────
    // DNSSEC (DÉSACTIVÉ POUR L'INSTANT)
    // ───────────────────────────────────────────────────────────
    
    dnssec-validation auto;
    
    /*
     * dnssec-validation :
     * Active la validation DNSSEC
     * 
     * auto = Validation automatique avec les clés intégrées
     * 
     * DNSSEC = DNS Security Extensions
     * Signe cryptographiquement les enregistrements DNS
     * Protège contre le cache poisoning et le spoofing
     * 
     * (Exercice 4 détaillera DNSSEC)
     */
    
    // ───────────────────────────────────────────────────────────
    // ÉCOUTE DES INTERFACES RÉSEAU
    // ───────────────────────────────────────────────────────────
    
    listen-on { 127.0.0.1; 192.168.1.100; };
    listen-on-v6 { ::1; };
    
    /*
     * listen-on :
     * Liste des adresses IPv4 sur lesquelles BIND écoute
     * 
     * 127.0.0.1 = localhost (requêtes locales)
     * 192.168.1.100 = IP de ce serveur (requêtes réseau)
     * 
     * Pour écouter sur TOUTES les interfaces :
     * listen-on { any; };
     * 
     * listen-on-v6 :
     * Liste des adresses IPv6
     * ::1 = localhost IPv6
     */
    
    // ───────────────────────────────────────────────────────────
    // CONTRÔLE D'ACCÈS (ACL - Access Control List)
    // ───────────────────────────────────────────────────────────
    
    allow-query { localhost; 192.168.1.0/24; };
    
    /*
     * allow-query :
     * Qui peut faire des requêtes DNS à ce serveur
     * 
     * localhost = Le serveur lui-même
     * 192.168.1.0/24 = Toutes les IPs de 192.168.1.1 à 192.168.1.254
     * 
     * [ATTENTION] IMPORTANT pour la sécurité !
     * Ne PAS autoriser "any" sur un serveur public
     * (risque d'amplification DDoS)
     * 
     * Syntaxe CIDR :
     * /24 = 255.255.255.0 (254 hôtes)
     * /16 = 255.255.0.0 (65534 hôtes)
     * /8 = 255.0.0.0 (16777214 hôtes)
     */
    
    allow-recursion { localhost; 192.168.1.0/24; };
    
    /*
     * allow-recursion :
     * Qui peut demander une résolution récursive
     * 
     * Résolution récursive :
     * Le serveur DNS fait tout le travail pour trouver la réponse
     * (interroge les serveurs racine, TLD, etc.)
     * 
     * Résolution itérative :
     * Le serveur DNS répond "je ne sais pas, demande à X"
     * Le client doit interroger X lui-même
     * 
     * [ATTENTION] Limiter la récursion pour éviter les abus
     */
    
    allow-transfer { none; };
    
    /*
     * allow-transfer :
     * Qui peut demander un transfert de zone (AXFR)
     * 
     * AXFR = Transfert complet d'une zone
     * Utilisé pour synchroniser master/slave
     * 
     * none = Personne (sécurité par défaut)
     * 
     * En prod, autoriser seulement les DNS secondaires :
     * allow-transfer { 192.168.1.101; 192.168.1.102; };
     */
    
    // ───────────────────────────────────────────────────────────
    // SÉCURITÉ ET PERFORMANCE
    // ───────────────────────────────────────────────────────────
    
    recursion yes;
    
    /*
     * recursion :
     * Active/désactive la résolution récursive
     * 
     * yes = Le serveur fait les recherches complètes
     * no = Le serveur répond seulement pour ses zones autoritaires
     * 
     * Serveur résolveur (cache) : recursion yes
     * Serveur autoritaire pur : recursion no
     */
    
    allow-query-cache { localhost; 192.168.1.0/24; };
    
    /*
     * allow-query-cache :
     * Qui peut interroger le cache DNS
     * 
     * Le cache stocke les réponses récentes pour :
     * - Accélérer les requêtes répétées
     * - Réduire la charge sur les serveurs en amont
     * 
     * TTL (Time To Live) détermine la durée de mise en cache
     */
    
    version "DNS Server";
    
    /*
     * version :
     * Chaîne renvoyée quand on interroge la version
     * 
     * Par défaut, BIND renvoie sa version exacte
     * Problème de sécurité : révèle les vulnérabilités
     * 
     * Mieux : Masquer la version réelle
     * version "DNS Server" ou version "not disclosed"
     * 
     * Test :
     * dig @192.168.1.100 version.bind chaos txt
     */
    
    // ───────────────────────────────────────────────────────────
    // GESTION DU CACHE
    // ───────────────────────────────────────────────────────────
    
    max-cache-size 256M;
    
    /*
     * max-cache-size :
     * Taille maximale du cache en mémoire
     * 
     * 256M = 256 mégaoctets
     * 
     * Plus le cache est grand :
     * + Moins de requêtes vers l'extérieur
     * + Plus de RAM consommée
     * 
     * Recommandations :
     * - Petit serveur : 64M - 256M
     * - Serveur moyen : 512M - 1G
     * - Gros serveur : 2G - 4G
     */
    
    max-cache-ttl 86400;
    
    /*
     * max-cache-ttl :
     * Durée maximale de mise en cache (en secondes)
     * 
     * 86400 = 24 heures (60*60*24)
     * 
     * Même si l'enregistrement a un TTL plus long,
     * BIND le limitera à cette valeur
     * 
     * Évite de garder des données obsolètes trop longtemps
     */
};

// ═══════════════════════════════════════════════════════════════
```

**Sauvegarde : `Ctrl + O`, `Entrée`, `Ctrl + X`**

---

### ÉTAPE 5 : Déclarer nos zones DNS

```bash
sudo nano /etc/bind/named.conf.local
```

**Ajouter :**

```bind
// ═══════════════════════════════════════════════════════════════
// ZONES DNS LOCALES
// ═══════════════════════════════════════════════════════════════

// ───────────────────────────────────────────────────────────────
// ZONE DIRECTE : monentreprise.local
// ───────────────────────────────────────────────────────────────

zone "monentreprise.local" {
    type master;
    file "/etc/bind/zones/db.monentreprise.local";
};

/*
 * zone "monentreprise.local" :
 * Déclare une zone DNS pour le domaine monentreprise.local
 * 
 * type master :
 * Ce serveur est le serveur MAÎTRE (autoritaire) pour cette zone
 * Il détient la copie principale des enregistrements
 * 
 * Autres types possibles :
 * - slave : Serveur secondaire (copie depuis le master)
 * - hint : Serveurs racine
 * - forward : Redirige toutes les requêtes
 * - stub : Zone stub (NS + glue records seulement)
 * 
 * file :
 * Chemin vers le fichier de zone contenant les enregistrements
 * Chemin absolu ou relatif à "directory" (dans options)
 */

// ───────────────────────────────────────────────────────────────
// ZONE INVERSE : 192.168.1.0/24
// ───────────────────────────────────────────────────────────────

zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168.1";
};

/*
 * zone "1.168.192.in-addr.arpa" :
 * Zone de recherche INVERSE (reverse lookup)
 * Permet de retrouver le nom à partir de l'IP
 * 
 * Format : RÉSEAU-INVERSÉ.in-addr.arpa
 * 
 * Exemples :
 * - 192.168.1.0/24 -> 1.168.192.in-addr.arpa
 * - 10.0.0.0/8 -> 0.0.10.in-addr.arpa
 * - 172.16.0.0/16 -> 16.172.in-addr.arpa
 * 
 * Pourquoi inverser ?
 * Parce que DNS fonctionne de droite à gauche
 * 
 * Exemple complet :
 * IP : 192.168.1.10
 * -> Requête PTR pour 10.1.168.192.in-addr.arpa
 * -> Répond avec www.monentreprise.local
 * 
 * Utilité :
 * - Validation de serveurs mail (anti-spam)
 * - Logs plus lisibles (IP -> nom)
 * - Diagnostics réseau
 */

// ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

### ÉTAPE 6 : Créer le dossier pour les fichiers de zone

```bash
sudo mkdir /etc/bind/zones
```

---

### ÉTAPE 7 : Créer le fichier de zone directe

```bash
sudo nano /etc/bind/zones/db.monentreprise.local
```

**Contenu :**

```bind
; ═══════════════════════════════════════════════════════════════
; FICHIER DE ZONE : monentreprise.local
; ═══════════════════════════════════════════════════════════════
; Description : Zone DNS directe pour le domaine monentreprise.local
; Type : Master
; Dernière modification : 2024-12-16
; ═══════════════════════════════════════════════════════════════

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT SOA (START OF AUTHORITY)
; ───────────────────────────────────────────────────────────────

$TTL    86400
@       IN      SOA     ns1.monentreprise.local. admin.monentreprise.local. (
                        2024121601      ; Serial (YYYYMMDDNN)
                        3600            ; Refresh (1 heure)
                        1800            ; Retry (30 minutes)
                        604800          ; Expire (1 semaine)
                        86400 )         ; Negative Cache TTL (1 jour)

/*
 * ═══════════════════════════════════════════════════════════════
 * DÉCORTIQUONS L'ENREGISTREMENT SOA LIGNE PAR LIGNE
 * ═══════════════════════════════════════════════════════════════
 * 
 * $TTL 86400 :
 * Directive spéciale définissant le TTL par défaut pour cette zone
 * 86400 secondes = 24 heures = 1 jour
 * 
 * TTL (Time To Live) :
 * Durée pendant laquelle un enregistrement peut être mis en cache
 * 
 * Plus le TTL est élevé :
 * + Moins de requêtes vers le serveur autoritaire
 * + Moins de charge serveur
 * - Changements plus lents à propager
 * 
 * Plus le TTL est bas :
 * + Changements se propagent rapidement
 * - Plus de charge serveur
 * 
 * Recommandations :
 * - Production stable : 86400 (1 jour)
 * - Avant migration : 300 (5 minutes)
 * - Après migration : Augmenter progressivement
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * @ :
 * Symbole spécial = Nom de la zone elle-même
 * Ici, @ = monentreprise.local
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * IN :
 * Classe d'enregistrement = INternet
 * 
 * Autres classes (rarement utilisées) :
 * - CH (CHaos) : Pour interroger les serveurs BIND
 * - HS (Hesiod) : Ancien système d'annuaire MIT
 * 
 * Par défaut, IN est implicite
 * On peut écrire : @  SOA  ns1...
 * Au lieu de :     @  IN  SOA  ns1...
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * SOA :
 * Type d'enregistrement = Start Of Authority
 * Métadonnées sur la zone
 * 
 * [ATTENTION] OBLIGATOIRE : Chaque zone DOIT avoir UN SEUL enregistrement SOA
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * ns1.monentreprise.local. :
 * MNAME = Master NAME server
 * Nom du serveur DNS principal de cette zone
 * 
 * [ATTENTION] Doit se terminer par un POINT !
 * Le point indique un FQDN (Fully Qualified Domain Name)
 * 
 * Avec point : ns1.monentreprise.local. = nom complet
 * Sans point : ns1 serait interprété comme ns1.monentreprise.local.monentreprise.local
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * admin.monentreprise.local. :
 * RNAME = Responsible NAME (email de l'administrateur)
 * 
 * Format : utilisateur.domaine.
 * Le @ est remplacé par un point
 * 
 * admin.monentreprise.local. = admin@monentreprise.local
 * 
 * Si l'email contient un point :
 * john.doe@example.com -> john\.doe.example.com.
 * (Le point dans le nom est échappé avec \)
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * ( ... ) :
 * Les paramètres SOA peuvent être sur plusieurs lignes
 * Les parenthèses permettent cela
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * 2024121601 :
 * SERIAL = Numéro de série de la zone
 * 
 * [ATTENTION] TRÈS IMPORTANT !
 * Le numéro de série DOIT augmenter à chaque modification
 * Les serveurs secondaires (slaves) s'en servent pour détecter les mises à jour
 * 
 * Format recommandé : YYYYMMDDNN
 * - YYYY = Année (2024)
 * - MM = Mois (12)
 * - DD = Jour (16)
 * - NN = Numéro de révision du jour (01, 02, 03...)
 * 
 * Exemple :
 * - 16 décembre 2024, première modification : 2024121601
 * - 16 décembre 2024, deuxième modification : 2024121602
 * - 17 décembre 2024, première modification : 2024121701
 * 
 * Alternatives :
 * - Format UNIX timestamp : 1702738800
 * - Séquentiel : 1, 2, 3, 4, ...
 * 
 * [ATTENTION] Si tu oublies d'incrémenter le serial :
 * Les serveurs secondaires ne verront PAS les changements !
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * 3600 :
 * REFRESH = Intervalle de rafraîchissement (en secondes)
 * 
 * Fréquence à laquelle les serveurs secondaires vérifient
 * si le numéro de série a changé
 * 
 * 3600 = 1 heure
 * 
 * Processus :
 * 1. Slave attend REFRESH secondes
 * 2. Slave interroge le Master : "Quel est ton serial ?"
 * 3. Si serial Master > serial Slave -> Transfert de zone (AXFR)
 * 4. Sinon -> Attendre REFRESH secondes de plus
 * 
 * Recommandations :
 * - Réseau local stable : 3600 - 7200 (1-2 heures)
 * - Production Internet : 7200 - 28800 (2-8 heures)
 * - Zone très dynamique : 300 - 900 (5-15 minutes)
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * 1800 :
 * RETRY = Intervalle de nouvelle tentative (en secondes)
 * 
 * Si le serveur secondaire n'arrive pas à contacter le master
 * (timeout, panne réseau, etc.), il réessaye après RETRY secondes
 * 
 * 1800 = 30 minutes
 * 
 * Recommandations :
 * - RETRY < REFRESH
 * - Typiquement : RETRY = REFRESH / 2
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * 604800 :
 * EXPIRE = Délai d'expiration (en secondes)
 * 
 * Si le serveur secondaire n'arrive PAS à contacter le master
 * pendant EXPIRE secondes, il arrête de répondre pour cette zone
 * 
 * 604800 = 7 jours = 1 semaine
 * 
 * Scénario catastrophe :
 * 1. Le serveur master tombe en panne
 * 2. Les slaves continuent de répondre (avec leurs données en cache)
 * 3. Après 7 jours sans refresh, les slaves s'arrêtent
 * 4. La zone devient indisponible
 * 
 * Recommandations :
 * - EXPIRE >> REFRESH (au moins 7-10 jours)
 * - Production critique : 1209600 (2 semaines) à 2419200 (4 semaines)
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * 86400 :
 * NEGATIVE CACHE TTL (aussi appelé MINIMUM)
 * 
 * Durée de mise en cache des réponses NÉGATIVES
 * 
 * Réponse négative = "Ce nom n'existe pas" (NXDOMAIN)
 * 
 * Exemple :
 * - Requête pour inexistant.monentreprise.local
 * - Réponse : NXDOMAIN (ce nom n'existe pas)
 * - Cette réponse négative est cachée pendant 86400 secondes
 * 
 * 86400 = 1 jour
 * 
 * Pourquoi cacher les réponses négatives ?
 * - Évite de bombarder le serveur avec des requêtes pour des noms inexistants
 * - Cas d'usage : Typo dans un nom, scan de sécurité, malware
 * 
 * Recommandations :
 * - Valeur modérée : 3600 - 86400 (1 heure à 1 jour)
 * - Trop bas : Charge serveur inutile
 * - Trop haut : Si tu ajoutes un nouveau nom, il faudra attendre
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS NS (NAME SERVER)
; ───────────────────────────────────────────────────────────────

@       IN      NS      ns1.monentreprise.local.

/*
 * Enregistrement NS (Name Server) :
 * Indique quel serveur DNS est autoritaire pour cette zone
 * 
 * @ = monentreprise.local (la zone elle-même)
 * NS = Type d'enregistrement
 * ns1.monentreprise.local. = Nom du serveur DNS
 * 
 * Une zone peut avoir plusieurs serveurs NS :
 * @  IN  NS  ns1.monentreprise.local.
 * @  IN  NS  ns2.monentreprise.local.
 * 
 * Minimum recommandé en production : 2 serveurs NS
 * (redondance en cas de panne)
 * 
 * [ATTENTION] Chaque serveur NS doit avoir un enregistrement A correspondant
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS A (ADDRESS)
; ───────────────────────────────────────────────────────────────

ns1             IN      A       192.168.1.100

/*
 * Enregistrement A (Address) :
 * Associe un nom à une adresse IPv4
 * 
 * ns1 = Nom d'hôte (sera complété en ns1.monentreprise.local)
 * A = Type d'enregistrement (IPv4)
 * 192.168.1.100 = Adresse IP
 * 
 * Pourquoi "ns1" et pas "ns1.monentreprise.local." ?
 * Parce qu'on est dans la zone monentreprise.local
 * Les noms relatifs (sans point final) sont automatiquement complétés
 * 
 * ns1 -> ns1.monentreprise.local.
 * 
 * Si on voulait référencer un nom d'un autre domaine :
 * external  IN  A  1.2.3.4  [X] MAUVAIS (deviendrait external.monentreprise.local)
 * external.example.com.  IN  A  1.2.3.4  [OK] BON (FQDN avec point final)
 */

www             IN      A       192.168.1.10

/*
 * Serveur web
 * www.monentreprise.local -> 192.168.1.10
 */

mail            IN      A       192.168.1.20

/*
 * Serveur mail
 * mail.monentreprise.local -> 192.168.1.20
 */

files           IN      A       192.168.1.30

/*
 * Serveur de fichiers
 * files.monentreprise.local -> 192.168.1.30
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT MX (MAIL EXCHANGE)
; ───────────────────────────────────────────────────────────────

@               IN      MX      10 mail.monentreprise.local.

/*
 * Enregistrement MX (Mail eXchange) :
 * Indique quel serveur gère les emails pour ce domaine
 * 
 * @ = monentreprise.local
 * MX = Type d'enregistrement
 * 10 = Priorité (plus le nombre est BAS, plus la priorité est HAUTE)
 * mail.monentreprise.local. = Serveur mail
 * 
 * Fonctionnement :
 * 1. Un email est envoyé vers admin@monentreprise.local
 * 2. Le serveur expéditeur interroge le DNS :
 *    "Quel est le MX de monentreprise.local ?"
 * 3. Réponse : mail.monentreprise.local (priorité 10)
 * 4. Le serveur interroge : "Quelle est l'IP de mail.monentreprise.local ?"
 * 5. Réponse : 192.168.1.20
 * 6. Connexion SMTP vers 192.168.1.20
 * 
 * Plusieurs serveurs MX (redondance) :
 * @  IN  MX  10  mail1.example.com.
 * @  IN  MX  20  mail2.example.com.
 * @  IN  MX  30  mail3.example.com.
 * 
 * L'expéditeur essaye d'abord mail1 (priorité 10)
 * Si échec, essaye mail2 (priorité 20)
 * Si échec, essaye mail3 (priorité 30)
 * 
 * [ATTENTION] Le serveur MX DOIT avoir un enregistrement A ou AAAA
 * [ATTENTION] Un enregistrement MX ne peut PAS pointer vers un CNAME
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT CNAME (CANONICAL NAME)
; ───────────────────────────────────────────────────────────────

ftp             IN      CNAME   www.monentreprise.local.

/*
 * Enregistrement CNAME (Canonical NAME) :
 * Crée un ALIAS (autre nom) pour un enregistrement existant
 * 
 * ftp = Alias
 * CNAME = Type d'enregistrement
 * www.monentreprise.local. = Nom canonique (réel)
 * 
 * Fonctionnement :
 * 1. Requête pour ftp.monentreprise.local
 * 2. Réponse CNAME : ftp -> www.monentreprise.local
 * 3. Nouvelle requête pour www.monentreprise.local
 * 4. Réponse A : www -> 192.168.1.10
 * 
 * Résultat : ftp.monentreprise.local -> 192.168.1.10
 * 
 * Avantages :
 * - Si l'IP de www change, ftp change aussi automatiquement
 * - Pas besoin de dupliquer les enregistrements A
 * 
 * [ATTENTION] Limitations :
 * - Un CNAME ne peut PAS coexister avec d'autres enregistrements du même nom
 * - Un CNAME ne peut PAS pointer vers un autre CNAME (chaînage interdit)
 * 
 * Exemples VALIDES :
 * ftp  IN  CNAME  www.example.com.  [OK]
 * 
 * Exemples INVALIDES :
 * @ IN CNAME www.example.com.  [X] (le domaine apex ne peut pas être un CNAME)
 * ftp  IN  CNAME  alias.example.com.
 * alias  IN  CNAME  www.example.com.  [X] (chaînage interdit)
 * 
 * mail  IN  CNAME  www.example.com.
 * mail  IN  MX  10  smtp.example.com.  [X] (conflit de nom)
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT TXT (TEXTE)
; ───────────────────────────────────────────────────────────────

@               IN      TXT     "v=spf1 mx ~all"

/*
 * Enregistrement TXT (TeXTe) :
 * Stocke du texte arbitraire
 * 
 * Utilisations courantes :
 * 
 * 1. SPF (Sender Policy Framework) :
 * Indique quels serveurs peuvent envoyer des emails pour ce domaine
 * "v=spf1 mx ~all" signifie :
 * - v=spf1 : Version SPF 1
 * - mx : Les serveurs MX de ce domaine peuvent envoyer
 * - ~all : Tous les autres sont suspects (soft fail)
 * 
 * Autres valeurs SPF :
 * - +all : Tout le monde peut envoyer (dangereux !)
 * - -all : Rejeter tout ce qui n'est pas autorisé (strict)
 * - ?all : Neutre
 * 
 * 2. Vérification de domaine :
 * google-site-verification=abc123...
 * _github-challenge-org.TXT="abc123..."
 * 
 * 3. DKIM (DomainKeys Identified Mail) :
 * Clés publiques pour vérifier les signatures emails
 * 
 * 4. DMARC (Domain-based Message Authentication) :
 * _dmarc  IN  TXT  "v=DMARC1; p=quarantine; rua=mailto:abuse@example.com"
 */

; ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

### ÉTAPE 8 : Créer le fichier de zone inverse

```bash
sudo nano /etc/bind/zones/db.192.168.1
```

**Contenu :**

```bind
; ═══════════════════════════════════════════════════════════════
; FICHIER DE ZONE INVERSE : 192.168.1.0/24
; ═══════════════════════════════════════════════════════════════
; Description : Zone de recherche inverse (PTR)
; Réseau : 192.168.1.0/24
; ═══════════════════════════════════════════════════════════════

$TTL    86400
@       IN      SOA     ns1.monentreprise.local. admin.monentreprise.local. (
                        2024121601      ; Serial
                        3600            ; Refresh
                        1800            ; Retry
                        604800          ; Expire
                        86400 )         ; Negative Cache TTL

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS NS
; ───────────────────────────────────────────────────────────────

@       IN      NS      ns1.monentreprise.local.

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS PTR (POINTER)
; ───────────────────────────────────────────────────────────────

100     IN      PTR     ns1.monentreprise.local.

/*
 * Enregistrement PTR (PoinTeR) :
 * Recherche inverse : IP -> Nom
 * 
 * 100 = Dernier octet de l'IP (192.168.1.100)
 * PTR = Type d'enregistrement
 * ns1.monentreprise.local. = Nom correspondant
 * 
 * Fonctionnement complet :
 * 
 * 1. Requête inverse pour 192.168.1.100
 * 
 * 2. Construction du nom de requête :
 *    - Prendre l'IP : 192.168.1.100
 *    - Inverser les octets : 100.1.168.192
 *    - Ajouter .in-addr.arpa : 100.1.168.192.in-addr.arpa
 * 
 * 3. Requête DNS pour 100.1.168.192.in-addr.arpa
 * 
 * 4. Le serveur DNS autoritaire pour 1.168.192.in-addr.arpa répond
 * 
 * 5. Dans notre zone (db.192.168.1), on a :
 *    100  IN  PTR  ns1.monentreprise.local.
 * 
 * 6. Réponse : ns1.monentreprise.local.
 * 
 * Pourquoi seulement "100" et pas "100.1.168.192" ?
 * Parce que la zone est déjà "1.168.192.in-addr.arpa"
 * Les noms sont relatifs à cette zone
 * 
 * 100 dans la zone 1.168.192.in-addr.arpa
 * = 100.1.168.192.in-addr.arpa
 * = IP 192.168.1.100
 * 
 * Utilité des PTR :
 * - Serveurs mail : Validation anti-spam
 *   (Beaucoup de serveurs rejettent les emails si pas de PTR)
 * - Logs : Afficher les noms au lieu des IPs
 * - Diagnostics : traceroute, etc.
 * 
 * [ATTENTION] BONNES PRATIQUES :
 * 
 * 1. Cohérence A <-> PTR :
 * Si www.example.com -> 192.168.1.10 (A)
 * Alors 192.168.1.10 -> www.example.com (PTR)
 * 
 * 2. Pas de PTR multiples pour une même IP :
 * [X] MAUVAIS :
 * 10  IN  PTR  www.example.com.
 * 10  IN  PTR  mail.example.com.
 * 
 * [OK] BON : Choisir UN nom principal
 * 10  IN  PTR  www.example.com.
 */

10      IN      PTR     www.monentreprise.local.
20      IN      PTR     mail.monentreprise.local.
30      IN      PTR     files.monentreprise.local.

/*
 * 10 = 192.168.1.10 -> www.monentreprise.local
 * 20 = 192.168.1.20 -> mail.monentreprise.local
 * 30 = 192.168.1.30 -> files.monentreprise.local
 */

; ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

### ÉTAPE 9 : Vérifier la syntaxe des fichiers

**BIND fournit des outils pour valider la configuration AVANT de redémarrer.**

**Vérifier la configuration générale :**

```bash
sudo named-checkconf
```

**Si aucune erreur, la commande ne renvoie RIEN.**

**[OK] Configuration générale OK !**

---

**Si erreur, exemple :**

```
/etc/bind/named.conf.local:5: missing ';' before '}'
```

**Ligne 5 du fichier, il manque un point-virgule.**

---

**Vérifier la zone directe :**

```bash
sudo named-checkzone monentreprise.local /etc/bind/zones/db.monentreprise.local
```

**Résultat attendu :**

```
zone monentreprise.local/IN: loaded serial 2024121601
OK
```

**[OK] Zone directe OK !**

---

**Vérifier la zone inverse :**

```bash
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1
```

**Résultat :**

```
zone 1.168.192.in-addr.arpa/IN: loaded serial 2024121601
OK
```

**[OK] Zone inverse OK !**

---

**Si erreur de syntaxe, exemple :**

```
/etc/bind/zones/db.monentreprise.local:15: NS 'ns1.monentreprise.local' has no address records (A or AAAA)
zone monentreprise.local/IN: not loaded due to errors.
```

**Le serveur NS n'a pas d'enregistrement A.**

**Solution : Ajouter l'enregistrement A pour ns1.**

---

### ÉTAPE 10 : Redémarrer BIND9

```bash
sudo systemctl restart bind9
```

---

**Vérifier qu'il n'y a pas d'erreur :**

```bash
sudo systemctl status bind9
```

**Résultat :**

```
[BLACK_CIRCLE] named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled)
     Active: active (running) since Mon 2024-12-16 12:00:00 UTC; 5s ago
   Main PID: 23456 (named)
      Tasks: 5
     Memory: 18.5M
```

**[OK] BIND9 redémarré avec succès !**

---

**Consulter les logs en cas de problème :**

```bash
sudo journalctl -u bind9 -n 50 --no-pager
```

**Ou :**

```bash
sudo tail -50 /var/log/syslog | grep named
```

---

### ÉTAPE 11 : Tester les résolutions DNS

**Avant de tester, configurer le serveur pour utiliser son propre DNS.**

**Éditer `/etc/resolv.conf` :**

```bash
sudo nano /etc/resolv.conf
```

**Ajouter en PREMIER :**

```
nameserver 127.0.0.1
nameserver 8.8.8.8
```

**Explication :**
- `nameserver 127.0.0.1` : Utiliser le DNS local (notre BIND)
- `nameserver 8.8.8.8` : Fallback si le DNS local ne répond pas

---

**[ATTENTION] Sur Ubuntu avec systemd-resolved :**

```bash
sudo nano /etc/systemd/resolved.conf
```

**Modifier :**

```ini
[Resolve]
DNS=127.0.0.1
FallbackDNS=8.8.8.8 8.8.4.4
```

**Redémarrer :**

```bash
sudo systemctl restart systemd-resolved
```

---

**Tester avec `dig` (DNS lookup utility) :**

**Test 1 : Résolution du serveur DNS lui-même**

```bash
dig ns1.monentreprise.local
```

**Résultat attendu :**

```
; <<>> DiG 9.18.12 <<>> ns1.monentreprise.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;ns1.monentreprise.local.       IN      A

;; ANSWER SECTION:
ns1.monentreprise.local. 86400  IN      A       192.168.1.100

;; AUTHORITY SECTION:
monentreprise.local.    86400   IN      NS      ns1.monentreprise.local.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 16 12:05:00 UTC 2024
;; MSG SIZE  rcvd: 89
```

**Décodons cette réponse :**

**`status: NOERROR`**
- Pas d'erreur, la requête a réussi

**`flags: qr aa rd ra`**
- `qr` = Query Response (c'est une réponse)
- `aa` = Authoritative Answer (réponse autoritaire)
- `rd` = Recursion Desired (récursion demandée)
- `ra` = Recursion Available (récursion disponible)

**`QUESTION SECTION`**
- La question posée : "Quelle est l'IP de ns1.monentreprise.local ?"

**`ANSWER SECTION`**
- La réponse : ns1.monentreprise.local = 192.168.1.100
- 86400 = TTL (durée de cache)

**`AUTHORITY SECTION`**
- Serveur NS autoritaire pour cette zone

**`Query time: 0 msec`**
- Temps de réponse instantané (serveur local)

**`SERVER: 127.0.0.1#53`**
- Serveur DNS interrogé : 127.0.0.1 port 53

**[OK] Résolution directe fonctionne !**

---

**Test 2 : Résolution du serveur web**

```bash
dig www.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
www.monentreprise.local. 86400  IN      A       192.168.1.10
```

**[OK] www -> 192.168.1.10**

---

**Test 3 : Résolution de l'alias FTP (CNAME)**

```bash
dig ftp.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
ftp.monentreprise.local. 86400  IN      CNAME   www.monentreprise.local.
www.monentreprise.local. 86400  IN      A       192.168.1.10
```

**Explication :**
- Ligne 1 : ftp est un CNAME vers www
- Ligne 2 : www a l'IP 192.168.1.10

**[OK] Alias CNAME fonctionne !**

---

**Test 4 : Enregistrement MX (serveur mail)**

```bash
dig monentreprise.local MX
```

**Résultat :**

```
;; ANSWER SECTION:
monentreprise.local.    86400   IN      MX      10 mail.monentreprise.local.

;; ADDITIONAL SECTION:
mail.monentreprise.local. 86400 IN      A       192.168.1.20
```

**Explication :**
- MX priorité 10 -> mail.monentreprise.local
- Section additionnelle : IP de mail

**[OK] Enregistrement MX fonctionne !**

---

**Test 5 : Résolution inverse (PTR)**

```bash
dig -x 192.168.1.100
```

**`-x` = Raccourci pour recherche inverse**

**Résultat :**

```
;; ANSWER SECTION:
100.1.168.192.in-addr.arpa. 86400 IN    PTR     ns1.monentreprise.local.
```

**[OK] 192.168.1.100 -> ns1.monentreprise.local**

---

**Test 6 : Résolution externe (forwarding vers Google DNS)**

```bash
dig google.com
```

**Résultat :**

```
;; ANSWER SECTION:
google.com.             300     IN      A       142.250.74.206

;; Query time: 25 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
```

**Explication :**
- Notre serveur ne gère pas google.com
- Il a forwardé la requête vers 8.8.8.8
- Reçu la réponse et l'a mise en cache
- Query time = 25 ms (temps de l'aller-retour vers 8.8.8.8)

**[OK] Forwarding fonctionne !**

---

**Test avec `nslookup` (alternative à dig) :**

```bash
nslookup www.monentreprise.local
```

**Résultat :**

```
Server:         127.0.0.1
Address:        127.0.0.1#53

Name:   www.monentreprise.local
Address: 192.168.1.10
```

**[OK] Fonctionne aussi avec nslookup !**

---

### ÉTAPE 12 : Configurer les clients pour utiliser ce DNS

**Sur un PC client Windows :**

```
1. Panneau de configuration -> Réseau et Internet
2. Centre Réseau et partage
3. Modifier les paramètres de la carte
4. Clic droit sur la connexion -> Propriétés
5. Protocole Internet Version 4 (TCP/IPv4) -> Propriétés
6. Utiliser l'adresse de serveur DNS suivante :
   - Serveur DNS préféré : 192.168.1.100
   - Serveur DNS auxiliaire : 8.8.8.8
7. OK
```

---

**Sur un PC client Linux :**

```bash
sudo nano /etc/resolv.conf
```

**Ajouter :**

```
nameserver 192.168.1.100
nameserver 8.8.8.8
```

**Ou avec NetworkManager :**

```bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns "192.168.1.100 8.8.8.8"
sudo nmcli connection down "Wired connection 1"
sudo nmcli connection up "Wired connection 1"
```

---

**Tester depuis le client :**

```bash
ping www.monentreprise.local
```

**Résultat :**

```
PING www.monentreprise.local (192.168.1.10) 56(84) bytes of data.
64 bytes from www.monentreprise.local (192.168.1.10): icmp_seq=1 ttl=64 time=0.5 ms
```

**[OK] Résolution DNS fonctionne depuis les clients !**

---

### [OK] TESTS DE VALIDATION

**1. Résolutions directes**

- [ ] `dig ns1.monentreprise.local` -> 192.168.1.100
- [ ] `dig www.monentreprise.local` -> 192.168.1.10
- [ ] `dig mail.monentreprise.local` -> 192.168.1.20
- [ ] `dig files.monentreprise.local` -> 192.168.1.30

---

**2. Résolution CNAME**

- [ ] `dig ftp.monentreprise.local` -> CNAME www -> 192.168.1.10

---

**3. Enregistrement MX**

- [ ] `dig monentreprise.local MX` -> mail.monentreprise.local priorité 10

---

**4. Résolutions inverses (PTR)**

- [ ] `dig -x 192.168.1.100` -> ns1.monentreprise.local
- [ ] `dig -x 192.168.1.10` -> www.monentreprise.local
- [ ] `dig -x 192.168.1.20` -> mail.monentreprise.local

---

**5. Forwarding**

- [ ] `dig google.com` -> Réponse valide (via Google DNS)
- [ ] Query time < 100 ms

---

**6. Flags autoritaires**

```bash
dig www.monentreprise.local | grep "flags:"
```

- [ ] Doit contenir `aa` (Authoritative Answer)

---

**7. Vérifier le cache**

```bash
# Vider le cache
sudo rndc flush

# Faire une requête externe
dig google.com

# Refaire la même requête
dig google.com
```

- [ ] Le 2ème query time doit être BEAUCOUP plus rapide (< 1 ms)

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "connection timed out; no servers could be reached"

**Symptôme :**

```bash
dig www.monentreprise.local
```

```
;; connection timed out; no servers could be reached
```

**Causes possibles :**

**1. BIND ne tourne pas**

```bash
sudo systemctl status bind9
```

**Si inactif :**

```bash
sudo systemctl start bind9
```

---

**2. Pare-feu bloque le port 53**

```bash
sudo ufw status
```

**Si actif et port 53 bloqué :**

```bash
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
```

---

**3. BIND n'écoute pas sur la bonne interface**

```bash
sudo netstat -tulpn | grep :53
```

**Doit afficher :**

```
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      12345/named
tcp        0      0 192.168.1.100:53        0.0.0.0:*               LISTEN      12345/named
udp        0      0 127.0.0.1:53            0.0.0.0:*                           12345/named
udp        0      0 192.168.1.100:53        0.0.0.0:*                           12345/named
```

**Si absent, vérifier `listen-on` dans `/etc/bind/named.conf.options`.**

---

#### Erreur 2 : "SERVFAIL"

**Symptôme :**

```bash
dig www.monentreprise.local
```

```
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 12345
```

**SERVFAIL = Erreur serveur**

**Causes :**

**1. Erreur de syntaxe dans le fichier de zone**

```bash
sudo named-checkzone monentreprise.local /etc/bind/zones/db.monentreprise.local
```

**Corriger les erreurs.**

---

**2. Zone non déclarée**

```bash
sudo named-checkconf
```

**Vérifier `/etc/bind/named.conf.local`.**

---

**3. Permissions incorrectes**

```bash
ls -l /etc/bind/zones/
```

**Doit être :**

```
-rw-r--r-- 1 bind bind 1234 Dec 16 12:00 db.monentreprise.local
```

**Si incorrect :**

```bash
sudo chown bind:bind /etc/bind/zones/*
sudo chmod 644 /etc/bind/zones/*
```

---

#### Erreur 3 : "NXDOMAIN"

**Symptôme :**

```bash
dig inexistant.monentreprise.local
```

```
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 12345
```

**NXDOMAIN = Ce nom n'existe pas**

**C'est NORMAL si le nom n'est vraiment pas dans la zone.**

**Si le nom DEVRAIT exister :**

**1. Vérifier qu'il est dans le fichier de zone**

```bash
grep inexistant /etc/bind/zones/db.monentreprise.local
```

---

**2. Vérifier que le serial a été incrémenté**

Si tu as modifié la zone, tu DOIS incrémenter le serial.

---

**3. Recharger la zone**

```bash
sudo rndc reload monentreprise.local
```

---

#### Erreur 4 : Pas de résolution inverse

**Symptôme :**

```bash
dig -x 192.168.1.10
```

```
;; ANSWER SECTION:
# (vide)
```

**Causes :**

**1. Zone inverse non déclarée**

Vérifier `/etc/bind/named.conf.local` :

```bind
zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168.1";
};
```

---

**2. Enregistrement PTR manquant**

Vérifier `/etc/bind/zones/db.192.168.1` :

```bind
10      IN      PTR     www.monentreprise.local.
```

---

**3. Mauvais nom de zone**

Pour 192.168.1.0/24, le nom de zone DOIT être :

```
1.168.192.in-addr.arpa
```

**Pas :**
- `192.168.1.in-addr.arpa` [X]
- `1.168.192.0.in-addr.arpa` [X]

---

#### Erreur 5 : Forwarding ne fonctionne pas

**Symptôme :**

```bash
dig google.com
```

**Timeout ou SERVFAIL**

**Causes :**

**1. Forwarders mal configurés**

Vérifier `/etc/bind/named.conf.options` :

```bind
forwarders {
    8.8.8.8;
    8.8.4.4;
};
```

---

**2. Pas de route vers les forwarders**

```bash
ping 8.8.8.8
```

**Si pas de réponse, problème réseau.**

---

**3. Pare-feu sortant bloque le port 53**

```bash
sudo ufw status
```

**Autoriser :**

```bash
sudo ufw allow out 53/tcp
sudo ufw allow out 53/udp
```

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. Structure DNS**
- Zone = Domaine géré par un serveur
- Fichier de zone = Contient les enregistrements
- FQDN = Nom complet se terminant par un point

**2. Enregistrements principaux**
- A : Nom -> IPv4
- AAAA : Nom -> IPv6
- PTR : IP -> Nom (inverse)
- CNAME : Alias
- MX : Serveur mail
- NS : Serveur DNS autoritaire
- SOA : Métadonnées de zone

**3. Serial**
- DOIT augmenter à chaque modification
- Format recommandé : YYYYMMDDNN
- Les slaves s'en servent pour détecter les mises à jour

**4. TTL**
- Durée de mise en cache
- Plus élevé = Moins de charge, changements lents
- Plus bas = Charge élevée, changements rapides
- Recommandation : 86400 (1 jour)

**5. Outils de test**
- `dig` : Outil principal (détaillé)
- `nslookup` : Alternative simple
- `host` : Encore plus simple
- `named-checkconf` : Valider la config
- `named-checkzone` : Valider une zone
- `rndc` : Contrôler BIND à distance

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Ajouter des sous-domaines**

```bind
; Dans db.monentreprise.local
dev.www    IN  A  192.168.1.11
test.www   IN  A  192.168.1.12
```

**Résultat :**
- `dev.www.monentreprise.local` -> 192.168.1.11
- `test.www.monentreprise.local` -> 192.168.1.12

---

**2. Wildcard DNS**

```bind
*.app      IN  A  192.168.1.50
```

**Résultat :**
- `toto.app.monentreprise.local` -> 192.168.1.50
- `titi.app.monentreprise.local` -> 192.168.1.50
- Etc.

**Utile pour :** Environnements multi-tenants, tests

---

**3. Enregistrements SRV (Services)**

```bind
_ldap._tcp  IN  SRV  0 5 389 ldap.monentreprise.local.
```

**Format :** `_service._protocol priorité poids port cible`

**Utilité :** Découverte automatique de services (LDAP, Kerberos, SIP, etc.)

---

**4. Logging et monitoring**

```bind
# Dans /etc/bind/named.conf.options
logging {
    channel query_log {
        file "/var/log/named/query.log" versions 3 size 5m;
        severity info;
        print-time yes;
    };
    category queries { query_log; };
};
```

**Créer le dossier :**

```bash
sudo mkdir /var/log/named
sudo chown bind:bind /var/log/named
```

**Logs de toutes les requêtes DNS.**

---

**5. Statistiques avec `rndc`**

```bash
# Activer les stats
sudo rndc stats

# Consulter
sudo cat /var/cache/bind/named.stats
```

**Infos :**
- Nombre de requêtes
- Types de requêtes (A, AAAA, MX, etc.)
- Taux de cache hit/miss
- Etc.

---

**6. Zone de transfert dynamique (DDNS)**

Permet de mettre à jour les enregistrements sans éditer le fichier manuellement.

**Utilité :** DHCP qui met à jour le DNS automatiquement

---

**7. Split DNS (vues)**

Réponses différentes selon l'IP du client.

**Exemple :**
- Client interne -> www = 192.168.1.10
- Client externe -> www = 203.0.113.10

---

## [COURS] CONCLUSION DE L'EXERCICE 1

**[OK] Félicitations ! Tu as configuré un serveur DNS BIND9 fonctionnel !**

**Ce que tu as appris :**
- Installer et configurer BIND9
- Comprendre la structure des zones DNS
- Créer des enregistrements A, PTR, NS, SOA, MX, CNAME, TXT
- Configurer les forwarders
- Utiliser dig et nslookup pour tester
- Diagnostiquer les erreurs courantes
- Gérer le cache DNS

**Compétences acquises :**
- [OK] Administration DNS (niveau débutant-intermédiaire)
- [OK] Fichiers de zone BIND
- [OK] Résolution directe et inverse
- [OK] Diagnostic DNS

**Temps moyen de réalisation :** 2-3 heures

**Prochaine étape :** Exercice 2 - DNS secondaire et transferts de zone ! [SYNC]

---

---

Je vais continuer avec les exercices 2, 3, 4 et 5 dans les prochaines réponses pour respecter la limite de longueur. Veux-tu que je continue ?

# [JAUNE] EXERCICE 2 : DNS SECONDAIRE ET TRANSFERTS DE ZONE

## [LISTE] ÉNONCÉ

### Contexte professionnel

La direction de ton entreprise est satisfaite du serveur DNS mis en place. Cependant, le RSSI (Responsable Sécurité des Systèmes d'Information) soulève un problème critique :

**"Que se passe-t-il si le serveur DNS primaire tombe en panne ?"**

Ta mission : Mettre en place une **infrastructure DNS redondante** avec un serveur secondaire (slave) qui se synchronise automatiquement avec le serveur primaire (master).

### Cahier des charges

L'infrastructure doit comprendre :
- **Serveur DNS primaire (master)** : ns1.monentreprise.local (192.168.1.100)
- **Serveur DNS secondaire (slave)** : ns2.monentreprise.local (192.168.1.101)
- Transfert de zone automatique (AXFR)
- Synchronisation en temps réel (NOTIFY)
- Mécanisme de bascule (failover)
- Documentation de la procédure de récupération après incident

### Objectifs techniques

- Configurer le serveur master pour autoriser les transferts de zone
- Installer et configurer un serveur slave
- Mettre en place les notifications NOTIFY
- Tester les transferts de zone (AXFR/IXFR)
- Valider le failover automatique
- Sécuriser les transferts avec TSIG (clés partagées)

### Contraintes

- Les deux serveurs doivent être autoritaires
- Synchronisation automatique en moins de 1 minute
- Aucune perte de données en cas de panne du master
- Temps estimé : 2-3 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre les rôles master/slave en DNS
- [OK] Configurer les transferts de zone AXFR et IXFR
- [OK] Mettre en place les notifications NOTIFY
- [OK] Sécuriser les transferts avec TSIG
- [OK] Diagnostiquer les problèmes de synchronisation
- [OK] Tester le failover DNS
- [OK] Gérer les numéros de série (serial)
- [OK] Monitorer la réplication DNS

---

## [DOCS] PRÉREQUIS

- Exercice 1 terminé (serveur DNS master fonctionnel)
- Deuxième serveur Ubuntu 22.04 (ou VM)
- Compréhension des concepts de réplication
- Accès réseau entre les deux serveurs

---

## [GUIDE] RAPPEL THÉORIQUE : MASTER/SLAVE DNS

### Pourquoi plusieurs serveurs DNS ?

**Problème :** Un seul serveur DNS = **Single Point of Failure (SPOF)**

**Scénario catastrophe :**
```
1. Le serveur DNS tombe en panne (panne matérielle, coupure réseau, etc.)
2. Tous les clients ne peuvent plus résoudre les noms
3. www.monentreprise.local devient inaccessible
4. Les emails ne peuvent plus être envoyés/reçus
5. Paralysie complète de l'infrastructure
```

**Solution :** **Redondance DNS**

```
                    Clients
                       |
        ┌──────────────┼──────────────┐
        |                             |
    ns1 (Master)                  ns2 (Slave)
    192.168.1.100                 192.168.1.101
        |
    Zone authoritaire
    (db.monentreprise.local)
        |
        └──── Transfert de zone ────> Copie synchronisée
                (AXFR/IXFR)
```

---

### Master vs Slave

| Caractéristique | Master (Primaire) | Slave (Secondaire) |
|-----------------|-------------------|-------------------|
| **Édition des zones** | [OK] Oui, fichiers locaux | [X] Non, lecture seule |
| **Source de vérité** | [OK] Oui | [X] Non, copie du master |
| **Réponses autoritaires** | [OK] Oui | [OK] Oui (même données) |
| **Transferts de zone** | Envoie vers slaves | Reçoit du master |
| **Failover** | Si en panne, slaves prennent le relais | Si en panne, master continue |
| **Fichiers de zone** | Modifiés manuellement | Générés automatiquement |

---

### Types de transferts de zone

**AXFR (Full Zone Transfer)**
- Transfert COMPLET de la zone
- Utilisé lors de la première synchronisation
- Ou si le slave a perdu ses données

**IXFR (Incremental Zone Transfer)**
- Transfert INCRÉMENTAL (seulement les changements)
- Plus rapide et moins gourmand en bande passante
- Nécessite que le master conserve l'historique des changements

**Exemple :**

```
Master :
- Version 1 (serial 2024121601) : 10 enregistrements
- Version 2 (serial 2024121602) : 11 enregistrements (1 ajouté)
- Version 3 (serial 2024121603) : 12 enregistrements (1 ajouté)

AXFR : Transfère les 12 enregistrements complets
IXFR : Transfère seulement les 2 enregistrements ajoutés
```

---

### Mécanisme NOTIFY

**Problème :**
Sans notification, le slave vérifie périodiquement (selon REFRESH dans SOA).

```
Master modifié à 10:00
Slave REFRESH = 3600s (1 heure)
-> Le slave détectera le changement à 11:00 au plus tôt
-> Délai de propagation : 1 heure !
```

**Solution : NOTIFY**

```
1. Administrateur modifie la zone sur le master
2. Master incrémente le serial : 2024121601 -> 2024121602
3. Master envoie immédiatement une notification NOTIFY au slave
4. Slave reçoit NOTIFY : "Hey, j'ai une nouvelle version !"
5. Slave interroge le master : "Quel est ton serial ?"
6. Master répond : "2024121602"
7. Slave compare : Son serial (2024121601) < Master (2024121602)
8. Slave lance un transfert IXFR
9. Synchronisation terminée en quelques secondes
```

**Résultat : Délai de propagation < 1 minute**

---

### Sécurité : TSIG (Transaction SIGnature)

**Problème :**
Par défaut, les transferts de zone ne sont PAS chiffrés ni authentifiés.

**Risques :**
- Un attaquant peut intercepter les transferts (données sensibles)
- Un attaquant peut se faire passer pour un slave et demander un transfert
- Un attaquant peut empoisonner le cache en envoyant de fausses réponses

**Solution : TSIG**

**TSIG** = Transaction SIGnature
- Authentification cryptographique basée sur des clés partagées
- Signature HMAC (Hash-based Message Authentication Code)
- Protège les transferts de zone et les notifications

**Fonctionnement :**

```
1. Master et Slave partagent une clé secrète (generée avec dnssec-keygen)
2. Lors d'un transfert :
   - Master calcule HMAC(données + clé secrète) = Signature
   - Master envoie : données + signature
3. Slave reçoit et vérifie :
   - Calcule HMAC(données reçues + clé secrète)
   - Compare avec la signature reçue
   - Si identique -> Authentique
   - Sinon -> Rejet
```

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Préparer le serveur secondaire

**Sur le NOUVEAU serveur (ns2) :**

```bash
# Mettre à jour
sudo apt update

# Installer BIND9
sudo apt install bind9 bind9utils bind9-doc dnsutils -y
```

---

**Configurer l'hostname :**

```bash
sudo hostnamectl set-hostname ns2
```

---

**Configurer une IP fixe (si DHCP) :**

```bash
sudo nano /etc/netplan/01-netcfg.yaml
```

**Contenu :**

```yaml
network:
  version: 2
  ethernets:
    ens33:  # Adapter selon ton interface
      addresses:
        - 192.168.1.101/24
      gateway4: 192.168.1.1
      nameservers:
        addresses:
          - 127.0.0.1
          - 8.8.8.8
```

**Appliquer :**

```bash
sudo netplan apply
```

---

**Vérifier la connectivité entre master et slave :**

**Depuis ns2 (slave) :**

```bash
ping 192.168.1.100
```

**Résultat :**

```
PING 192.168.1.100 56(84) bytes of data.
64 bytes from 192.168.1.100: icmp_seq=1 ttl=64 time=0.5 ms
```

**[OK] Connectivité OK**

---

### ÉTAPE 2 : Générer une clé TSIG partagée

**Sur le serveur MASTER (ns1) :**

```bash
# Générer une clé TSIG
sudo tsig-keygen -a hmac-sha256 transfer-key > /etc/bind/keys/transfer.key
```

**Explication de la commande :**

**`tsig-keygen`**
- Outil pour générer des clés TSIG

**`-a hmac-sha256`**
- Algorithme de hachage : HMAC-SHA256
- Autres options : hmac-md5, hmac-sha1, hmac-sha512
- SHA256 = Bon compromis sécurité/performance

**`transfer-key`**
- Nom de la clé (arbitraire)

**`> /etc/bind/keys/transfer.key`**
- Sauvegarder dans un fichier

---

**Créer le dossier si nécessaire :**

```bash
sudo mkdir -p /etc/bind/keys
```

---

**Examiner la clé générée :**

```bash
sudo cat /etc/bind/keys/transfer.key
```

**Résultat :**

```bind
key "transfer-key" {
    algorithm hmac-sha256;
    secret "AbCdEf123456789+/abcdef==";
};
```

**Explication :**

**`key "transfer-key"`**
- Nom de la clé

**`algorithm hmac-sha256;`**
- Algorithme utilisé

**`secret "...";`**
- La clé secrète encodée en Base64
- [ATTENTION] GARDER SECRÈTE !
- Ne JAMAIS la partager en clair (sauf entre master/slave)

---

**Copier cette clé vers le slave :**

```bash
sudo scp /etc/bind/keys/transfer.key user@192.168.1.101:/tmp/
```

**[ATTENTION] Méthode sécurisée : SCP (SSH Copy)**

---

**Sur le serveur SLAVE (ns2) :**

```bash
# Créer le dossier
sudo mkdir -p /etc/bind/keys

# Déplacer la clé
sudo mv /tmp/transfer.key /etc/bind/keys/

# Sécuriser les permissions
sudo chown bind:bind /etc/bind/keys/transfer.key
sudo chmod 600 /etc/bind/keys/transfer.key
```

**Permissions 600 :**
- Propriétaire (bind) : rw-
- Groupe : ---
- Autres : ---

**Seul BIND peut lire la clé !**

---

### ÉTAPE 3 : Configurer le serveur MASTER

**Sur ns1 (master), éditer `/etc/bind/named.conf.local` :**

```bash
sudo nano /etc/bind/named.conf.local
```

**Modifier pour inclure la clé et configurer les transferts :**

```bind
// ═══════════════════════════════════════════════════════════════
// ZONES DNS LOCALES - CONFIGURATION MASTER/SLAVE
// ═══════════════════════════════════════════════════════════════

// ───────────────────────────────────────────────────────────────
// INCLUSION DE LA CLÉ TSIG
// ───────────────────────────────────────────────────────────────

include "/etc/bind/keys/transfer.key";

/*
 * include :
 * Charge le contenu d'un autre fichier
 * 
 * Ici, on charge la clé TSIG générée
 * 
 * Équivalent à copier-coller le contenu de transfer.key ici
 */

// ───────────────────────────────────────────────────────────────
// DÉFINITION DES SERVEURS SECONDAIRES
// ───────────────────────────────────────────────────────────────

// Liste des serveurs slaves autorisés
acl "trusted-slaves" {
    192.168.1.101;  // ns2
    // Ajouter d'autres slaves ici si nécessaire
};

/*
 * acl (Access Control List) :
 * Définit un groupe d'adresses IP
 * 
 * "trusted-slaves" = Nom de l'ACL (arbitraire)
 * 
 * Avantages :
 * - Réutilisable dans plusieurs zones
 * - Plus lisible que répéter les IPs
 * - Centralisé (facile de modifier)
 * 
 * Exemple d'utilisation :
 * allow-transfer { trusted-slaves; };
 * Au lieu de :
 * allow-transfer { 192.168.1.101; 192.168.1.102; ... };
 */

// ───────────────────────────────────────────────────────────────
// ZONE DIRECTE : monentreprise.local
// ───────────────────────────────────────────────────────────────

zone "monentreprise.local" {
    type master;
    file "/etc/bind/zones/db.monentreprise.local";
    
    // Autoriser les transferts de zone vers les slaves
    allow-transfer { key transfer-key; };
    
    /*
     * allow-transfer { key transfer-key; } :
     * 
     * Autorise les transferts de zone UNIQUEMENT aux clients
     * qui présentent la clé TSIG "transfer-key"
     * 
     * Sécurité :
     * - Sans clé valide -> Transfert refusé
     * - Avec clé valide -> Transfert autorisé
     * 
     * Syntaxes possibles :
     * 
     * 1. Par IP (NON SÉCURISÉ) :
     * allow-transfer { 192.168.1.101; };
     * [X] N'importe qui avec cette IP peut transférer
     * 
     * 2. Par clé TSIG (SÉCURISÉ) :
     * allow-transfer { key transfer-key; };
     * [OK] Nécessite la clé secrète
     * 
     * 3. Combinaison IP + clé (TRÈS SÉCURISÉ) :
     * allow-transfer { 192.168.1.101 key transfer-key; };
     * [OK] IP correcte ET clé valide requises
     * 
     * 4. ACL + clé :
     * allow-transfer { trusted-slaves; key transfer-key; };
     */
    
    // Notifier les slaves lors d'un changement
    notify yes;
    
    /*
     * notify :
     * Active/désactive les notifications NOTIFY
     * 
     * yes = Envoie NOTIFY à tous les serveurs NS de la zone
     * no = Pas de notification (slaves doivent poll)
     * explicit = Notifie seulement les serveurs dans also-notify
     * 
     * Processus :
     * 1. Zone modifiée, serial incrémenté
     * 2. Master recharge la zone (rndc reload)
     * 3. Master envoie NOTIFY aux slaves
     * 4. Slaves déclenchent un transfert IXFR/AXFR
     * 
     * [ATTENTION] NOTIFY est un UDP sur le port 53
     * Vérifier que le pare-feu n'est pas bloqué
     */
    
    // Liste explicite des serveurs à notifier
    also-notify { 192.168.1.101 key transfer-key; };
    
    /*
     * also-notify :
     * Liste supplémentaire de serveurs à notifier
     * 
     * Par défaut, notify yes envoie aux serveurs NS de la zone
     * also-notify ajoute des serveurs à cette liste
     * 
     * Utile si :
     * - Le slave n'est pas dans les NS de la zone
     * - Tu veux notifier des serveurs cachés
     * 
     * Syntaxe :
     * also-notify { IP; IP; ... };
     * 
     * Avec TSIG :
     * also-notify { IP key nom-cle; };
     */
};

// ───────────────────────────────────────────────────────────────
// ZONE INVERSE : 192.168.1.0/24
// ───────────────────────────────────────────────────────────────

zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168.1";
    allow-transfer { key transfer-key; };
    notify yes;
    also-notify { 192.168.1.101 key transfer-key; };
};

/*
 * Configuration identique pour la zone inverse
 * 
 * [ATTENTION] IMPORTANT :
 * Les zones directes ET inverses doivent être répliquées
 * Sinon incohérence entre master et slave
 */

// ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

**Modifier le fichier de zone pour ajouter ns2 :**

```bash
sudo nano /etc/bind/zones/db.monentreprise.local
```

**Modifications :**

```bind
; ═══════════════════════════════════════════════════════════════
; FICHIER DE ZONE : monentreprise.local (MISE À JOUR)
; ═══════════════════════════════════════════════════════════════

$TTL    86400
@       IN      SOA     ns1.monentreprise.local. admin.monentreprise.local. (
                        2024121602      ; Serial (INCRÉMENTÉ !)
                        3600
                        1800
                        604800
                        86400 )

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS NS (AJOUTER ns2)
; ───────────────────────────────────────────────────────────────

@       IN      NS      ns1.monentreprise.local.
@       IN      NS      ns2.monentreprise.local.  ; <- NOUVEAU

/*
 * Ajout du serveur secondaire dans les NS
 * 
 * Maintenant, la zone a 2 serveurs autoritaires :
 * - ns1.monentreprise.local (master)
 * - ns2.monentreprise.local (slave)
 * 
 * Les clients DNS pourront interroger l'un ou l'autre
 * 
 * [ATTENTION] Ne pas oublier de créer l'enregistrement A pour ns2
 */

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENTS A
; ───────────────────────────────────────────────────────────────

ns1             IN      A       192.168.1.100
ns2             IN      A       192.168.1.101  ; <- NOUVEAU

/*
 * Enregistrement A pour ns2
 * 
 * [ATTENTION] OBLIGATOIRE :
 * Chaque serveur NS DOIT avoir un enregistrement A (ou AAAA)
 * Sinon, les clients ne pourront pas contacter ns2
 */

www             IN      A       192.168.1.10
mail            IN      A       192.168.1.20
files           IN      A       192.168.1.30

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT MX
; ───────────────────────────────────────────────────────────────

@               IN      MX      10 mail.monentreprise.local.

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT CNAME
; ───────────────────────────────────────────────────────────────

ftp             IN      CNAME   www.monentreprise.local.

; ───────────────────────────────────────────────────────────────
; ENREGISTREMENT TXT
; ───────────────────────────────────────────────────────────────

@               IN      TXT     "v=spf1 mx ~all"

; ═══════════════════════════════════════════════════════════════
```

**[ATTENTION] Points critiques :**

1. **Serial incrémenté** : 2024121601 -> 2024121602
2. **ns2 ajouté dans les NS**
3. **Enregistrement A pour ns2**

**Sauvegarde.**

---

**Faire de même pour la zone inverse :**

```bash
sudo nano /etc/bind/zones/db.192.168.1
```

**Modifications :**

```bind
$TTL    86400
@       IN      SOA     ns1.monentreprise.local. admin.monentreprise.local. (
                        2024121602      ; Serial INCRÉMENTÉ
                        3600
                        1800
                        604800
                        86400 )

@       IN      NS      ns1.monentreprise.local.
@       IN      NS      ns2.monentreprise.local.  ; NOUVEAU

100     IN      PTR     ns1.monentreprise.local.
101     IN      PTR     ns2.monentreprise.local.  ; NOUVEAU
10      IN      PTR     www.monentreprise.local.
20      IN      PTR     mail.monentreprise.local.
30      IN      PTR     files.monentreprise.local.
```

**Sauvegarde.**

---

**Vérifier la syntaxe :**

```bash
sudo named-checkconf
sudo named-checkzone monentreprise.local /etc/bind/zones/db.monentreprise.local
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1
```

**Résultats attendus :**

```
zone monentreprise.local/IN: loaded serial 2024121602
OK
zone 1.168.192.in-addr.arpa/IN: loaded serial 2024121602
OK
```

**[OK] Zones valides !**

---

**Recharger BIND sur le master :**

```bash
sudo rndc reload
```

**Résultat :**

```
server reload successful
```

---

### ÉTAPE 4 : Configurer le serveur SLAVE

**Sur ns2 (slave), éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Contenu (similaire au master) :**

```bind
options {
    directory "/var/cache/bind";
    
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };
    
    dnssec-validation auto;
    
    listen-on { 127.0.0.1; 192.168.1.101; };
    listen-on-v6 { ::1; };
    
    allow-query { localhost; 192.168.1.0/24; };
    allow-recursion { localhost; 192.168.1.0/24; };
    allow-query-cache { localhost; 192.168.1.0/24; };
    
    // [ATTENTION] IMPORTANT pour un SLAVE
    allow-transfer { none; };
    
    /*
     * allow-transfer { none; } :
     * 
     * Un slave ne devrait PAS autoriser les transferts de zone
     * (il n'est pas master)
     * 
     * Sauf si :
     * - Tu as une cascade : Master -> Slave1 -> Slave2
     * - Slave1 peut transférer vers Slave2
     */
    
    recursion yes;
    version "DNS Server";
    max-cache-size 256M;
    max-cache-ttl 86400;
};
```

**Sauvegarde.**

---

**Éditer `/etc/bind/named.conf.local` sur ns2 :**

```bash
sudo nano /etc/bind/named.conf.local
```

**Contenu :**

```bind
// ═══════════════════════════════════════════════════════════════
// ZONES DNS LOCALES - CONFIGURATION SLAVE
// ═══════════════════════════════════════════════════════════════

// ───────────────────────────────────────────────────────────────
// INCLUSION DE LA CLÉ TSIG
// ───────────────────────────────────────────────────────────────

include "/etc/bind/keys/transfer.key";

// ───────────────────────────────────────────────────────────────
// DÉFINITION DU SERVEUR MASTER
// ───────────────────────────────────────────────────────────────

// Serveur master
server 192.168.1.100 {
    keys { transfer-key; };
};

/*
 * server 192.168.1.100 :
 * Configuration spécifique pour le serveur master
 * 
 * keys { transfer-key; } :
 * Utilise la clé TSIG "transfer-key" pour communiquer
 * avec ce serveur
 * 
 * Toutes les communications avec 192.168.1.100 :
 * - Transferts AXFR/IXFR
 * - Notifications NOTIFY
 * - Requêtes SOA
 * Seront signées avec cette clé
 */

// ───────────────────────────────────────────────────────────────
// ZONE DIRECTE : monentreprise.local (SLAVE)
// ───────────────────────────────────────────────────────────────

zone "monentreprise.local" {
    type slave;
    file "/var/cache/bind/db.monentreprise.local";
    masters { 192.168.1.100 key transfer-key; };
};

/*
 * ═══════════════════════════════════════════════════════════════
 * CONFIGURATION SLAVE EXPLIQUÉE LIGNE PAR LIGNE
 * ═══════════════════════════════════════════════════════════════
 * 
 * type slave :
 * Ce serveur est SECONDAIRE pour cette zone
 * 
 * Conséquences :
 * - Lecture seule (pas d'édition manuelle)
 * - Récupère les données depuis le master
 * - Répond aux requêtes de manière autoritaire (flag AA)
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * file "/var/cache/bind/db.monentreprise.local" :
 * Chemin où le slave STOCKE la zone transférée
 * 
 * [ATTENTION] DIFFÉRENCE IMPORTANTE avec le master :
 * 
 * Master : file "/etc/bind/zones/db.monentreprise.local"
 * -> Fichier édité MANUELLEMENT
 * -> Emplacement : /etc/bind/zones/
 * 
 * Slave : file "/var/cache/bind/db.monentreprise.local"
 * -> Fichier généré AUTOMATIQUEMENT par BIND
 * -> Emplacement : /var/cache/bind/
 * -> [ATTENTION] NE JAMAIS éditer ce fichier manuellement !
 * 
 * Pourquoi /var/cache/bind/ ?
 * - Dossier par défaut pour les fichiers temporaires de BIND
 * - Permissions appropriées (bind:bind)
 * - Nettoyé en cas de réinstallation
 * 
 * Format du fichier :
 * Le slave stocke la zone dans un format binaire optimisé
 * Différent du format texte du master
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * masters { 192.168.1.100 key transfer-key; } :
 * Liste des serveurs masters depuis lesquels transférer la zone
 * 
 * 192.168.1.100 = IP du master
 * key transfer-key = Utiliser la clé TSIG pour l'authentification
 * 
 * [ATTENTION] "masters" au pluriel !
 * On peut avoir plusieurs masters (rare) :
 * masters { 192.168.1.100; 192.168.1.200; };
 * 
 * Le slave essaiera le premier, puis le second si échec
 * 
 * Avec TSIG :
 * masters { 192.168.1.100 key transfer-key; };
 * 
 * Toutes les communications vers ce master seront signées
 */

// ───────────────────────────────────────────────────────────────
// ZONE INVERSE : 192.168.1.0/24 (SLAVE)
// ───────────────────────────────────────────────────────────────

zone "1.168.192.in-addr.arpa" {
    type slave;
    file "/var/cache/bind/db.192.168.1";
    masters { 192.168.1.100 key transfer-key; };
};

/*
 * Configuration identique pour la zone inverse
 * 
 * Les deux zones (directe + inverse) doivent être répliquées
 */

// ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

**Vérifier la syntaxe sur le slave :**

```bash
sudo named-checkconf
```

**Aucune sortie = OK [OK]**

---

**Redémarrer BIND sur le slave :**

```bash
sudo systemctl restart bind9
```

---

**Vérifier le statut :**

```bash
sudo systemctl status bind9
```

**Résultat :**

```
[BLACK_CIRCLE] named.service - BIND Domain Name Server
     Loaded: loaded
     Active: active (running)
```

**[OK] BIND slave démarré !**

---

### ÉTAPE 5 : Vérifier le transfert de zone initial

**Sur le serveur SLAVE (ns2), consulter les logs :**

```bash
sudo journalctl -u bind9 -n 50 --no-pager
```

**Chercher des lignes comme :**

```
Dec 16 14:00:00 ns2 named[12345]: zone monentreprise.local/IN: Transfer started.
Dec 16 14:00:00 ns2 named[12345]: transfer of 'monentreprise.local/IN' from 192.168.1.100#53: connected using 192.168.1.101#45678
Dec 16 14:00:00 ns2 named[12345]: zone monentreprise.local/IN: transferred serial 2024121602
Dec 16 14:00:00 ns2 named[12345]: transfer of 'monentreprise.local/IN' from 192.168.1.100#53: Transfer status: success
Dec 16 14:00:00 ns2 named[12345]: transfer of 'monentreprise.local/IN' from 192.168.1.100#53: Transfer completed: 1 messages, 12 records, 345 bytes, 0.012 secs (28750 bytes/sec)
```

**Décodage :**

**`Transfer started`**
- Le slave commence à transférer la zone

**`connected using 192.168.1.101#45678`**
- Connexion établie depuis l'IP du slave, port source 45678

**`transferred serial 2024121602`**
- Serial transféré : 2024121602

**`Transfer status: success`**
- Transfert réussi [OK]

**`1 messages, 12 records, 345 bytes, 0.012 secs`**
- 1 message DNS
- 12 enregistrements transférés
- 345 octets
- Durée : 0.012 secondes (12 ms)

**[OK] Transfert de zone réussi !**

---

**Vérifier que les fichiers de zone ont été créés :**

```bash
ls -l /var/cache/bind/
```

**Résultat :**

```
-rw-r--r-- 1 bind bind  456 Dec 16 14:00 db.monentreprise.local
-rw-r--r-- 1 bind bind  289 Dec 16 14:00 db.192.168.1
```

**[OK] Fichiers de zone créés automatiquement !**

---

**Examiner le contenu (format binaire optimisé) :**

```bash
sudo cat /var/cache/bind/db.monentreprise.local
```

**Le contenu sera en format binaire (non lisible directement).**

**Pour voir le contenu :**

```bash
sudo named-compilezone -f raw -F text -o - monentreprise.local /var/cache/bind/db.monentreprise.local
```

**Affiche la zone en format texte.**

---

### ÉTAPE 6 : Tester les résolutions DNS sur le slave

**Depuis le serveur slave (ns2) :**

```bash
dig @localhost www.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
www.monentreprise.local. 86400  IN      A       192.168.1.10

;; AUTHORITY SECTION:
monentreprise.local.    86400   IN      NS      ns1.monentreprise.local.
monentreprise.local.    86400   IN      NS      ns2.monentreprise.local.

;; flags: qr aa rd ra
```

**Points importants :**

**`flags: ... aa ...`**
- `aa` = Authoritative Answer
- Le slave répond de manière AUTORITAIRE
- Même statut que le master

**`AUTHORITY SECTION`**
- Les deux serveurs NS sont présents

**[OK] Le slave répond correctement !**

---

**Tester depuis un client :**

**Configurer le client pour utiliser ns2 :**

```bash
# Temporairement
dig @192.168.1.101 www.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
www.monentreprise.local. 86400  IN      A       192.168.1.10
```

**[OK] Résolution via le slave fonctionne !**

---

### ÉTAPE 7 : Tester la synchronisation automatique (NOTIFY)

**Objectif : Modifier la zone sur le master et vérifier que le slave se synchronise automatiquement.**

**Sur le serveur MASTER (ns1), ajouter un nouvel enregistrement :**

```bash
sudo nano /etc/bind/zones/db.monentreprise.local
```

**Ajouter à la fin (avant la dernière ligne) :**

```bind
; Test de synchronisation
test            IN      A       192.168.1.50
```

**[ATTENTION] INCRÉMENTER LE SERIAL !**

```bind
@       IN      SOA     ns1.monentreprise.local. admin.monentreprise.local. (
                        2024121603      ; <- ÉTAIT 2024121602
                        3600
                        ...
```

**Sauvegarde.**

---

**Vérifier la syntaxe :**

```bash
sudo named-checkzone monentreprise.local /etc/bind/zones/db.monentreprise.local
```

**Résultat :**

```
zone monentreprise.local/IN: loaded serial 2024121603
OK
```

**[OK] Zone valide !**

---

**Recharger la zone sur le master :**

```bash
sudo rndc reload monentreprise.local
```

**Résultat :**

```
zone monentreprise.local/IN: loaded serial 2024121603
```

**[OK] Zone rechargée avec le nouveau serial !**

---

**Surveiller les logs du master :**

```bash
sudo journalctl -u bind9 -f
```

**Tu devrais voir :**

```
Dec 16 14:30:00 ns1 named[12345]: zone monentreprise.local/IN: sending notifies (serial 2024121603)
Dec 16 14:30:00 ns1 named[12345]: client @0x7f... 192.168.1.101#12345 (monentreprise.local): transfer of 'monentreprise.local/IN': IXFR started (serial 2024121602 -> 2024121603)
Dec 16 14:30:00 ns1 named[12345]: client @0x7f... 192.168.1.101#12345 (monentreprise.local): transfer of 'monentreprise.local/IN': IXFR ended
```

**Décodage :**

**`sending notifies (serial 2024121603)`**
- Le master envoie une notification NOTIFY au slave

**`IXFR started (serial 2024121602 -> 2024121603)`**
- Transfert INCRÉMENTAL (IXFR)
- De la version 2024121602 vers 2024121603

**`IXFR ended`**
- Transfert terminé

**[OK] Notification + transfert automatique !**

---

**Sur le serveur SLAVE (ns2), vérifier les logs :**

```bash
sudo journalctl -u bind9 -n 20 --no-pager
```

**Tu devrais voir :**

```
Dec 16 14:30:00 ns2 named[12345]: client @0x7f... 192.168.1.100#53: received notify for zone 'monentreprise.local'
Dec 16 14:30:00 ns2 named[12345]: zone monentreprise.local/IN: Transfer started.
Dec 16 14:30:00 ns2 named[12345]: transfer of 'monentreprise.local/IN' from 192.168.1.100#53: connected
Dec 16 14:30:00 ns2 named[12345]: zone monentreprise.local/IN: transferred serial 2024121603: IXFR
Dec 16 14:30:00 ns2 named[12345]: transfer of 'monentreprise.local/IN' from 192.168.1.100#53: Transfer completed: 1 messages, 3 records, 89 bytes, 0.005 secs
```

**Décodage :**

**`received notify`**
- Le slave a reçu la notification NOTIFY

**`Transfer started`**
- Démarrage du transfert

**`transferred serial 2024121603: IXFR`**
- Serial 2024121603 transféré via IXFR

**`3 records`**
- Seulement 3 enregistrements transférés (incrémental)
- vs 12 enregistrements lors du transfert complet initial (AXFR)

**[OK] Synchronisation automatique en quelques secondes !**

---

**Tester la résolution du nouvel enregistrement sur le slave :**

```bash
dig @192.168.1.101 test.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
test.monentreprise.local. 86400 IN      A       192.168.1.50
```

**[BRAVO] Le slave a bien le nouvel enregistrement ! [BRAVO]**

---

### ÉTAPE 8 : Tester le failover (haute disponibilité)

**Scénario : Le serveur master tombe en panne.**

**Configurer les clients pour utiliser les DEUX serveurs DNS :**

**Sur un client Linux :**

```bash
sudo nano /etc/resolv.conf
```

**Contenu :**

```
nameserver 192.168.1.100  # ns1 (master)
nameserver 192.168.1.101  # ns2 (slave)
```

**Ou avec NetworkManager :**

```bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns "192.168.1.100 192.168.1.101"
sudo nmcli connection down "Wired connection 1"
sudo nmcli connection up "Wired connection 1"
```

---

**Tester la résolution (master actif) :**

```bash
dig www.monentreprise.local
```

**Résultat :**

```
;; SERVER: 192.168.1.100#53(192.168.1.100)
```

**Le client interroge le premier serveur (master).**

---

**Simuler une panne du master :**

```bash
# Sur ns1 (master)
sudo systemctl stop bind9
```

**[ATTENTION] Le master est maintenant DOWN !**

---

**Tester la résolution (avec master down) :**

```bash
# Sur le client
dig www.monentreprise.local
```

**Résultat :**

```
;; SERVER: 192.168.1.101#53(192.168.1.101)

;; ANSWER SECTION:
www.monentreprise.local. 86400  IN      A       192.168.1.10
```

**Explications :**

1. Le client essaye d'abord ns1 (192.168.1.100)
2. Timeout (pas de réponse)
3. Le client bascule automatiquement sur ns2 (192.168.1.101)
4. ns2 répond correctement

**[OK] Failover automatique fonctionnel ! [BRAVO]**

---

**Délai de basculement :**

```bash
time dig www.monentreprise.local
```

**Résultat :**

```
real    0m5.023s
```

**Environ 5 secondes (timeout sur le premier serveur).**

---

**Redémarrer le master :**

```bash
# Sur ns1
sudo systemctl start bind9
```

**Les requêtes suivantes utiliseront à nouveau le master (premier dans la liste).**

---

### ÉTAPE 9 : Forcer un transfert de zone manuel

**Parfois utile pour :**
- Résoudre une désynchronisation
- Tester les transferts
- Forcer une mise à jour immédiate

**Sur le serveur SLAVE (ns2) :**

```bash
# Méthode 1 : Recharger la zone
sudo rndc reload monentreprise.local
```

**Résultat :**

```
zone monentreprise.local/IN: loaded serial 2024121603
```

---

**Méthode 2 : Forcer un refresh**

```bash
sudo rndc refresh monentreprise.local
```

**Le slave interroge immédiatement le master pour le serial.**

---

**Méthode 3 : Forcer un transfert complet (AXFR)**

```bash
sudo rndc retransfer monentreprise.local
```

**Force un transfert AXFR même si le serial est identique.**

**Utile si :**
- Corruption des données
- Fichier de zone slave supprimé
- Désynchronisation inexpliquée

---

### [OK] TESTS DE VALIDATION

**1. Transfert de zone initial**

- [ ] Slave a transféré la zone au démarrage
- [ ] Fichiers créés dans `/var/cache/bind/`
- [ ] Logs indiquent "Transfer completed"

---

**2. Résolutions DNS sur le slave**

- [ ] `dig @192.168.1.101 www.monentreprise.local` -> 192.168.1.10
- [ ] `dig @192.168.1.101 ns2.monentreprise.local` -> 192.168.1.101
- [ ] Flag `aa` (Authoritative Answer) présent

---

**3. NOTIFY et synchronisation automatique**

- [ ] Modifier une zone sur le master, incrémenter le serial
- [ ] Recharger : `rndc reload`
- [ ] Vérifier les logs du master : "sending notifies"
- [ ] Vérifier les logs du slave : "received notify"
- [ ] Délai de synchronisation < 10 secondes
- [ ] `dig @192.168.1.101` retourne le nouvel enregistrement

---

**4. Transfert incrémental (IXFR)**

- [ ] Logs du slave indiquent "IXFR" (pas AXFR)
- [ ] Nombre de records transférés < Total (incrémental)

---

**5. Failover**

- [ ] Client configuré avec les deux DNS
- [ ] Stopper le master : `systemctl stop bind9`
- [ ] `dig` fonctionne toujours (bascule sur slave)
- [ ] Redémarrer le master
- [ ] `dig` utilise à nouveau le master

---

**6. Sécurité TSIG**

**Tester un transfert SANS la clé (doit échouer) :**

```bash
dig @192.168.1.100 monentreprise.local AXFR
```

**Résultat attendu :**

```
; Transfer failed.
```

**Avec la clé (sur le slave, devrait fonctionner via la config).**

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "transfer of zone ... refused"

**Symptôme :**

```
transfer of 'monentreprise.local/IN' from 192.168.1.100#53: failed while receiving responses: REFUSED
```

**Cause : Le master refuse le transfert**

**Solutions :**

**1. Vérifier allow-transfer sur le master :**

```bash
sudo grep -A 5 "zone \"monentreprise.local\"" /etc/bind/named.conf.local
```

**Doit contenir :**

```bind
allow-transfer { key transfer-key; };
```

---

**2. Vérifier que la clé est identique sur master et slave :**

```bash
# Sur ns1
sudo cat /etc/bind/keys/transfer.key

# Sur ns2
sudo cat /etc/bind/keys/transfer.key
```

**Le champ `secret` doit être IDENTIQUE.**

---

**3. Vérifier que la clé est bien incluse :**

```bash
sudo grep -r "include.*transfer.key" /etc/bind/
```

**Doit retourner :**

```
/etc/bind/named.conf.local:include "/etc/bind/keys/transfer.key";
```

---

#### Erreur 2 : "no valid RRSIG" ou "TSIG verification failed"

**Symptôme :**

```
zone monentreprise.local/IN: Transfer failed: TSIG verification failure
```

**Cause : Problème avec TSIG**

**Solutions :**

**1. Horloge désynchronisée**

TSIG inclut un timestamp. Si les horloges diffèrent de > 5 minutes :

```bash
# Vérifier l'heure sur master et slave
date

# Synchroniser avec NTP
sudo apt install ntp -y
sudo systemctl start ntp
```

---

**2. Algorithme différent**

```bash
# Vérifier l'algorithme dans la clé
sudo grep algorithm /etc/bind/keys/transfer.key
```

**Doit être IDENTIQUE sur master et slave.**

---

#### Erreur 3 : Le slave ne reçoit pas les NOTIFY

**Symptôme :**

Le slave ne se synchronise pas automatiquement après modification.

**Diagnostic :**

**1. Vérifier que notify est activé sur le master :**

```bind
zone "monentreprise.local" {
    notify yes;  # <- Doit être présent
    ...
};
```

---

**2. Vérifier que le pare-feu n'est pas bloqué :**

```bash
# Sur le slave
sudo ufw status
```

**Port 53 UDP doit être ouvert (NOTIFY utilise UDP).**

```bash
sudo ufw allow 53/udp
```

---

**3. Vérifier que also-notify est correct :**

```bind
also-notify { 192.168.1.101 key transfer-key; };
```

**L'IP doit être celle du SLAVE.**

---

**4. Capturer le trafic réseau :**

```bash
# Sur le slave
sudo tcpdump -i any port 53 -n
```

**Modifier la zone sur le master, recharger.**

**Tu devrais voir des paquets UDP de 192.168.1.100 -> 192.168.1.101.**

---

#### Erreur 4 : "zone serial unchanged"

**Symptôme :**

```bash
rndc reload monentreprise.local
```

```
zone monentreprise.local/IN: zone serial (2024121602) unchanged. zone may fail to transfer to slaves.
```

**Cause : Tu as oublié d'incrémenter le serial**

**Solution :**

```bash
sudo nano /etc/bind/zones/db.monentreprise.local
```

**Incrémenter le serial :**

```
2024121602 -> 2024121603
```

**[ATTENTION] TOUJOURS incrémenter le serial après modification !**

---

#### Erreur 5 : Le slave répond mais avec des données obsolètes

**Symptôme :**

Le master a serial 2024121603, mais le slave répond avec serial 2024121601.

**Diagnostic :**

**1. Vérifier le serial sur le slave :**

```bash
dig @192.168.1.101 monentreprise.local SOA
```

**Compare avec le master :**

```bash
dig @192.168.1.100 monentreprise.local SOA
```

---

**2. Forcer un refresh sur le slave :**

```bash
sudo rndc refresh monentreprise.local
```

---

**3. Si ça ne fonctionne pas, forcer un retransfert :**

```bash
sudo rndc retransfer monentreprise.local
```

---

**4. En dernier recours, supprimer le fichier et redémarrer :**

```bash
sudo rm /var/cache/bind/db.monentreprise.local
sudo systemctl restart bind9
```

**Le slave retransférera automatiquement la zone.**

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. Master vs Slave**
- Master = Source de vérité, éditable manuellement
- Slave = Copie en lecture seule, générée automatiquement

**2. Serial**
- DOIT augmenter à chaque modification
- Le slave compare son serial avec le master
- Si master > slave -> Transfert

**3. Transferts de zone**
- AXFR = Transfert complet (initial ou après corruption)
- IXFR = Transfert incrémental (seulement les changements)

**4. NOTIFY**
- Notification push du master vers le slave
- Synchronisation quasi-instantanée (< 1 minute)
- Meilleur que le polling périodique (REFRESH)

**5. TSIG**
- Authentification cryptographique
- Protège les transferts de zone
- Basé sur des clés partagées (secret)

**6. Fichiers de zone**
- Master : `/etc/bind/zones/` (éditable)
- Slave : `/var/cache/bind/` (généré, ne pas toucher)

**7. Failover**
- Les clients doivent avoir les deux DNS configurés
- Basculement automatique en cas de panne
- Délai = timeout du premier serveur (5s par défaut)

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Ajouter un 3ème serveur DNS (slave)**

**Cascade : Master -> Slave1 -> Slave2**

```bind
# Sur Slave1, autoriser les transferts vers Slave2
allow-transfer { 192.168.1.102 key transfer-key; };
```

---

**2. Monitoring avec Prometheus + Grafana**

**Exporter BIND :**

```bash
sudo apt install prometheus-bind-exporter -y
```

**Métriques disponibles :**
- Nombre de requêtes
- Taux de transferts de zone
- État de synchronisation
- Cache hit/miss ratio

---

**3. Automatiser les alertes**

**Script de vérification de synchronisation :**

```bash
#!/bin/bash

MASTER_SERIAL=$(dig @192.168.1.100 monentreprise.local SOA +short | awk '{print $3}')
SLAVE_SERIAL=$(dig @192.168.1.101 monentreprise.local SOA +short | awk '{print $3}')

if [ "$MASTER_SERIAL" != "$SLAVE_SERIAL" ]; then
    echo "ALERTE : Slave désynchronisé ! Master=$MASTER_SERIAL, Slave=$SLAVE_SERIAL" | \
      mail -s "DNS Sync Alert" admin@example.com
fi
```

**Cron toutes les 5 minutes :**

```bash
*/5 * * * * /usr/local/bin/check-dns-sync.sh
```

---

**4. Transferts de zone chiffrés avec TLS**

BIND 9.18+ supporte DNS-over-TLS pour les transferts.

```bind
tls transfer-key {
    cert-file "/etc/bind/certs/server.crt";
    key-file "/etc/bind/certs/server.key";
    ca-file "/etc/bind/certs/ca.crt";
};

zone "monentreprise.local" {
    type master;
    allow-transfer { tls transfer-key; };
    ...
};
```

---

**5. Hidden master**

Le master n'est PAS dans les enregistrements NS publics.

**Avantages :**
- Protège le master des attaques DDoS
- Seuls les slaves répondent aux clients

**Configuration :**

```bind
# Sur le master
allow-query { localhost; trusted-slaves; };  # Pas "any"

# Retirer le master des NS publics
@  IN  NS  ns2.monentreprise.local.
@  IN  NS  ns3.monentreprise.local.
# ns1 n'est PAS listé
```

---

**6. Catalogue zones (BIND 9.11+)**

Synchronisation automatique de NOUVELLES zones.

**Problème :**
Quand tu ajoutes une zone sur le master, tu dois la déclarer MANUELLEMENT sur chaque slave.

**Solution : Catalogue zones**

Le master maintient une "zone catalogue" qui liste toutes les zones.
Les slaves s'y abonnent et ajoutent automatiquement les nouvelles zones.

---

## [COURS] CONCLUSION DE L'EXERCICE 2

**[OK] Félicitations ! Tu as mis en place une infrastructure DNS redondante ! [BRAVO]**

**Ce que tu as appris :**
- Configurer un serveur DNS secondaire (slave)
- Mettre en place les transferts de zone AXFR/IXFR
- Activer les notifications NOTIFY
- Sécuriser les transferts avec TSIG
- Tester le failover automatique
- Diagnostiquer les problèmes de synchronisation
- Gérer les serials et la réplication

**Compétences acquises :**
- [OK] DNS master/slave (niveau intermédiaire)
- [OK] Transferts de zone sécurisés
- [OK] Haute disponibilité DNS
- [OK] Troubleshooting de réplication
- [OK] Sécurité TSIG

**Temps moyen de réalisation :** 2-3 heures

**Prochaine étape :** Exercice 3 - DNS dynamique (DDNS) avec DHCP ! [SYNC]

---

Veux-tu que je continue avec les exercices 3, 4 et 5 ?

# [JAUNE] EXERCICE 3 : DNS DYNAMIQUE (DDNS) AVEC DHCP

## [LISTE] ÉNONCÉ

### Contexte professionnel

Le parc informatique de ton entreprise s'agrandit. Actuellement, tu dois :
- Ajouter manuellement chaque nouvelle machine dans le DNS
- Mettre à jour les enregistrements quand une machine change d'IP
- Gérer les incohérences entre DHCP et DNS

Le directeur IT te demande d'**automatiser** ce processus : quand une machine reçoit une IP via DHCP, son nom doit être automatiquement enregistré dans le DNS.

### Cahier des charges

Mettre en place un système de DNS dynamique (DDNS) qui :
- S'intègre avec le serveur DHCP (ISC DHCP)
- Met à jour automatiquement les enregistrements A et PTR
- Sécurise les mises à jour avec TSIG
- Gère le nettoyage des enregistrements obsolètes
- Supporte à la fois Windows et Linux

### Objectifs techniques

- Installer et configurer un serveur DHCP (ISC DHCP Server)
- Configurer BIND pour accepter les mises à jour dynamiques
- Créer une clé TSIG pour sécuriser les updates
- Intégrer DHCP et DNS avec DDNS
- Tester les mises à jour automatiques A et PTR
- Gérer le lease time et le garbage collection

### Contraintes

- Serveur DHCP : ISC DHCP Server 4.4+
- Plage DHCP : 192.168.1.200 - 192.168.1.250
- Mises à jour DNS en temps réel
- Sécurité : Authentification TSIG obligatoire
- Temps estimé : 2-3 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre le fonctionnement de DDNS (Dynamic DNS)
- [OK] Installer et configurer ISC DHCP Server
- [OK] Configurer BIND pour les mises à jour dynamiques
- [OK] Sécuriser DDNS avec TSIG
- [OK] Intégrer DHCP et DNS
- [OK] Gérer les updates (nsupdate)
- [OK] Diagnostiquer les problèmes DDNS
- [OK] Gérer le cycle de vie des enregistrements

---

## [DOCS] PRÉREQUIS

- Exercices 1 et 2 terminés
- Serveur BIND9 fonctionnel
- Compréhension de DHCP
- Réseau de test disponible

---

## [GUIDE] RAPPEL THÉORIQUE : DDNS ET DHCP

### Qu'est-ce que le DDNS ?

**DDNS** = Dynamic Domain Name System

**Problème avec DNS statique :**

```
1. Nouvelle machine "laptop-alice" arrive sur le réseau
2. DHCP lui attribue l'IP 192.168.1.205
3. Alice veut accéder à sa machine : ssh laptop-alice.monentreprise.local
4. [X] Échec : Le DNS ne connaît pas "laptop-alice"
5. L'admin doit MANUELLEMENT ajouter :
   - laptop-alice  IN  A  192.168.1.205
   - 205  IN  PTR  laptop-alice.monentreprise.local.
6. 3 jours plus tard, le bail DHCP expire
7. DHCP attribue une NOUVELLE IP : 192.168.1.212
8. [X] Le DNS a toujours 192.168.1.205 (obsolète)
9. L'admin doit MANUELLEMENT mettre à jour
```

**Cauchemar administratif avec 100+ machines !**

---

**Solution : DDNS**

```
1. Nouvelle machine "laptop-alice" arrive
2. DHCP lui attribue 192.168.1.205
3. DHCP envoie automatiquement au DNS :
   - "Ajoute : laptop-alice -> 192.168.1.205"
   - "Ajoute : 192.168.1.205 -> laptop-alice (PTR)"
4. DNS met à jour sa zone
5. Alice peut immédiatement faire : ssh laptop-alice.monentreprise.local
6. [OK] Fonctionne !
7. Le bail expire, nouvelle IP : 192.168.1.212
8. DHCP met à jour automatiquement le DNS
9. [OK] Toujours fonctionnel, sans intervention manuelle !
```

---

### Fonctionnement de DDNS

**Protocole : RFC 2136 (Dynamic Updates in the Domain Name System)**

**Flux complet :**

```
┌──────────┐                  ┌──────────┐                  ┌──────────┐
│  Client  │                  │   DHCP   │                  │   DNS    │
└──────────┘                  └──────────┘                  └──────────┘
     │                              │                              │
     │ 1. DHCPDISCOVER              │                              │
     │─────────────────────────────>│                              │
     │                              │                              │
     │ 2. DHCPOFFER (IP: .205)      │                              │
     │<─────────────────────────────│                              │
     │                              │                              │
     │ 3. DHCPREQUEST (hostname)    │                              │
     │─────────────────────────────>│                              │
     │                              │                              │
     │                              │ 4. DNS UPDATE (A record)     │
     │                              │─────────────────────────────>│
     │                              │                              │
     │                              │ 5. ACK/NACK                  │
     │                              │<─────────────────────────────│
     │                              │                              │
     │                              │ 6. DNS UPDATE (PTR record)   │
     │                              │─────────────────────────────>│
     │                              │                              │
     │                              │ 7. ACK/NACK                  │
     │                              │<─────────────────────────────│
     │                              │                              │
     │ 8. DHCPACK (lease confirmé)  │                              │
     │<─────────────────────────────│                              │
     │                              │                              │
```

**Étapes détaillées :**

1. **Client envoie DHCPDISCOVER** : "Je cherche une IP"
2. **DHCP répond DHCPOFFER** : "Je peux te donner 192.168.1.205"
3. **Client envoie DHCPREQUEST** : "OK, je prends cette IP. Mon hostname est laptop-alice"
4. **DHCP envoie DNS UPDATE au serveur DNS** :
   ```
   UPDATE monentreprise.local.
   ADD laptop-alice.monentreprise.local. 3600 A 192.168.1.205
   ```
5. **DNS répond ACK** : "Enregistrement ajouté"
6. **DHCP envoie DNS UPDATE pour le PTR** :
   ```
   UPDATE 1.168.192.in-addr.arpa.
   ADD 205.1.168.192.in-addr.arpa. 3600 PTR laptop-alice.monentreprise.local.
   ```
7. **DNS répond ACK** : "PTR ajouté"
8. **DHCP envoie DHCPACK au client** : "Bail confirmé, tu peux utiliser cette IP"

---

### Sécurité : Pourquoi TSIG est crucial ?

**Problème sans TSIG :**

```
Attaquant malveillant :
1. Envoie un DNS UPDATE : "www.monentreprise.local -> 6.6.6.6" (IP de l'attaquant)
2. DNS accepte l'update (pas d'authentification)
3. Les clients accédant à www sont redirigés vers le serveur de l'attaquant
4. Phishing, vol de données, etc.
```

**Solution : TSIG (Transaction SIGnature)**

```
DHCP et DNS partagent une clé secrète
Chaque DNS UPDATE est signé avec cette clé
DNS vérifie la signature avant d'accepter l'update
Sans la clé -> Rejet
```

---

### Gestion du cycle de vie des enregistrements

**Problème : Enregistrements obsolètes**

```
Scénario :
1. laptop-alice reçoit 192.168.1.205 (lundi)
2. DNS : laptop-alice -> .205
3. Alice éteint son laptop (mardi)
4. Le bail expire (mercredi)
5. DHCP attribue .205 à laptop-bob (jeudi)
6. [X] DNS a toujours : laptop-alice -> .205
   Mais la vraie machine est laptop-bob !
7. Incohérence et confusion
```

**Solution 1 : DHCP supprime les vieux enregistrements**

```
Quand un bail expire :
1. DHCP envoie DNS UPDATE DELETE
2. Supprime laptop-alice -> .205
3. L'enregistrement disparaît du DNS
```

**Solution 2 : TTL court**

```
Les enregistrements DDNS ont un TTL court (ex: 1 heure)
Après expiration du TTL, le cache est vidé
Réduit l'impact des enregistrements obsolètes
```

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Créer une clé TSIG pour DDNS

**Sur le serveur DNS (ns1) :**

```bash
# Créer le dossier pour les clés si nécessaire
sudo mkdir -p /etc/bind/keys

# Générer une clé TSIG dédiée au DDNS
sudo tsig-keygen -a hmac-sha256 ddns-key > /etc/bind/keys/ddns.key
```

**Explication :**

**`ddns-key`**
- Nom de la clé (arbitraire)
- Convention : Nom descriptif de l'usage

**`> /etc/bind/keys/ddns.key`**
- Fichier de sortie

---

**Examiner la clé :**

```bash
sudo cat /etc/bind/keys/ddns.key
```

**Résultat :**

```bind
key "ddns-key" {
    algorithm hmac-sha256;
    secret "K3yS3cr3tH3r3Base64Encoded==";
};
```

**[ATTENTION] Cette clé sera partagée entre BIND et DHCP**

---

**Sécuriser les permissions :**

```bash
sudo chown bind:bind /etc/bind/keys/ddns.key
sudo chmod 640 /etc/bind/keys/ddns.key
```

**Permissions 640 :**
- bind (propriétaire) : rw-
- bind (groupe) : r--
- Autres : ---

---

### ÉTAPE 2 : Configurer BIND pour les mises à jour dynamiques

**Éditer `/etc/bind/named.conf.local` :**

```bash
sudo nano /etc/bind/named.conf.local
```

**Ajouter l'inclusion de la clé DDNS (en haut du fichier) :**

```bind
// ═══════════════════════════════════════════════════════════════
// ZONES DNS LOCALES - AVEC DDNS
// ═══════════════════════════════════════════════════════════════

// ───────────────────────────────────────────────────────────────
// INCLUSION DES CLÉS TSIG
// ───────────────────────────────────────────────────────────────

include "/etc/bind/keys/transfer.key";  // Clé pour les transferts de zone
include "/etc/bind/keys/ddns.key";      // Clé pour les mises à jour dynamiques

/*
 * On a maintenant DEUX clés :
 * 
 * transfer-key :
 * - Utilisée pour les transferts de zone (master -> slave)
 * - Partagée entre ns1 et ns2
 * 
 * ddns-key :
 * - Utilisée pour les mises à jour dynamiques (DHCP -> DNS)
 * - Partagée entre ns1 et le serveur DHCP
 * 
 * Pourquoi deux clés séparées ?
 * - Principe du moindre privilège
 * - DHCP ne devrait PAS pouvoir transférer toute la zone
 * - Slave ne devrait PAS pouvoir faire des updates arbitraires
 * - Si une clé est compromise, l'autre reste sécurisée
 */
```

---

**Modifier la zone directe pour accepter les updates :**

```bind
// ───────────────────────────────────────────────────────────────
// ZONE DIRECTE : monentreprise.local (AVEC DDNS)
// ───────────────────────────────────────────────────────────────

zone "monentreprise.local" {
    type master;
    file "/var/lib/bind/db.monentreprise.local";
    
    /*
     * [ATTENTION] CHANGEMENT IMPORTANT :
     * Le fichier de zone est déplacé de :
     * /etc/bind/zones/ -> /var/lib/bind/
     * 
     * Pourquoi ?
     * 
     * Quand BIND fait des mises à jour dynamiques :
     * 1. Il MODIFIE le fichier de zone
     * 2. Il crée des fichiers journaux (.jnl)
     * 
     * /etc/bind/ est pour les fichiers de CONFIGURATION
     * (lecture seule en production)
     * 
     * /var/lib/bind/ est pour les DONNÉES modifiables
     * (lecture/écriture pour BIND)
     * 
     * Structure recommandée :
     * /etc/bind/zones/ = Zones STATIQUES (pas de DDNS)
     * /var/lib/bind/ = Zones DYNAMIQUES (avec DDNS)
     */
    
    allow-transfer { key transfer-key; };
    
    /*
     * Les transferts de zone utilisent toujours transfer-key
     * (pas ddns-key)
     * 
     * Séparation des responsabilités
     */
    
    notify yes;
    also-notify { 192.168.1.101 key transfer-key; };
    
    // ───────────────────────────────────────────────────────────
    // CONFIGURATION DES MISES À JOUR DYNAMIQUES
    // ───────────────────────────────────────────────────────────
    
    allow-update { key ddns-key; };
    
    /*
     * allow-update :
     * Autorise les mises à jour dynamiques (DNS UPDATE)
     * 
     * key ddns-key :
     * Seulement les clients présentant la clé ddns-key
     * peuvent faire des updates
     * 
     * Syntaxes possibles :
     * 
     * 1. Par clé TSIG (RECOMMANDÉ) :
     * allow-update { key ddns-key; };
     * [OK] Sécurisé, nécessite la clé secrète
     * 
     * 2. Par IP (NON RECOMMANDÉ) :
     * allow-update { 192.168.1.50; };
     * [X] N'importe qui avec cette IP peut mettre à jour
     * 
     * 3. Personne (DÉFAUT) :
     * allow-update { none; };
     * [X] Aucune mise à jour dynamique possible
     * 
     * 4. Combinaison IP + clé (TRÈS SÉCURISÉ) :
     * allow-update { 192.168.1.50 key ddns-key; };
     * [OK] IP correcte ET clé valide requises
     */
    
    update-policy {
        grant ddns-key zonesub any;
    };
    
    /*
     * update-policy :
     * Politique de mise à jour plus fine que allow-update
     * 
     * Format :
     * grant <key-name> <match-type> <name> <types>
     * 
     * grant ddns-key :
     * La clé ddns-key est autorisée
     * 
     * zonesub :
     * Match type = Zone ou sous-domaines
     * Peut mettre à jour N'IMPORTE QUEL nom dans la zone
     * 
     * any :
     * Types d'enregistrements = Tous (A, AAAA, PTR, etc.)
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * Autres match-types possibles :
     * 
     * - name <fqdn> :
     *   grant ddns-key name laptop-alice.monentreprise.local. A;
     *   -> Peut mettre à jour SEULEMENT laptop-alice (type A)
     * 
     * - subdomain <zone> :
     *   grant ddns-key subdomain dhcp.monentreprise.local. any;
     *   -> Peut mettre à jour seulement *.dhcp.monentreprise.local
     * 
     * - wildcard <pattern> :
     *   grant ddns-key wildcard *.laptop.monentreprise.local. any;
     *   -> Pattern avec wildcard
     * 
     * - self :
     *   grant ddns-key self any;
     *   -> Peut mettre à jour seulement son propre nom (Kerberos)
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * Types d'enregistrements possibles :
     * 
     * - any : Tous les types
     * - A : Seulement IPv4
     * - AAAA : Seulement IPv6
     * - PTR : Seulement inverse
     * - TXT : Seulement texte
     * - etc.
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * allow-update vs update-policy :
     * 
     * [ATTENTION] Si update-policy est défini, allow-update est IGNORÉ
     * 
     * Recommandation :
     * - Utiliser update-policy pour un contrôle fin
     * - Utiliser allow-update pour une configuration simple
     * 
     * Exemple combiné (ce qu'on fait ici) :
     * allow-update { key ddns-key; };      # Compatibilité
     * update-policy { grant ddns-key zonesub any; };  # Contrôle fin
     */
};
```

---

**Modifier la zone inverse :**

```bind
// ───────────────────────────────────────────────────────────────
// ZONE INVERSE : 192.168.1.0/24 (AVEC DDNS)
// ───────────────────────────────────────────────────────────────

zone "1.168.192.in-addr.arpa" {
    type master;
    file "/var/lib/bind/db.192.168.1";
    
    allow-transfer { key transfer-key; };
    notify yes;
    also-notify { 192.168.1.101 key transfer-key; };
    
    allow-update { key ddns-key; };
    update-policy {
        grant ddns-key zonesub any;
    };
    
    /*
     * Configuration identique à la zone directe
     * 
     * [ATTENTION] IMPORTANT :
     * DHCP doit pouvoir mettre à jour AUSSI la zone inverse
     * Pour ajouter les enregistrements PTR
     * 
     * Sans ça :
     * - Résolution directe OK : laptop-alice -> .205
     * - Résolution inverse KO : .205 -> ???
     */
};
```

**Sauvegarde.**

---

### ÉTAPE 3 : Déplacer les fichiers de zone vers /var/lib/bind/

**Créer le dossier si nécessaire :**

```bash
sudo mkdir -p /var/lib/bind
```

---

**Copier les fichiers de zone :**

```bash
sudo cp /etc/bind/zones/db.monentreprise.local /var/lib/bind/
sudo cp /etc/bind/zones/db.192.168.1 /var/lib/bind/
```

**[ATTENTION] On COPIE (pas déplacer) pour garder une sauvegarde**

---

**Modifier les permissions :**

```bash
sudo chown bind:bind /var/lib/bind/db.*
sudo chmod 644 /var/lib/bind/db.*
```

---

**Donner les permissions d'écriture au dossier :**

```bash
sudo chmod 775 /var/lib/bind/
```

**Permissions 775 :**
- bind (propriétaire) : rwx
- bind (groupe) : rwx
- Autres : r-x

**BIND peut créer des fichiers dans ce dossier (ex: .jnl)**

---

**Vérifier la syntaxe :**

```bash
sudo named-checkconf
sudo named-checkzone monentreprise.local /var/lib/bind/db.monentreprise.local
sudo named-checkzone 1.168.192.in-addr.arpa /var/lib/bind/db.192.168.1
```

**Résultats attendus : OK**

---

**Recharger BIND :**

```bash
sudo rndc reload
```

**Vérifier qu'il n'y a pas d'erreur :**

```bash
sudo systemctl status bind9
```

**[OK] BIND prêt pour DDNS !**

---

### ÉTAPE 4 : Installer et configurer ISC DHCP Server

**Installer le serveur DHCP :**

```bash
sudo apt update
sudo apt install isc-dhcp-server -y
```

**[ATTENTION] Le service va échouer au démarrage (normal, pas encore configuré)**

---

**Configurer l'interface réseau pour DHCP :**

```bash
sudo nano /etc/default/isc-dhcp-server
```

**Modifier la ligne `INTERFACESv4` :**

```bash
# Interface(s) sur lesquelles DHCP écoute
INTERFACESv4="ens33"

# Adapter selon ton interface réseau
# Pour connaître ton interface :
# ip addr show
```

**Explication :**

**`INTERFACESv4`**
- Liste des interfaces réseau pour DHCPv4
- Séparées par des espaces si plusieurs

**`ens33`**
- Nom de l'interface réseau
- Peut être : `eth0`, `ens33`, `enp0s3`, etc.
- Vérifier avec `ip addr show`

**Sauvegarde.**

---

**Configurer DHCP :**

```bash
sudo nano /etc/dhcp/dhcpd.conf
```

**Remplacer TOUT le contenu par :**

```dhcp
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION ISC DHCP SERVER - AVEC DDNS
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# PARAMÈTRES GLOBAUX
# ───────────────────────────────────────────────────────────────

# Serveur DHCP autoritaire
authoritative;

/*
 * authoritative :
 * Ce serveur est AUTORITAIRE pour ce réseau
 * 
 * Conséquence :
 * Si un client a une IP invalide, DHCP envoie DHCPNAK
 * (force le client à renouveler)
 * 
 * Sans authoritative :
 * DHCP ignore les requêtes invalides (client non reconfiguré)
 * 
 * [ATTENTION] À utiliser SEULEMENT si c'est le SEUL serveur DHCP du réseau
 */

# Durée des baux DHCP
default-lease-time 86400;      # 24 heures (en secondes)
max-lease-time 172800;         # 48 heures

/*
 * default-lease-time :
 * Durée par défaut d'un bail (lease) DHCP
 * 86400 secondes = 24 heures = 1 jour
 * 
 * Signification :
 * - Un client reçoit une IP pour 24 heures
 * - Après 12 heures (50%), il tente de renouveler (DHCPREQUEST)
 * - Après 21 heures (87.5%), il tente de renouveler à nouveau
 * - Après 24 heures, le bail expire
 * - Si le client est toujours en ligne, il renouvelle automatiquement
 * 
 * max-lease-time :
 * Durée MAXIMALE qu'un client peut demander
 * 172800 secondes = 48 heures = 2 jours
 * 
 * Même si le client demande plus, DHCP limite à max-lease-time
 * 
 * Recommandations :
 * - Réseau stable (peu de changements) : 7 jours (604800)
 * - Réseau dynamique (WiFi public) : 1 heure (3600)
 * - Réseau entreprise : 1-2 jours (86400-172800)
 */

# Options DNS
option domain-name "monentreprise.local";
option domain-name-servers 192.168.1.100, 192.168.1.101;

/*
 * option domain-name :
 * Domaine DNS par défaut envoyé aux clients
 * 
 * Utilité :
 * Si un client cherche "laptop-alice", il essaiera :
 * laptop-alice.monentreprise.local
 * 
 * option domain-name-servers :
 * Liste des serveurs DNS à utiliser
 * 
 * 192.168.1.100 = ns1 (master)
 * 192.168.1.101 = ns2 (slave)
 * 
 * [ATTENTION] Ordre d'importance :
 * Le client essaiera d'abord ns1, puis ns2 si échec
 */

# ───────────────────────────────────────────────────────────────
# CONFIGURATION DDNS
# ───────────────────────────────────────────────────────────────

# Activer les mises à jour DNS
ddns-updates on;
ddns-update-style interim;

/*
 * ddns-updates on :
 * Active les mises à jour DNS dynamiques
 * 
 * ddns-update-style :
 * Style de mise à jour DDNS
 * 
 * Valeurs possibles :
 * - interim : Style standard (recommandé)
 * - ad-hoc : Ancien style (déprécié)
 * - none : Désactiver DDNS
 * 
 * interim est le style moderne et sécurisé
 */

# Ne pas mettre à jour les enregistrements A si le client envoie son propre FQDN
ignore client-updates;

/*
 * ignore client-updates :
 * Ignore les tentatives du CLIENT de mettre à jour le DNS
 * 
 * Par défaut, certains clients (Windows) essaient de mettre à jour
 * eux-mêmes le DNS après avoir reçu une IP
 * 
 * Avec ignore client-updates :
 * Seul le serveur DHCP fait les updates
 * 
 * Avantages :
 * - Contrôle centralisé
 * - Évite les conflits
 * - Sécurité (clients non authentifiés ne peuvent pas modifier le DNS)
 */

# Toujours mettre à jour les enregistrements PTR
update-static-leases on;

/*
 * update-static-leases on :
 * Mettre à jour le DNS même pour les baux STATIQUES (IP fixes)
 * 
 * Utile si tu as des réservations DHCP (IP fixe pour un MAC)
 * 
 * Sans ça, seuls les baux dynamiques mettent à jour le DNS
 */

# ───────────────────────────────────────────────────────────────
# CLÉ TSIG POUR DDNS
# ───────────────────────────────────────────────────────────────

# Inclusion de la clé TSIG
include "/etc/dhcp/ddns.key";

/*
 * include :
 * Charge un fichier externe
 * 
 * /etc/dhcp/ddns.key contiendra la clé TSIG
 * (même secret que dans /etc/bind/keys/ddns.key)
 * 
 * [ATTENTION] Ce fichier n'existe pas encore, on va le créer après
 */

# ───────────────────────────────────────────────────────────────
# ZONES DNS À METTRE À JOUR
# ───────────────────────────────────────────────────────────────

# Zone directe
zone monentreprise.local. {
    primary 192.168.1.100;
    key ddns-key;
}

/*
 * zone monentreprise.local. :
 * Déclaration d'une zone DNS à mettre à jour
 * 
 * [ATTENTION] Le point final est OBLIGATOIRE (FQDN)
 * monentreprise.local. (avec point)
 * 
 * primary 192.168.1.100 :
 * Serveur DNS principal pour cette zone
 * IP de notre serveur BIND master
 * 
 * DHCP enverra les DNS UPDATE à cette adresse
 * 
 * key ddns-key :
 * Utiliser la clé TSIG "ddns-key" pour signer les updates
 * 
 * Processus :
 * 1. Client reçoit une IP
 * 2. DHCP construit un DNS UPDATE :
 *    "Ajoute laptop-alice.monentreprise.local -> 192.168.1.205"
 * 3. DHCP signe l'update avec la clé ddns-key
 * 4. DHCP envoie à 192.168.1.100 (serveur DNS)
 * 5. BIND vérifie la signature
 * 6. Si valide -> Ajoute l'enregistrement
 */

# Zone inverse
zone 1.168.192.in-addr.arpa. {
    primary 192.168.1.100;
    key ddns-key;
}

/*
 * Configuration identique pour la zone inverse
 * 
 * DHCP mettra à jour :
 * - Zone directe : laptop-alice -> .205 (A)
 * - Zone inverse : .205 -> laptop-alice (PTR)
 * 
 * Les DEUX sont nécessaires pour une résolution complète
 */

# ───────────────────────────────────────────────────────────────
# DÉFINITION DU SOUS-RÉSEAU
# ───────────────────────────────────────────────────────────────

subnet 192.168.1.0 netmask 255.255.255.0 {
    
    # Plage d'adresses dynamiques
    range 192.168.1.200 192.168.1.250;
    
    /*
     * range :
     * Plage d'IPs attribuables dynamiquement
     * 
     * 192.168.1.200 - 192.168.1.250 :
     * 51 adresses disponibles (.200 à .250 inclus)
     * 
     * Les IPs en dehors de cette plage peuvent être :
     * - Réservations statiques (host { ... })
     * - IPs fixes manuelles (serveurs, imprimantes, etc.)
     * 
     * Recommandation :
     * Diviser le réseau :
     * - .1 - .99 : Serveurs et équipements fixes
     * - .100 - .199 : Réservations DHCP
     * - .200 - .250 : Pool dynamique
     */
    
    # Passerelle par défaut
    option routers 192.168.1.1;
    
    /*
     * option routers :
     * Passerelle par défaut (gateway)
     * 
     * 192.168.1.1 = Routeur/Box Internet
     * 
     * Les clients configureront cette IP comme passerelle
     * Pour accéder à l'extérieur du réseau local
     */
    
    # Broadcast
    option broadcast-address 192.168.1.255;
    
    /*
     * option broadcast-address :
     * Adresse de diffusion (broadcast) du réseau
     * 
     * Calcul :
     * Réseau : 192.168.1.0/24
     * Broadcast : 192.168.1.255 (dernière IP du réseau)
     * 
     * Utilisée pour les communications en broadcast
     * (ex: requêtes ARP, DHCPDISCOVER, etc.)
     */
    
    # Serveur NTP (optionnel)
    option ntp-servers 192.168.1.100;
    
    /*
     * option ntp-servers :
     * Serveurs NTP (Network Time Protocol)
     * Pour la synchronisation de l'heure
     * 
     * Optionnel, mais recommandé pour :
     * - Logs cohérents
     * - Certificats SSL (validité temporelle)
     * - Kerberos, etc.
     */
}

# ───────────────────────────────────────────────────────────────
# RÉSERVATIONS DHCP (OPTIONNEL)
# ───────────────────────────────────────────────────────────────

# Exemple de réservation pour une machine spécifique
# host imprimante {
#     hardware ethernet 00:11:22:33:44:55;
#     fixed-address 192.168.1.150;
# }

/*
 * host <nom> :
 * Définit une réservation DHCP (IP fixe pour un MAC)
 * 
 * hardware ethernet <MAC> :
 * Adresse MAC de la machine
 * 
 * Format MAC :
 * 00:11:22:33:44:55 (séparateurs : ou -)
 * 
 * fixed-address <IP> :
 * IP réservée pour cette machine
 * 
 * Processus :
 * 1. Machine avec MAC 00:11:22:33:44:55 envoie DHCPDISCOVER
 * 2. DHCP reconnaît le MAC
 * 3. Assigne toujours l'IP 192.168.1.150
 * 
 * Utilité :
 * - Serveurs qui ont besoin d'une IP stable
 * - Mais qu'on veut gérer via DHCP (centralisation)
 * - Imprimantes, caméras IP, etc.
 * 
 * [ATTENTION] L'IP réservée doit être EN DEHORS de la plage dynamique
 * Sinon, risque de conflit
 */

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

**Copier la clé TSIG pour DHCP :**

```bash
# Copier la clé depuis BIND
sudo cp /etc/bind/keys/ddns.key /etc/dhcp/

# Ajuster les permissions
sudo chown root:root /etc/dhcp/ddns.key
sudo chmod 640 /etc/dhcp/ddns.key
```

**[ATTENTION] Le serveur DHCP tourne sous l'utilisateur `root`, pas `bind`**

---

**Vérifier la configuration DHCP :**

```bash
sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf
```

**Résultat attendu :**

```
Internet Systems Consortium DHCP Server 4.4.1
Copyright 2004-2018 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Config file: /etc/dhcp/dhcpd.conf
Database file: /var/lib/dhcp/dhcpd.leases
PID file: /var/run/dhcpd.pid
```

**Aucune erreur = [OK] Configuration valide**

---

**Démarrer le serveur DHCP :**

```bash
sudo systemctl start isc-dhcp-server
```

---

**Vérifier le statut :**

```bash
sudo systemctl status isc-dhcp-server
```

**Résultat :**

```
[BLACK_CIRCLE] isc-dhcp-server.service - ISC DHCP IPv4 server
     Loaded: loaded
     Active: active (running) since Mon 2024-12-16 15:00:00 UTC; 5s ago
   Main PID: 23456 (dhcpd)
```

**[OK] DHCP actif !**

---

### ÉTAPE 5 : Tester DDNS avec un client

**Option 1 : Client Linux**

**Sur une machine cliente (ou VM) :**

```bash
# Libérer l'IP actuelle (si existante)
sudo dhclient -r

# Demander une nouvelle IP via DHCP
sudo dhclient -v ens33
```

**`-v` = Verbose (affiche les détails)**

**Résultat attendu :**

```
DHCPDISCOVER on ens33 to 255.255.255.255 port 67 interval 3
DHCPOFFER of 192.168.1.200 from 192.168.1.100
DHCPREQUEST for 192.168.1.200 on ens33 to 255.255.255.255 port 67
DHCPACK of 192.168.1.200 from 192.168.1.100
bound to 192.168.1.200 -- renewal in 40622 seconds.
```

**[OK] IP reçue : 192.168.1.200**

---

**Sur le serveur DHCP, vérifier les logs :**

```bash
sudo journalctl -u isc-dhcp-server -n 30 --no-pager
```

**Tu devrais voir :**

```
Dec 16 15:05:00 ns1 dhcpd[23456]: DHCPDISCOVER from 00:0c:29:xx:xx:xx via ens33
Dec 16 15:05:00 ns1 dhcpd[23456]: DHCPOFFER on 192.168.1.200 to 00:0c:29:xx:xx:xx via ens33
Dec 16 15:05:00 ns1 dhcpd[23456]: DHCPREQUEST for 192.168.1.200 from 00:0c:29:xx:xx:xx via ens33
Dec 16 15:05:00 ns1 dhcpd[23456]: DHCPACK on 192.168.1.200 to 00:0c:29:xx:xx:xx via ens33
Dec 16 15:05:00 ns1 dhcpd[23456]: Added new forward map from client-hostname.monentreprise.local to 192.168.1.200
Dec 16 15:05:00 ns1 dhcpd[23456]: Added reverse map from 200.1.168.192.in-addr.arpa. to client-hostname.monentreprise.local
```

**Lignes importantes :**

**`Added new forward map`**
- Enregistrement A ajouté : client-hostname -> 192.168.1.200

**`Added reverse map`**
- Enregistrement PTR ajouté : 192.168.1.200 -> client-hostname

**[OK] DDNS a fonctionné !**

---

**Sur le serveur DNS (ns1), vérifier les logs BIND :**

```bash
sudo journalctl -u bind9 -n 30 --no-pager
```

**Tu devrais voir :**

```
Dec 16 15:05:00 ns1 named[12345]: client @0x7f... 192.168.1.100#xxxxx/key ddns-key: signer "ddns-key" approved
Dec 16 15:05:00 ns1 named[12345]: client @0x7f... 192.168.1.100#xxxxx/key ddns-key: updating zone 'monentreprise.local/IN': adding an RR at 'client-hostname.monentreprise.local' A 192.168.1.200
Dec 16 15:05:00 ns1 named[12345]: client @0x7f... 192.168.1.100#xxxxx/key ddns-key: updating zone '1.168.192.in-addr.arpa/IN': adding an RR at '200.1.168.192.in-addr.arpa' PTR client-hostname.monentreprise.local.
```

**Décodage :**

**`signer "ddns-key" approved`**
- La signature TSIG a été vérifiée et acceptée

**`updating zone ... adding an RR`**
- Ajout d'un enregistrement (RR = Resource Record)

**[OK] DNS a accepté les updates !**

---

**Vérifier les fichiers de zone :**

```bash
# Zone directe
sudo cat /var/lib/bind/db.monentreprise.local
```

**Tu verras maintenant le nouvel enregistrement :**

```bind
client-hostname.monentreprise.local. 86400 IN A 192.168.1.200
```

---

**MAIS AUSSI un fichier journal (.jnl) :**

```bash
ls -l /var/lib/bind/
```

**Résultat :**

```
-rw-r--r-- 1 bind bind  1234 Dec 16 15:05 db.monentreprise.local
-rw-r--r-- 1 bind bind   456 Dec 16 15:05 db.monentreprise.local.jnl
-rw-r--r-- 1 bind bind   789 Dec 16 15:05 db.192.168.1
-rw-r--r-- 1 bind bind   234 Dec 16 15:05 db.192.168.1.jnl
```

**Fichiers `.jnl` (journal) :**

```
.jnl = Journal file
Contient les modifications DDNS en cours

BIND écrit d'abord dans le .jnl (rapide)
Puis périodiquement réécrit le fichier de zone complet

Avantages :
- Performance (append vs réécriture complète)
- Récupération en cas de crash

[ATTENTION] Ne PAS supprimer les .jnl manuellement !
BIND les gère automatiquement
```

---

**Tester la résolution DNS :**

```bash
# Résolution directe
dig client-hostname.monentreprise.local

# Résolution inverse
dig -x 192.168.1.200
```

**Résultats attendus :**

```
;; ANSWER SECTION:
client-hostname.monentreprise.local. 86400 IN A 192.168.1.200

;; ANSWER SECTION:
200.1.168.192.in-addr.arpa. 86400 IN PTR client-hostname.monentreprise.local.
```

**[BRAVO] DDNS fonctionne parfaitement ! [BRAVO]**

---

### ÉTAPE 6 : Tester avec nsupdate (mise à jour manuelle)

**`nsupdate` = Outil pour envoyer des DNS UPDATE manuellement**

**Utile pour :**
- Tester DDNS
- Ajouter des enregistrements temporaires
- Déboguer

---

**Créer un fichier de commandes update :**

```bash
nano ~/dns-update.txt
```

**Contenu :**

```bind
server 192.168.1.100
zone monentreprise.local.
update add test-ddns.monentreprise.local. 300 A 192.168.1.99
send
```

**Explication ligne par ligne :**

**`server 192.168.1.100`**
- Serveur DNS cible

**`zone monentreprise.local.`**
- Zone à mettre à jour

**`update add ...`**
- Commande d'ajout

**`test-ddns.monentreprise.local.`**
- Nom de l'enregistrement (FQDN avec point final)

**`300`**
- TTL (5 minutes)

**`A`**
- Type d'enregistrement

**`192.168.1.99`**
- Valeur (IP)

**`send`**
- Envoyer la commande

**Sauvegarde : `Ctrl + O`, `Entrée`, `Ctrl + X`**

---

**Exécuter nsupdate avec la clé TSIG :**

```bash
nsupdate -k /etc/bind/keys/ddns.key ~/dns-update.txt
```

**`-k <fichier-clé>` : Utiliser la clé TSIG pour signer**

---

**Si succès, aucune sortie.**

**Vérifier :**

```bash
dig test-ddns.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
test-ddns.monentreprise.local. 300 IN A 192.168.1.99
```

**[OK] Enregistrement ajouté manuellement via DDNS !**

---

**Supprimer l'enregistrement :**

```bash
nano ~/dns-delete.txt
```

**Contenu :**

```bind
server 192.168.1.100
zone monentreprise.local.
update delete test-ddns.monentreprise.local. A
send
```

**Exécuter :**

```bash
nsupdate -k /etc/bind/keys/ddns.key ~/dns-delete.txt
```

---

**Vérifier :**

```bash
dig test-ddns.monentreprise.local
```

**Résultat :**

```
;; ANSWER SECTION:
(vide)
```

**[OK] Enregistrement supprimé !**

---

### [OK] TESTS DE VALIDATION

**1. DHCP attribue des IPs**

- [ ] Client Linux demande une IP : `dhclient -v`
- [ ] Reçoit une IP dans la plage (192.168.1.200-250)
- [ ] Logs DHCP indiquent "DHCPACK"

---

**2. DDNS met à jour les enregistrements A**

- [ ] Logs DHCP : "Added new forward map"
- [ ] Logs BIND : "updating zone ... adding an RR"
- [ ] `dig client-hostname.monentreprise.local` -> IP correcte

---

**3. DDNS met à jour les enregistrements PTR**

- [ ] Logs DHCP : "Added reverse map"
- [ ] `dig -x <IP>` -> Hostname correct

---

**4. Sécurité TSIG**

**Tester sans la clé (doit échouer) :**

```bash
echo "
server 192.168.1.100
zone monentreprise.local.
update add hack.monentreprise.local. 300 A 6.6.6.6
send
" | nsupdate
```

**Résultat attendu :**

```
update failed: REFUSED
```

**[OK] Update refusé sans la clé !**

---

**5. Renouvellement de bail**

- [ ] Attendre 50% du lease time
- [ ] Client renouvelle automatiquement (logs DHCP : DHCPREQUEST)
- [ ] Enregistrement DNS reste inchangé (pas de duplication)

---

**6. Expiration de bail**

- [ ] Éteindre un client
- [ ] Attendre l'expiration du bail (24h par défaut, réduire pour test)
- [ ] Logs DHCP : "lease ... has expired"
- [ ] Enregistrement DNS supprimé automatiquement

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "REFUSED" dans les logs BIND

**Symptôme :**

```bash
sudo journalctl -u bind9 -n 20
```

```
client @0x... 192.168.1.100#xxxxx: update 'monentreprise.local/IN' denied
```

**Cause : BIND refuse l'update**

**Solutions :**

**1. Vérifier allow-update :**

```bash
sudo grep -A 5 "zone \"monentreprise.local\"" /etc/bind/named.conf.local
```

**Doit contenir :**

```bind
allow-update { key ddns-key; };
```

---

**2. Vérifier que la clé est identique :**

```bash
# Sur BIND
sudo cat /etc/bind/keys/ddns.key | grep secret

# Sur DHCP
sudo cat /etc/dhcp/ddns.key | grep secret
```

**Le champ `secret` doit être IDENTIQUE.**

---

**3. Vérifier que la clé est bien incluse :**

```bash
# Dans BIND
sudo grep -r "include.*ddns.key" /etc/bind/

# Dans DHCP
sudo grep -r "include.*ddns.key" /etc/dhcp/
```

---

#### Erreur 2 : Logs DHCP : "unable to add forward map ... timed out"

**Symptôme :**

```
Dec 16 15:10:00 ns1 dhcpd[23456]: unable to add forward map from client-hostname.monentreprise.local to 192.168.1.200: timed out
```

**Cause : DHCP ne peut pas joindre le serveur DNS**

**Solutions :**

**1. Vérifier que BIND écoute sur la bonne IP :**

```bash
sudo netstat -tulpn | grep :53
```

**Doit afficher :**

```
tcp  0  0  192.168.1.100:53  0.0.0.0:*  LISTEN  12345/named
udp  0  0  192.168.1.100:53  0.0.0.0:*         12345/named
```

---

**2. Pare-feu bloque le port 53 :**

```bash
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
```

---

**3. Tester la connexion depuis le serveur DHCP :**

```bash
dig @192.168.1.100 monentreprise.local SOA
```

**Doit répondre (pas timeout).**

---

#### Erreur 3 : Le hostname n'est pas envoyé par le client

**Symptôme :**

L'IP est attribuée, mais le DNS n'est pas mis à jour.

**Logs DHCP :**

```
DHCPACK on 192.168.1.200 to 00:0c:29:xx:xx:xx via ens33
(pas de "Added forward map")
```

**Cause : Le client n'envoie pas son hostname**

**Solutions :**

**Sur le client Linux, configurer le hostname DHCP :**

```bash
sudo nano /etc/dhcp/dhclient.conf
```

**Ajouter/modifier :**

```
send host-name = gethostname();
```

**Ou spécifier un nom fixe :**

```
send host-name "laptop-alice";
```

---

**Redémarrer le client réseau :**

```bash
sudo dhclient -r
sudo dhclient -v ens33
```

---

**Vérifier les logs DHCP :**

```bash
sudo journalctl -u isc-dhcp-server -n 10
```

**Doit maintenant contenir :**

```
DHCPREQUEST for 192.168.1.200 (192.168.1.100) from 00:0c:29:xx:xx:xx (laptop-alice) via ens33
Added new forward map from laptop-alice.monentreprise.local to 192.168.1.200
```

**[OK] Hostname envoyé !**

---

#### Erreur 4 : Fichiers .jnl corrompus

**Symptôme :**

```
named[12345]: zone monentreprise.local/IN: journal file is out of date: removing journal file
```

**OU**

BIND refuse de démarrer après un crash.

**Solution :**

**Arrêter BIND :**

```bash
sudo systemctl stop bind9
```

---

**Supprimer les fichiers .jnl :**

```bash
sudo rm /var/lib/bind/*.jnl
```

---

**Redémarrer BIND :**

```bash
sudo systemctl start bind9
```

**BIND recréera les .jnl automatiquement.**

**[ATTENTION] Les updates DDNS non "committés" seront perdus**

---

#### Erreur 5 : Zone devient trop volumineuse avec le temps

**Symptôme :**

Après des mois/années, le fichier de zone contient des milliers d'enregistrements DDNS obsolètes.

**Solution : Freeze/Thaw pour nettoyer**

**Freezer la zone (arrêter les updates) :**

```bash
sudo rndc freeze monentreprise.local
```

---

**Éditer manuellement le fichier de zone :**

```bash
sudo nano /var/lib/bind/db.monentreprise.local
```

**Supprimer les enregistrements obsolètes.**

**[ATTENTION] NE PAS oublier d'incrémenter le serial !**

---

**Dégeler la zone (reprendre les updates) :**

```bash
sudo rndc thaw monentreprise.local
```

**BIND recharge la zone et accepte à nouveau les updates.**

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. DDNS (Dynamic DNS)**
- Mises à jour automatiques du DNS par DHCP
- Protocole RFC 2136
- Synchronisation IP <-> Nom en temps réel

**2. Intégration DHCP + DNS**
- DHCP attribue une IP
- DHCP met à jour DNS (A et PTR)
- DNS répond immédiatement aux requêtes

**3. Sécurité TSIG**
- Authentification cryptographique
- Empêche les updates non autorisés
- Clé partagée entre DHCP et DNS

**4. Fichiers de zone dynamiques**
- Emplacement : `/var/lib/bind/` (pas `/etc/bind/`)
- Fichiers .jnl (journaux) générés automatiquement
- [ATTENTION] Ne PAS éditer manuellement (utiliser freeze/thaw)

**5. Cycle de vie des enregistrements**
- Création automatique (DHCPACK)
- Renouvellement (DHCPREQUEST)
- Suppression automatique (expiration du bail)

**6. nsupdate**
- Outil CLI pour DNS UPDATE
- Utile pour tests et scripts
- Nécessite clé TSIG pour zones sécurisées

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. DDNS avec IPv6**

```dhcp
# Dans dhcpd.conf
ddns-domainname "monentreprise.local.";
ddns-rev-domainname "ip6.arpa.";

subnet6 2001:db8::/64 {
    range6 2001:db8::100 2001:db8::200;
    option dhcp6.name-servers 2001:db8::100;
}

zone ip6.arpa. {
    primary6 2001:db8::100;
    key ddns-key;
}
```

---

**2. Scavenge automatique (nettoyage)**

**BIND peut supprimer automatiquement les enregistrements obsolètes :**

```bind
zone "monentreprise.local" {
    ...
    update-policy {
        grant ddns-key zonesub any;
    };
    
    # Supprimer les enregistrements non mis à jour depuis 7 jours
    max-journal-size 10m;
    serial-update-method increment;
}
```

---

**3. DDNS avec Active Directory (Windows)**

**Windows Server intègre DNS + DHCP + AD.**

**Clients Windows mettent à jour le DNS eux-mêmes (Secure Dynamic Update).**

**Authentification via Kerberos (pas TSIG).**

---

**4. Surveillance et alertes**

**Script de monitoring :**

```bash
#!/bin/bash
# Vérifier que DDNS fonctionne

# Nombre d'enregistrements dynamiques
DYNAMIC_COUNT=$(grep -c "^[^;].*IN A 192.168.1.2" /var/lib/bind/db.monentreprise.local)

echo "Enregistrements dynamiques : $DYNAMIC_COUNT"

# Alerter si trop nombreux (fuite ?)
if [ $DYNAMIC_COUNT -gt 100 ]; then
    echo "ALERTE : Trop d'enregistrements dynamiques ($DYNAMIC_COUNT)" | \
      mail -s "DDNS Alert" admin@example.com
fi
```

---

**5. Split-horizon DDNS**

**Différentes zones pour interne/externe :**

```bind
view "internal" {
    match-clients { 192.168.1.0/24; };
    
    zone "monentreprise.local" {
        type master;
        file "/var/lib/bind/internal/db.monentreprise.local";
        allow-update { key ddns-key; };
    };
};

view "external" {
    match-clients { any; };
    
    zone "monentreprise.local" {
        type master;
        file "/etc/bind/zones/db.monentreprise.local";
        allow-update { none; };  # Pas de DDNS externe
    };
};
```

**Avantages :**
- Clients internes voient les machines DDNS
- Clients externes ne voient que les serveurs publics

---

## [COURS] CONCLUSION DE L'EXERCICE 3

**[OK] Félicitations ! Tu as mis en place un système DDNS complet ! [BRAVO]**

**Ce que tu as appris :**
- Installer et configurer ISC DHCP Server
- Intégrer DHCP et DNS avec DDNS
- Sécuriser les mises à jour avec TSIG
- Utiliser nsupdate pour des updates manuels
- Gérer les fichiers de zone dynamiques
- Diagnostiquer les problèmes DDNS

**Compétences acquises :**
- [OK] DDNS (Dynamic DNS) - niveau intermédiaire
- [OK] Intégration DHCP + DNS
- [OK] Sécurité TSIG avancée
- [OK] Gestion du cycle de vie DNS
- [OK] Troubleshooting DDNS

**Temps moyen de réalisation :** 2-3 heures

**Prochaine étape :** Exercice 4 - DNSSEC (sécurisation cryptographique du DNS) ! [SECURISE]

---

Veux-tu que je continue avec les exercices 4 et 5 ?

# [ROUGE] EXERCICE 4 : DNSSEC - SÉCURISATION CRYPTOGRAPHIQUE DU DNS

## [LISTE] ÉNONCÉ

### Contexte professionnel

Le RSSI (Responsable Sécurité des Systèmes d'Information) de ton entreprise a lu un article sur les attaques DNS :
- **DNS Cache Poisoning** (empoisonnement du cache)
- **Man-in-the-Middle** (interception et modification des réponses DNS)
- **DNS Spoofing** (usurpation de réponses DNS)

Il te demande : **"Comment pouvons-nous garantir que les réponses DNS n'ont pas été altérées ?"**

Ta mission : Implémenter **DNSSEC** (DNS Security Extensions) pour signer cryptographiquement les zones DNS et permettre la validation des réponses.

### Cahier des charges

Mettre en place DNSSEC avec :
- Génération de clés cryptographiques (KSK et ZSK)
- Signature automatique des zones
- Publication des clés publiques (DNSKEY)
- Génération des signatures (RRSIG)
- Configuration de la chaîne de confiance (DS)
- Validation DNSSEC sur les résolveurs
- Rotation automatique des clés

### Objectifs techniques

- Comprendre les principes de DNSSEC
- Générer les paires de clés KSK et ZSK
- Signer les zones DNS
- Configurer la politique de signature
- Publier les enregistrements DS au registrar
- Activer la validation DNSSEC
- Gérer la rotation des clés
- Diagnostiquer les problèmes DNSSEC

### Contraintes

- BIND 9.16+ (support DNSSEC natif)
- Algorithme recommandé : ECDSAP256SHA256 (13)
- Rotation ZSK : 30 jours
- Rotation KSK : 1 an
- Temps estimé : 3-4 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre les attaques DNS et les limites du DNS classique
- [OK] Maîtriser les concepts DNSSEC (KSK, ZSK, RRSIG, DNSKEY, DS)
- [OK] Générer des clés cryptographiques pour DNSSEC
- [OK] Signer automatiquement des zones DNS
- [OK] Configurer la chaîne de confiance DNSSEC
- [OK] Activer la validation DNSSEC
- [OK] Gérer la rotation des clés
- [OK] Diagnostiquer et résoudre les problèmes DNSSEC

---

## [DOCS] PRÉREQUIS

- Exercices 1, 2 et 3 terminés
- Serveur BIND9 fonctionnel (version 9.16+)
- Compréhension des concepts cryptographiques de base (clés publiques/privées, signatures)
- Accès au registrar pour publier les DS (pour domaines publics)

---

## [GUIDE] RAPPEL THÉORIQUE : DNSSEC

### Problème : Le DNS classique n'est PAS sécurisé

**DNS traditionnel :**

```
Client                Résolveur             Serveur autoritaire
  │                       │                         │
  │  Requête: www.bank.com│                         │
  │──────────────────────>│                         │
  │                       │  Requête: www.bank.com  │
  │                       │────────────────────────>│
  │                       │                         │
  │                       │  Réponse: 93.184.216.34 │
  │                       │<────────────────────────│
  │  Réponse: 93.184.216.34                        │
  │<──────────────────────│                         │
```

**Problème : Aucune garantie d'authenticité !**

---

### Attaque 1 : DNS Cache Poisoning (Empoisonnement du cache)

**Scénario :**

```
1. Attaquant envoie des FAUSSES réponses DNS au résolveur
2. Exemple : "www.bank.com -> 6.6.6.6" (serveur de l'attaquant)
3. Le résolveur met en CACHE cette fausse réponse
4. Tous les clients qui interrogent le résolveur reçoivent 6.6.6.6
5. Les utilisateurs pensent accéder à leur banque
6. En réalité, ils sont sur un site de phishing
7. Vol de mots de passe, données bancaires, etc.
```

**Exemple célèbre : Attaque Kaminsky (2008)**

Dan Kaminsky a découvert une vulnérabilité permettant d'empoisonner le cache DNS en quelques secondes.

---

### Attaque 2 : Man-in-the-Middle (Interception)

**Scénario :**

```
Client                Attaquant             Serveur autoritaire
  │                       │                         │
  │  Requête: www.bank.com│                         │
  │──────────────────────>│                         │
  │                       │  Requête: www.bank.com  │
  │                       │────────────────────────>│
  │                       │                         │
  │                       │  Réponse: 93.184.216.34 │
  │                       │<────────────────────────│
  │                       │                         │
  │  FAUSSE Réponse: 6.6.6.6                       │
  │<──────────────────────│                         │
  │                       │                         │
```

**L'attaquant intercepte et modifie les réponses DNS.**

---

### Solution : DNSSEC (DNS Security Extensions)

**DNSSEC = Signatures cryptographiques pour le DNS**

**Principes :**

1. **Chaque zone est signée avec une clé privée**
2. **Les signatures sont publiées dans le DNS (RRSIG)**
3. **Les clés publiques sont publiées dans le DNS (DNSKEY)**
4. **Les clients peuvent vérifier les signatures**
5. **Chaîne de confiance depuis la racine (.)**

**Avec DNSSEC :**

```
Client                Résolveur             Serveur autoritaire
  │                       │                         │
  │  Requête: www.bank.com│                         │
  │──────────────────────>│                         │
  │                       │  Requête: www.bank.com + DO flag
  │                       │────────────────────────>│
  │                       │                         │
  │                       │  Réponse: 93.184.216.34 │
  │                       │  + RRSIG (signature)    │
  │                       │  + DNSKEY (clé publique)│
  │                       │<────────────────────────│
  │                       │                         │
  │                       │ [Validation de la signature]
  │                       │ [OK] Signature valide     │
  │                       │                         │
  │  Réponse: 93.184.216.34                        │
  │  + Flag AD (Authentic Data)                    │
  │<──────────────────────│                         │
```

**Si un attaquant modifie la réponse :**
- La signature ne correspond plus
- La validation échoue
- Le résolveur REJETTE la réponse
- Le client reçoit SERVFAIL

**[OK] Protection contre l'empoisonnement et le MITM !**

---

### Concepts clés DNSSEC

**1. KSK (Key Signing Key) - Clé de signature de clé**

```
KSK = Clé "maître"
- Utilisée pour SIGNER les DNSKEY
- Durée de vie longue (1 an)
- Taille : 2048 bits (RSA) ou 256 bits (ECDSA)
- Publiée dans le DNS (DNSKEY avec flag 257)
- Hash publié chez le parent (DS record)
```

**2. ZSK (Zone Signing Key) - Clé de signature de zone**

```
ZSK = Clé "opérationnelle"
- Utilisée pour SIGNER les enregistrements de la zone
- Durée de vie courte (30 jours)
- Taille : identique à KSK
- Publiée dans le DNS (DNSKEY avec flag 256)
- Rotation fréquente pour limiter l'exposition
```

**Pourquoi deux clés ?**

```
Analogie : Coffre-fort à double sécurité

KSK = Clé du coffre principal
- Changée rarement (compliqué)
- Protégée au maximum
- Si compromise -> Catastrophe

ZSK = Clé du tiroir du coffre
- Changée régulièrement (facile)
- Utilisée quotidiennement
- Si compromise -> Impact limité (rotation rapide)

Avantages :
1. Sécurité : Limiter l'utilisation de la KSK
2. Opérationnel : Rotation ZSK sans toucher au DS chez le parent
3. Performance : Signature avec ZSK plus rapide (utilisée souvent)
```

**3. RRSIG (Resource Record Signature)**

```
RRSIG = Signature cryptographique d'un enregistrement DNS

Exemple :
www.example.com.  IN  A  93.184.216.34

Devient :
www.example.com.  IN  A      93.184.216.34
www.example.com.  IN  RRSIG  A 13 3 3600 20241231... (signature)

Format RRSIG :
- Type couvert (A, MX, NS, etc.)
- Algorithme (13 = ECDSAP256SHA256)
- Labels (nombre de labels dans le nom)
- TTL original
- Expiration de la signature
- Inception de la signature
- Key Tag (identifiant de la clé)
- Nom du signataire
- Signature (binaire encodé en Base64)
```

**4. DNSKEY (DNS Public Key)**

```
DNSKEY = Clé publique publiée dans le DNS

Format :
example.com.  IN  DNSKEY  257 3 13 mQE... (clé publique KSK)
example.com.  IN  DNSKEY  256 3 13 kL8... (clé publique ZSK)

Flags :
- 256 = ZSK (Zone Signing Key)
- 257 = KSK (Key Signing Key) [256 + SEP (Secure Entry Point)]

Protocol : Toujours 3 (pour DNSSEC)

Algorithm :
- 8 = RSASHA256 (RSA 2048 bits)
- 13 = ECDSAP256SHA256 (ECDSA P-256, RECOMMANDÉ)
- 14 = ECDSAP384SHA384 (ECDSA P-384)
```

**5. DS (Delegation Signer)**

```
DS = Hash de la KSK, publié chez le PARENT

Exemple :
Zone enfant : example.com
Zone parent  : com

Chez le parent (com) :
example.com.  IN  DS  12345 13 2 A1B2C3... (hash de la KSK de example.com)

Format DS :
- Key Tag (identifiant de la KSK)
- Algorithm (13 = ECDSAP256SHA256)
- Digest Type (2 = SHA-256, 4 = SHA-384)
- Digest (hash de la DNSKEY)

Rôle :
Le DS établit la CHAÎNE DE CONFIANCE entre parent et enfant
```

---

### Chaîne de confiance DNSSEC

**Du haut vers le bas :**

```
. (Racine)
│
├─ KSK racine (trust anchor)
│
└─ Zone: com
   │
   ├─ DS de example.com (publié par com)
   │
   └─ Zone: example.com
      │
      ├─ KSK de example.com
      ├─ ZSK de example.com
      │
      └─ Enregistrements signés
```

**Processus de validation :**

```
1. Client demande www.example.com
2. Résolveur commence par la racine (.)
   - Vérifie avec le trust anchor (KSK racine, pré-configurée)
3. Résolveur descend vers .com
   - Vérifie le DS de .com (signé par la racine)
   - Valide la KSK de .com
4. Résolveur descend vers example.com
   - Vérifie le DS de example.com (signé par .com)
   - Valide la KSK de example.com
5. Résolveur vérifie la ZSK de example.com
   - Signée par la KSK de example.com
6. Résolveur vérifie l'enregistrement A de www
   - Signé par la ZSK de example.com
7. [OK] Toute la chaîne est valide -> Réponse AUTHENTIQUE

Si UNE SEULE étape échoue -> SERVFAIL (réponse rejetée)
```

---

### Algorithmes cryptographiques

**Recommandations IETF (2024) :**

| Algorithme | Numéro | Type | Taille clé | Sécurité | Recommandation |
|------------|--------|------|-----------|----------|----------------|
| RSASHA256 | 8 | RSA | 2048 bits | [OK] Bonne | Acceptable |
| ECDSAP256SHA256 | 13 | ECDSA | 256 bits | [OK][OK] Excellente | **RECOMMANDÉ** |
| ECDSAP384SHA384 | 14 | ECDSA | 384 bits | [OK][OK][OK] Très haute | Pour sécurité maximale |
| ED25519 | 15 | EdDSA | 256 bits | [OK][OK][OK] Très haute | Futur (peu supporté) |

**Pourquoi ECDSAP256SHA256 (13) est recommandé ?**

```
ECDSA P-256 :
[OK] Sécurité équivalente à RSA 3072 bits
[OK] Clé BEAUCOUP plus petite (256 bits vs 2048)
[OK] Signatures plus courtes -> Réponses DNS plus petites
[OK] Calcul plus rapide (important pour serveurs chargés)
[OK] Large support (BIND, Unbound, PowerDNS, etc.)

RSA 2048 :
[ATTENTION] Clés et signatures volumineuses
[ATTENTION] Calcul plus lent
[ATTENTION] Risque de dépassement de taille UDP (512 octets)
[OK] Mais : Compatibilité universelle (old clients)
```

**On utilisera ECDSAP256SHA256 (algorithme 13) dans cet exercice.**

---

### Taille des réponses DNS et fragmentation

**Problème : UDP 512 octets**

```
DNS classique (sans DNSSEC) :
Requête + Réponse = ~100-200 octets

DNS avec DNSSEC :
Requête + Réponse + RRSIG + DNSKEY = ~1000-2000 octets !

UDP traditionnel : Maximum 512 octets
-> Dépassement -> Fragmentation -> Paquets perdus

Solutions :
1. EDNS0 (Extension Mechanisms for DNS)
   - Permet des paquets UDP jusqu'à 4096 octets
   - Supporté par 99% des résolveurs modernes

2. Algorithme ECDSA
   - Signatures courtes -> Réponses plus petites
   - Réduit le risque de fragmentation

3. Fallback TCP
   - Si UDP échoue -> Retry en TCP
   - TCP n'a pas de limite de taille
```

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Vérifier la version de BIND

**DNSSEC nécessite BIND 9.16+ pour les fonctionnalités modernes.**

```bash
named -v
```

**Résultat attendu :**

```
BIND 9.18.28-0ubuntu0.22.04.1 (Extended Support Version) <id:>
```

**Si version < 9.16 :**

```bash
# Ajouter le PPA officiel ISC
sudo add-apt-repository ppa:isc/bind -y
sudo apt update
sudo apt upgrade bind9 -y
```

---

### ÉTAPE 2 : Créer une politique de signature automatique

**BIND 9.16+ utilise `dnssec-policy` pour gérer automatiquement DNSSEC.**

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter (avant le `};` final) :**

```bind
// ═══════════════════════════════════════════════════════════════
// POLITIQUE DNSSEC
// ═══════════════════════════════════════════════════════════════

dnssec-policy "standard" {
    
    /*
     * dnssec-policy :
     * Définit une politique de signature DNSSEC
     * 
     * "standard" = Nom de la politique (arbitraire)
     * Peut être réutilisée pour plusieurs zones
     * 
     * BIND 9.16+ gère AUTOMATIQUEMENT :
     * - Génération des clés KSK et ZSK
     * - Signature de la zone
     * - Rotation des clés
     * - Re-signature des enregistrements
     * 
     * Plus besoin de dnssec-keygen, dnssec-signzone manuels !
     */
    
    // ───────────────────────────────────────────────────────────
    // CONFIGURATION DES CLÉS
    // ───────────────────────────────────────────────────────────
    
    keys {
        ksk lifetime unlimited algorithm ecdsap256sha256;
        zsk lifetime 30d algorithm ecdsap256sha256;
    };
    
    /*
     * keys :
     * Configuration des clés cryptographiques
     * 
     * ───────────────────────────────────────────────────────────
     * KSK (Key Signing Key) :
     * 
     * lifetime unlimited :
     * Durée de vie ILLIMITÉE (pas de rotation automatique)
     * 
     * Pourquoi ?
     * - La rotation de KSK nécessite une coordination avec le parent
     * - Il faut publier un nouveau DS chez le registrar
     * - Processus manuel complexe
     * - On préfère gérer la rotation KSK manuellement
     * 
     * Alternative :
     * lifetime 365d -> Rotation automatique tous les 1 an
     * [ATTENTION] Nécessite automatisation de la publication DS
     * 
     * algorithm ecdsap256sha256 :
     * Algorithme ECDSA P-256 avec SHA-256
     * Numéro d'algorithme : 13
     * 
     * Avantages :
     * [OK] Clés courtes (256 bits)
     * [OK] Signatures courtes
     * [OK] Calcul rapide
     * [OK] Sécurité équivalente à RSA 3072
     * [OK] Largement supporté
     * 
     * ───────────────────────────────────────────────────────────
     * ZSK (Zone Signing Key) :
     * 
     * lifetime 30d :
     * Rotation automatique tous les 30 jours
     * 
     * Processus de rotation :
     * Jour 0  : ZSK1 active
     * Jour 23 : ZSK2 générée et publiée (pré-publication)
     * Jour 30 : ZSK2 devient active, ZSK1 désactivée
     * Jour 37 : ZSK1 supprimée (post-publication)
     * 
     * Pourquoi rotation fréquente ?
     * - Limite l'exposition de la clé
     * - Si compromise -> Impact limité à 30 jours
     * - Bonne pratique de sécurité
     * 
     * Recommandations :
     * - 30-90 jours pour production
     * - Plus court pour haute sécurité
     * - Plus long pour réduire la charge serveur
     * 
     * algorithm ecdsap256sha256 :
     * Même algorithme que KSK (obligatoire)
     */
    
    // ───────────────────────────────────────────────────────────
    // DURÉE DE VIE DES SIGNATURES
    // ───────────────────────────────────────────────────────────
    
    dnskey-ttl 3600;
    
    /*
     * dnskey-ttl :
     * TTL des enregistrements DNSKEY
     * 3600 secondes = 1 heure
     * 
     * Compromis :
     * - TTL court -> Changements rapides (rotation de clés)
     * - TTL long -> Moins de charge sur les résolveurs
     * 
     * Recommandations :
     * - 1 heure (3600) : Standard
     * - 6 heures (21600) : Si rotation rare
     * - 5 minutes (300) : Pour tests
     */
    
    publish-safety 7d;
    retire-safety 7d;
    
    /*
     * publish-safety :
     * Délai de sécurité avant activation d'une nouvelle clé
     * 7 jours (7d)
     * 
     * Processus :
     * 1. Nouvelle clé PUBLIÉE dans le DNS (DNSKEY)
     * 2. Attendre publish-safety (7 jours)
     * 3. Les résolveurs ont le temps de mettre en cache la clé
     * 4. Activation de la clé pour signature
     * 
     * Pourquoi 7 jours ?
     * - Couvre les TTL longs (jusqu'à 86400s = 1 jour)
     * - Marge de sécurité x7
     * - Évite les échecs de validation si caches obsolètes
     * 
     * retire-safety :
     * Délai de sécurité avant suppression d'une ancienne clé
     * 7 jours (7d)
     * 
     * Processus :
     * 1. Clé DÉSACTIVÉE (ne signe plus)
     * 2. Attendre retire-safety (7 jours)
     * 3. Toutes les signatures générées par cette clé expirent
     * 4. Suppression de la clé du DNS
     * 
     * [ATTENTION] publish-safety et retire-safety DOIVENT être >= max TTL
     * Sinon risque de :
     * - Signatures non validables (clé manquante)
     * - Échecs de validation (SERVFAIL)
     */
    
    signatures-refresh 5d;
    signatures-validity 14d;
    
    /*
     * signatures-refresh :
     * Fréquence de re-signature des enregistrements
     * 5 jours (5d)
     * 
     * DNSSEC génère des signatures avec une DATE D'EXPIRATION
     * 
     * Pour éviter que les signatures expirent :
     * BIND re-signe périodiquement la zone
     * 
     * signatures-refresh = Quand commencer la re-signature
     * 
     * Calcul :
     * Signature valide pendant : signatures-validity (14 jours)
     * Re-signature après : signatures-refresh (5 jours)
     * Marge de sécurité : 14 - 5 = 9 jours
     * 
     * Si BIND est down pendant 9 jours -> Les signatures expirent
     * 
     * signatures-validity :
     * Durée de validité des signatures
     * 14 jours (14d)
     * 
     * Format RRSIG :
     * inception : 2024-12-16 00:00:00
     * expiration : 2024-12-30 00:00:00 (inception + 14 jours)
     * 
     * Après expiration :
     * - Les résolveurs rejettent la signature
     * - Réponse : SERVFAIL
     * - Nécessite re-signature
     * 
     * Compromis :
     * - Court (7 jours) : Sécurité (limite fenêtre d'attaque)
     *                     Mais : Re-signature fréquente (charge)
     * - Long (30 jours) : Performance (re-signature rare)
     *                     Mais : Fenêtre d'attaque plus large
     * 
     * Recommandation : 14 jours (standard)
     */
    
    max-zone-ttl 86400;
    
    /*
     * max-zone-ttl :
     * TTL maximum dans la zone
     * 86400 secondes = 1 jour
     * 
     * Utilisé pour calculer les délais de sécurité
     * 
     * [ATTENTION] IMPORTANT :
     * Tous les enregistrements de la zone doivent avoir
     * TTL <= max-zone-ttl
     * 
     * Sinon : Erreur de configuration
     * 
     * Vérification :
     * BIND valide que :
     * publish-safety >= max-zone-ttl
     * retire-safety >= max-zone-ttl
     * 
     * Si un enregistrement a TTL = 172800 (2 jours) :
     * -> max-zone-ttl doit être >= 172800
     * -> publish-safety doit être >= 172800 (recommandé: x2 = 4 jours)
     */
    
    // ───────────────────────────────────────────────────────────
    // NSEC vs NSEC3 (Authenticated Denial of Existence)
    // ───────────────────────────────────────────────────────────
    
    nsec3param iterations 0 optout no salt-length 0;
    
    /*
     * PROBLÈME : Prouver qu'un enregistrement N'EXISTE PAS
     * 
     * Exemple :
     * Client demande : unknown.example.com
     * Serveur répond : NXDOMAIN (n'existe pas)
     * 
     * Avec DNSSEC :
     * Comment SIGNER une non-existence ?
     * -> NSEC ou NSEC3
     * 
     * ───────────────────────────────────────────────────────────
     * NSEC (Next Secure) :
     * 
     * Liste CHAÎNÉE des enregistrements existants
     * 
     * Exemple :
     * www.example.com.  NSEC  mail.example.com. A AAAA RRSIG
     * mail.example.com. NSEC  ns1.example.com.  A MX RRSIG
     * ns1.example.com.  NSEC  www.example.com.  A RRSIG
     * 
     * Si client demande : blog.example.com
     * Réponse : NSEC de www.example.com -> mail.example.com
     * -> blog n'est PAS dans cet intervalle
     * -> Donc blog n'existe pas (NXDOMAIN)
     * 
     * [ATTENTION] Problème de NSEC : ZONE WALKING
     * Un attaquant peut énumérer TOUS les noms de la zone
     * En suivant la chaîne NSEC
     * 
     * ───────────────────────────────────────────────────────────
     * NSEC3 (NSEC version 3 - Hashed) :
     * 
     * Identique à NSEC, mais les noms sont HASHÉS
     * 
     * Exemple :
     * A1B2C3D4.example.com.  NSEC3  E5F6G7H8. A RRSIG
     * 
     * A1B2C3D4 = Hash de "www.example.com"
     * E5F6G7H8 = Hash de "mail.example.com"
     * 
     * Avantages :
     * [OK] Zone walking beaucoup plus difficile
     * [OK] Noms réels cachés
     * 
     * Inconvénients :
     * [ATTENTION] Plus complexe
     * [ATTENTION] Plus de calcul (hashage)
     * [ATTENTION] Réponses plus volumineuses
     * 
     * ───────────────────────────────────────────────────────────
     * NSEC3 PARAMÈTRES :
     * 
     * iterations 0 :
     * Nombre d'itérations de hashage
     * 0 = Un seul hash (recommandé en 2024)
     * 
     * Historiquement : iterations 10-50
     * Mais : Rainbow tables ont progressé
     * -> Plus d'itérations n'apportent plus de sécurité
     * -> Juste de la charge CPU
     * 
     * Recommandation moderne : iterations 0
     * 
     * optout no :
     * Opt-out pour les zones non signées
     * no = Toutes les zones doivent être signées
     * 
     * Contexte : Zones déléguées (subdomains)
     * Si optout yes -> Les subdomains peuvent être non signés
     * 
     * Recommandation : no (toujours signer)
     * 
     * salt-length 0 :
     * Longueur du sel (salt) pour le hashage
     * 0 = Pas de sel
     * 
     * Le sel était utilisé pour compliquer les rainbow tables
     * Mais avec iterations 0, le sel n'apporte rien
     * 
     * Recommandation moderne : salt-length 0
     * 
     * ───────────────────────────────────────────────────────────
     * NSEC vs NSEC3 : Que choisir ?
     * 
     * NSEC :
     * [OK] Plus simple
     * [OK] Plus rapide
     * [OK] Réponses plus petites
     * [ATTENTION] Zone walking possible
     * 
     * NSEC3 :
     * [OK] Zone walking difficile
     * [ATTENTION] Plus complexe
     * [ATTENTION] Plus lent
     * [ATTENTION] Réponses plus volumineuses
     * 
     * Recommandation :
     * - NSEC : Pour zones internes (monentreprise.local)
     *          Pas de risque de zone walking (réseau privé)
     * 
     * - NSEC3 : Pour domaines publics (example.com)
     *           Protection contre énumération
     * 
     * Pour cet exercice : On utilise NSEC3 (apprentissage complet)
     */
};
```

**Sauvegarde.**

---

### ÉTAPE 3 : Activer DNSSEC sur les zones

**Éditer `/etc/bind/named.conf.local` :**

```bash
sudo nano /etc/bind/named.conf.local
```

**Modifier la zone directe :**

```bind
zone "monentreprise.local" {
    type master;
    file "/var/lib/bind/db.monentreprise.local";
    
    allow-transfer { key transfer-key; };
    notify yes;
    also-notify { 192.168.1.101 key transfer-key; };
    
    allow-update { key ddns-key; };
    update-policy {
        grant ddns-key zonesub any;
    };
    
    // ───────────────────────────────────────────────────────────
    // ACTIVATION DNSSEC
    // ───────────────────────────────────────────────────────────
    
    dnssec-policy "standard";
    
    /*
     * dnssec-policy "standard" :
     * Active DNSSEC avec la politique "standard" définie précédemment
     * 
     * BIND va AUTOMATIQUEMENT :
     * 1. Générer les clés KSK et ZSK
     * 2. Signer la zone
     * 3. Créer les RRSIG pour chaque enregistrement
     * 4. Publier les DNSKEY
     * 5. Créer les NSEC3 pour les NXDOMAIN
     * 6. Gérer la rotation des clés
     * 7. Re-signer périodiquement
     * 
     * Emplacement des clés :
     * /var/lib/bind/K<zone>+<algo>+<keyid>.key     (clé publique)
     * /var/lib/bind/K<zone>+<algo>+<keyid>.private (clé privée)
     * 
     * Exemple :
     * /var/lib/bind/Kmonentreprise.local.+013+12345.key
     * /var/lib/bind/Kmonentreprise.local.+013+12345.private
     * 
     * +013 = Algorithme ECDSAP256SHA256
     * +12345 = Key ID
     */
    
    inline-signing yes;
    
    /*
     * inline-signing yes :
     * Signer la zone "en ligne" (inline)
     * 
     * Mode de fonctionnement :
     * 
     * SANS inline-signing :
     * 1. Zone non signée : db.monentreprise.local
     * 2. Commande manuelle : dnssec-signzone
     * 3. Zone signée : db.monentreprise.local.signed
     * 4. BIND charge la zone signée
     * 
     * Problème :
     * - Processus manuel
     * - Incompatible avec DDNS (updates dynamiques)
     * - Compliqué
     * 
     * AVEC inline-signing :
     * 1. Zone non signée : db.monentreprise.local
     * 2. BIND signe AUTOMATIQUEMENT en mémoire
     * 3. Zone signée servie aux clients
     * 4. Fichier source reste non signé (éditable)
     * 
     * Avantages :
     * [OK] Automatique
     * [OK] Compatible DDNS
     * [OK] Plus simple
     * 
     * [ATTENTION] inline-signing est OBLIGATOIRE avec dnssec-policy
     * (activé automatiquement si omis)
     */
};
```

---

**Modifier la zone inverse :**

```bind
zone "1.168.192.in-addr.arpa" {
    type master;
    file "/var/lib/bind/db.192.168.1";
    
    allow-transfer { key transfer-key; };
    notify yes;
    also-notify { 192.168.1.101 key transfer-key; };
    
    allow-update { key ddns-key; };
    update-policy {
        grant ddns-key zonesub any;
    };
    
    dnssec-policy "standard";
    inline-signing yes;
    
    /*
     * Configuration identique pour la zone inverse
     * 
     * [ATTENTION] IMPORTANT :
     * Les zones directes ET inverses doivent être signées
     * Sinon incohérence et échecs de validation
     */
};
```

**Sauvegarde.**

---

### ÉTAPE 4 : Vérifier la configuration et recharger BIND

**Vérifier la syntaxe :**

```bash
sudo named-checkconf
```

**Aucune erreur = [OK]**

---

**Recharger BIND :**

```bash
sudo rndc reload
```

**Résultat :**

```
server reload successful
```

---

**Vérifier les logs :**

```bash
sudo journalctl -u bind9 -n 50 --no-pager
```

**Tu devrais voir :**

```
Dec 16 16:00:00 ns1 named[12345]: zone monentreprise.local/IN: generating DNSSEC keys
Dec 16 16:00:00 ns1 named[12345]: zone monentreprise.local/IN: generating KSK (ecdsap256sha256)
Dec 16 16:00:00 ns1 named[12345]: zone monentreprise.local/IN: DNSKEY monentreprise.local/ECDSAP256SHA256/12345 (KSK) is now published
Dec 16 16:00:00 ns1 named[12345]: zone monentreprise.local/IN: generating ZSK (ecdsap256sha256)
Dec 16 16:00:00 ns1 named[12345]: zone monentreprise.local/IN: DNSKEY monentreprise.local/ECDSAP256SHA256/54321 (ZSK) is now published
Dec 16 16:00:01 ns1 named[12345]: zone monentreprise.local/IN: next key event: 16-Dec-2024 16:00:01.000
Dec 16 16:00:01 ns1 named[12345]: zone monentreprise.local/IN: reconfiguring zone keys
Dec 16 16:00:01 ns1 named[12345]: zone monentreprise.local/IN: DNSKEY monentreprise.local/ECDSAP256SHA256/54321 (ZSK) is now active
Dec 16 16:00:01 ns1 named[12345]: zone monentreprise.local/IN: DNSKEY monentreprise.local/ECDSAP256SHA256/12345 (KSK) is now active
Dec 16 16:00:02 ns1 named[12345]: zone monentreprise.local/IN: signing with key 12345/ECDSAP256SHA256
Dec 16 16:00:02 ns1 named[12345]: zone monentreprise.local/IN: signing with key 54321/ECDSAP256SHA256
Dec 16 16:00:03 ns1 named[12345]: zone monentreprise.local/IN: zone fully signed
```

**Décodage :**

**`generating DNSSEC keys`**
- BIND génère les clés automatiquement

**`KSK/ZSK is now published`**
- Clés publiées dans le DNS (DNSKEY)

**`is now active`**
- Clés activées pour signature

**`signing with key ...`**
- Signature de la zone en cours

**`zone fully signed`**
- [OK] Zone complètement signée !

---

### ÉTAPE 5 : Vérifier les clés générées

**Lister les fichiers de clés :**

```bash
sudo ls -l /var/lib/bind/K*
```

**Résultat attendu :**

```
-rw-r----- 1 bind bind  123 Dec 16 16:00 Kmonentreprise.local.+013+12345.key
-rw------- 1 bind bind   78 Dec 16 16:00 Kmonentreprise.local.+013+12345.private
-rw-r----- 1 bind bind  123 Dec 16 16:00 Kmonentreprise.local.+013+54321.key
-rw------- 1 bind bind   78 Dec 16 16:00 Kmonentreprise.local.+013+54321.private
-rw-r----- 1 bind bind  123 Dec 16 16:00 K1.168.192.in-addr.arpa.+013+98765.key
-rw------- 1 bind bind   78 Dec 16 16:00 K1.168.192.in-addr.arpa.+013+98765.private
-rw-r----- 1 bind bind  123 Dec 16 16:00 K1.168.192.in-addr.arpa.+013+45678.key
-rw------- 1 bind bind   78 Dec 16 16:00 K1.168.192.in-addr.arpa.+013+45678.private
```

**Format du nom de fichier :**

```
K<zone>+<algo>+<keyid>.<extension>

K = Prefix pour clés DNSSEC
<zone> = Nom de la zone
<algo> = Numéro d'algorithme (013 = ECDSAP256SHA256)
<keyid> = Identifiant unique de la clé (calculé)
.key = Clé publique
.private = Clé privée
```

---

**Examiner une clé publique (KSK) :**

```bash
sudo cat /var/lib/bind/Kmonentreprise.local.+013+12345.key
```

**Résultat :**

```
; This is a key-signing key, keyid 12345, for monentreprise.local.
; Created: 20241216160000 (Mon Dec 16 16:00:00 2024)
; Publish: 20241216160000 (Mon Dec 16 16:00:00 2024)
; Activate: 20241216160000 (Mon Dec 16 16:00:00 2024)
monentreprise.local. IN DNSKEY 257 3 13 mQE... (clé publique en Base64)
```

**Explication :**

**`257`**
- Flag KSK (256 + SEP Secure Entry Point)

**`3`**
- Protocol (toujours 3 pour DNSSEC)

**`13`**
- Algorithme ECDSAP256SHA256

**`mQE...`**
- Clé publique ECDSA P-256 (encodée en Base64)

---

**Examiner une clé privée ([ATTENTION] SENSIBLE) :**

```bash
sudo cat /var/lib/bind/Kmonentreprise.local.+013+12345.private
```

**Résultat :**

```
Private-key-format: v1.3
Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: A1B2C3D4... (clé privée en Base64)
Created: 20241216160000
Publish: 20241216160000
Activate: 20241216160000
```

**[ATTENTION] Cette clé DOIT rester SECRÈTE !**

**Permissions :**

```bash
sudo chmod 600 /var/lib/bind/*.private
sudo chown bind:bind /var/lib/bind/K*
```

---

### ÉTAPE 6 : Vérifier les enregistrements DNSSEC

**Interroger les DNSKEY :**

```bash
dig @localhost monentreprise.local DNSKEY +multiline
```

**Résultat :**

```
;; ANSWER SECTION:
monentreprise.local. 3600 IN DNSKEY 256 3 13 (
                kL8... (ZSK)
                ) ; ZSK; alg = ECDSAP256SHA256 ; key id = 54321
monentreprise.local. 3600 IN DNSKEY 257 3 13 (
                mQE... (KSK)
                ) ; KSK; alg = ECDSAP256SHA256 ; key id = 12345
```

**On voit bien les DEUX clés :**
- **256** = ZSK
- **257** = KSK

---

**Interroger un enregistrement avec sa signature :**

```bash
dig @localhost www.monentreprise.local A +dnssec +multiline
```

**Résultat :**

```
;; ANSWER SECTION:
www.monentreprise.local. 86400 IN A 192.168.1.10
www.monentreprise.local. 86400 IN RRSIG A 13 3 86400 (
                20241230000000 20241216000000 54321 monentreprise.local.
                A1B2C3D4... (signature en Base64)
                )
```

**Décodage du RRSIG :**

**`A`**
- Type d'enregistrement couvert (A)

**`13`**
- Algorithme (ECDSAP256SHA256)

**`3`**
- Nombre de labels (monentreprise.local. = 2 labels + racine)

**`86400`**
- TTL original

**`20241230000000`**
- Expiration : 30 Dec 2024 00:00:00

**`20241216000000`**
- Inception : 16 Dec 2024 00:00:00

**`54321`**
- Key Tag (ID de la ZSK qui a signé)

**`monentreprise.local.`**
- Nom du signataire

**`A1B2C3D4...`**
- Signature cryptographique

---

**Vérifier NSEC3 (authenticated denial) :**

```bash
dig @localhost doesnotexist.monentreprise.local A +dnssec
```

**Résultat :**

```
;; AUTHORITY SECTION:
A1B2C3D4E5F6.monentreprise.local. 3600 IN NSEC3 1 0 0 - (
                F6G7H8I9J0K1 A RRSIG )
monentreprise.local. 3600 IN NSEC3PARAM 1 0 0 -
```

**`NSEC3` présent :**
- [OK] Preuves cryptographiques de non-existence

---

### ÉTAPE 7 : Générer le DS pour publication chez le parent

**Pour les domaines PUBLICS (example.com, etc.) :**

Le DS doit être publié chez le **registrar** (parent zone).

**Pour les domaines INTERNES (monentreprise.local) :**

On va configurer un **trust anchor** local sur les résolveurs.

---

**Extraire le DS de la KSK :**

```bash
# Trouver le fichier de la KSK (flag 257)
KSK_FILE=$(sudo ls /var/lib/bind/Kmonentreprise.local.*.key | head -1)

# Générer le DS
sudo dnssec-dsfromkey -2 $KSK_FILE
```

**`-2` = Utiliser SHA-256 (recommandé)**

**Résultat :**

```
monentreprise.local. IN DS 12345 13 2 A1B2C3D4E5F6... (hash SHA-256 de la KSK)
```

**Format DS :**

```
<zone> IN DS <key-id> <algo> <digest-type> <digest>

12345 = Key ID de la KSK
13 = Algorithme ECDSAP256SHA256
2 = Digest type SHA-256
A1B2C3D4... = Hash de la DNSKEY
```

---

**Sauvegarder le DS :**

```bash
sudo dnssec-dsfromkey -2 $KSK_FILE | sudo tee /var/lib/bind/dsset-monentreprise.local.txt
```

**Ce fichier contient le DS à publier chez le parent.**

**Pour un domaine public :**
- Connexion au panneau de contrôle du registrar (OVH, Gandi, etc.)
- Section DNSSEC
- Coller le DS

---

### ÉTAPE 8 : Configurer la validation DNSSEC sur un résolveur

**Sur un serveur résolveur (peut être le même serveur ou un autre) :**

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter/modifier :**

```bind
options {
    directory "/var/cache/bind";
    
    // ───────────────────────────────────────────────────────────
    // VALIDATION DNSSEC
    // ───────────────────────────────────────────────────────────
    
    dnssec-validation auto;
    
    /*
     * dnssec-validation :
     * Active la validation DNSSEC
     * 
     * Valeurs :
     * - auto : Utilise le trust anchor de la racine (.)
     *          Inclus dans BIND (managed-keys)
     *          Mis à jour automatiquement (RFC 5011)
     * 
     * - yes : Validation active, mais nécessite trust anchors manuels
     * 
     * - no : Pas de validation (DANGEREUX)
     * 
     * Recommandation : auto (pour Internet)
     * 
     * Pour zones internes :
     * - Définir un trust anchor manuel
     * - Voir étape suivante
     */
    
    // Forwarders (optionnel)
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };
    
    recursion yes;
    allow-recursion { localhost; 192.168.1.0/24; };
    
    listen-on { 127.0.0.1; 192.168.1.100; };
    
    // Requêtes avec DNSSEC
    dnssec-enable yes;
    
    /*
     * dnssec-enable :
     * Active le support DNSSEC
     * 
     * [ATTENTION] Déprécié dans BIND 9.18+
     * (toujours activé par défaut)
     * 
     * Mais conservé pour compatibilité avec versions anciennes
     */
};
```

---

**Pour les zones INTERNES (monentreprise.local), ajouter un trust anchor :**

**Créer un fichier de trust anchor :**

```bash
sudo nano /etc/bind/trusted-keys.conf
```

**Contenu :**

```bind
// ═══════════════════════════════════════════════════════════════
// TRUST ANCHORS POUR ZONES INTERNES
// ═══════════════════════════════════════════════════════════════

trust-anchors {
    
    /*
     * trust-anchors :
     * Points de confiance pour la validation DNSSEC
     * 
     * Format :
     * "<zone>" <type> <key-data>;
     * 
     * Types :
     * - initial-key : Clé initiale (managed, mise à jour auto)
     * - static-key : Clé statique (jamais mise à jour)
     * - initial-ds : DS initial
     * - static-ds : DS statique
     * 
     * Recommandation : static-key pour zones internes
     * (pas de mécanisme de mise à jour automatique)
     */
    
    // Trust anchor pour monentreprise.local
    "monentreprise.local." static-key 257 3 13 "mQE...";
    
    /*
     * Copier la clé publique KSK depuis :
     * /var/lib/bind/Kmonentreprise.local.+013+12345.key
     * 
     * Format :
     * "<zone>" static-key <flags> <protocol> <algo> "<public-key>";
     * 
     * 257 = Flag KSK
     * 3 = Protocol
     * 13 = Algorithme ECDSAP256SHA256
     * "mQE..." = Clé publique (entre guillemets)
     * 
     * [ATTENTION] IMPORTANT :
     * Le trust anchor doit correspondre EXACTEMENT à la KSK du serveur autoritaire
     * 
     * Si la KSK change (rotation) :
     * -> Mettre à jour le trust anchor manuellement
     */
    
    // Trust anchor pour la zone inverse (optionnel)
    "1.168.192.in-addr.arpa." static-key 257 3 13 "kL8...";
};

// ═══════════════════════════════════════════════════════════════
```

**Récupérer la clé publique KSK :**

```bash
# Sur le serveur autoritaire
sudo grep "IN DNSKEY 257" /var/lib/bind/Kmonentreprise.local.*.key
```

**Copier la partie Base64 (la longue chaîne après le `13`).**

---

**Inclure le fichier de trust anchors :**

**Éditer `/etc/bind/named.conf` :**

```bash
sudo nano /etc/bind/named.conf
```

**Ajouter (après les autres includes) :**

```bind
include "/etc/bind/trusted-keys.conf";
```

**Sauvegarde.**

---

**Vérifier la configuration :**

```bash
sudo named-checkconf
```

---

**Recharger BIND :**

```bash
sudo rndc reload
```

---

### ÉTAPE 9 : Tester la validation DNSSEC

**Interroger avec validation :**

```bash
dig @localhost www.monentreprise.local +dnssec
```

**Résultat :**

```
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
www.monentreprise.local. 86400 IN A 192.168.1.10
www.monentreprise.local. 86400 IN RRSIG A 13 3 86400 ...
```

**Flag important :**

**`ad`** = **Authenticated Data**
- [OK] La signature a été VALIDÉE
- La réponse est AUTHENTIQUE
- Chaîne de confiance complète

---

**Tester avec delv (DNSSEC Lookaside Validation) :**

```bash
delv @localhost www.monentreprise.local A
```

**Résultat :**

```
; fully validated
www.monentreprise.local.	86400	IN	A	192.168.1.10
www.monentreprise.local.	86400	IN	RRSIG	A 13 3 86400 20241230000000 ...
```

**`fully validated` = [OK] Signature validée avec succès !**

---

**Tester une modification (simulation d'attaque) :**

**Modifier MANUELLEMENT un enregistrement signé (SIMULATION) :**

Cette étape est THÉORIQUE (pour comprendre). En pratique, BIND empêche ce genre de modification.

**Si un attaquant modifiait la réponse :**

```
www.monentreprise.local. 86400 IN A 6.6.6.6  (IP de l'attaquant)
(Mais signature toujours pour 192.168.1.10)
```

**Le résolveur validerait :**

1. Calculer hash de "www.monentreprise.local IN A 6.6.6.6"
2. Vérifier avec la signature RRSIG
3. [X] Signature invalide !
4. Réponse : **SERVFAIL**

**Le client ne recevrait PAS l'IP falsifiée.**

---

### [OK] TESTS DE VALIDATION

**1. Clés générées automatiquement**

- [ ] Fichiers `K*.key` et `K*.private` présents dans `/var/lib/bind/`
- [ ] KSK et ZSK pour chaque zone
- [ ] Logs BIND : "zone fully signed"

---

**2. DNSKEY publiées**

- [ ] `dig @localhost monentreprise.local DNSKEY` -> 2 clés (KSK + ZSK)
- [ ] Flag 257 (KSK) et 256 (ZSK)

---

**3. Signatures RRSIG**

- [ ] `dig @localhost www.monentreprise.local +dnssec` -> RRSIG présent
- [ ] Expiration dans le futur (20241230...)
- [ ] Key Tag correspond à la ZSK

---

**4. NSEC3 pour NXDOMAIN**

- [ ] `dig @localhost doesnotexist.monentreprise.local +dnssec` -> NSEC3 présent
- [ ] Pas de SERVFAIL, mais NXDOMAIN signé

---

**5. Validation DNSSEC**

- [ ] Flag `ad` présent dans les réponses
- [ ] `delv` indique "fully validated"
- [ ] Pas de SERVFAIL

---

**6. DS généré**

- [ ] `dnssec-dsfromkey` génère un DS valide
- [ ] Format : `<zone> IN DS <keyid> 13 2 <hash>`

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "SERVFAIL" lors de la validation

**Symptôme :**

```bash
dig @localhost www.monentreprise.local
```

```
;; status: SERVFAIL
```

**Cause : Échec de validation DNSSEC**

**Diagnostic :**

```bash
delv @localhost www.monentreprise.local A
```

**Peut afficher :**

```
;; resolution failed: SERVFAIL
```

---

**Solutions :**

**1. Vérifier que le trust anchor est correct :**

```bash
sudo cat /etc/bind/trusted-keys.conf
```

**La clé publique doit correspondre EXACTEMENT à la KSK.**

---

**2. Vérifier les logs BIND :**

```bash
sudo journalctl -u bind9 -n 50
```

**Chercher :**

```
validating www.monentreprise.local/A: no valid signature found
validating www.monentreprise.local/A: insecurity proof failed
```

---

**3. Désactiver temporairement la validation pour tester :**

```bash
dig @localhost www.monentreprise.local +cd
```

**`+cd` = Check Disabled (ignore validation)**

**Si ça fonctionne -> Problème de validation DNSSEC**

---

#### Erreur 2 : Signatures expirées

**Symptôme :**

```
validating www.monentreprise.local/A: verify failed due to bad signature (keyid=54321): RRSIG has expired
```

**Cause : Les signatures ont expiré**

**Solutions :**

**1. Vérifier l'horloge du serveur :**

```bash
date
```

**Si désynchronisée -> Installer NTP :**

```bash
sudo apt install ntp -y
sudo systemctl start ntp
```

---

**2. Forcer une re-signature :**

```bash
sudo rndc sign monentreprise.local
```

---

**3. Vérifier la politique DNSSEC :**

```bash
sudo grep "signatures-validity" /etc/bind/named.conf.options
```

**Doit être suffisamment long (14 jours recommandé).**

---

#### Erreur 3 : "no valid KEY found" ou "insecure"

**Symptôme :**

```
; unsigned answer
```

**Ou :**

```
no valid RRSIG resolving 'www.monentreprise.local/A'
```

**Cause : Chaîne de confiance brisée**

**Solutions :**

**1. Vérifier que la zone est bien signée :**

```bash
dig @localhost monentreprise.local DNSKEY
```

**Doit retourner les DNSKEY.**

---

**2. Vérifier que le trust anchor est chargé :**

```bash
sudo rndc managed-keys status | grep monentreprise
```

---

**3. Recharger les trust anchors :**

```bash
sudo rndc reload
```

---

#### Erreur 4 : Clés non générées

**Symptôme :**

```bash
sudo ls /var/lib/bind/K*
```

```
ls: cannot access '/var/lib/bind/K*': No such file or directory
```

**Cause : BIND n'a pas généré les clés**

**Solutions :**

**1. Vérifier que dnssec-policy est activé :**

```bash
sudo grep "dnssec-policy" /etc/bind/named.conf.local
```

---

**2. Vérifier les permissions du dossier :**

```bash
sudo ls -ld /var/lib/bind/
```

**Doit être :**

```
drwxrwxr-x 2 bind bind 4096 Dec 16 16:00 /var/lib/bind/
```

**Corriger si nécessaire :**

```bash
sudo chown bind:bind /var/lib/bind/
sudo chmod 775 /var/lib/bind/
```

---

**3. Forcer la génération :**

```bash
sudo rndc reconfig
```

**Vérifier les logs :**

```bash
sudo journalctl -u bind9 -n 20
```

---

#### Erreur 5 : "zone not loaded due to errors"

**Symptôme :**

```
zone monentreprise.local/IN: not loaded due to errors.
```

**Cause : Fichier de zone invalide avec DNSSEC**

**Solutions :**

**1. Vérifier le fichier de zone :**

```bash
sudo named-checkzone monentreprise.local /var/lib/bind/db.monentreprise.local
```

---

**2. Vérifier les TTL :**

**Tous les TTL doivent être <= max-zone-ttl (défini dans dnssec-policy).**

---

**3. Supprimer les fichiers .jnl corrompus :**

```bash
sudo systemctl stop bind9
sudo rm /var/lib/bind/*.jnl
sudo systemctl start bind9
```

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. DNSSEC = Signatures cryptographiques**
- Garantit l'authenticité des réponses DNS
- Protège contre cache poisoning et MITM
- Basé sur PKI (Public Key Infrastructure)

**2. KSK vs ZSK**
- KSK : Clé maître, longue durée de vie, signe les DNSKEY
- ZSK : Clé opérationnelle, rotation fréquente, signe les enregistrements

**3. Enregistrements DNSSEC**
- DNSKEY : Clés publiques
- RRSIG : Signatures
- DS : Hash de KSK (chez le parent)
- NSEC/NSEC3 : Preuves de non-existence

**4. Chaîne de confiance**
- Depuis la racine (.) jusqu'à la zone
- Chaque niveau valide le suivant
- Trust anchor = Point de départ

**5. Validation**
- Flag `ad` (Authenticated Data) = Signature valide
- SERVFAIL = Échec de validation
- delv = Outil de diagnostic DNSSEC

**6. Gestion automatique avec BIND 9.16+**
- dnssec-policy : Configuration centralisée
- Génération automatique des clés
- Signature automatique
- Rotation automatique

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Rotation manuelle de la KSK**

**Scénario : La KSK a 1 an, rotation nécessaire.**

```bash
# 1. Générer une nouvelle KSK
sudo dnssec-keygen -a ECDSAP256SHA256 -f KSK monentreprise.local

# 2. Ajouter à la zone (pré-publication)
sudo rndc loadkeys monentreprise.local

# 3. Générer le nouveau DS
sudo dnssec-dsfromkey -2 Kmonentreprise.local.+013+<new-keyid>.key

# 4. Publier le nouveau DS chez le registrar

# 5. Attendre propagation (7 jours)

# 6. Activer la nouvelle KSK
sudo rndc sign monentreprise.local

# 7. Désactiver l'ancienne KSK
# (éditer le fichier .key, changer Publish -> Inactive)

# 8. Attendre 7 jours (retire-safety)

# 9. Supprimer l'ancienne KSK
sudo rm Kmonentreprise.local.+013+<old-keyid>.*
```

---

**2. DNSSEC avec serveurs cachés (hidden master)**

```bind
# Master (caché, pas dans les NS)
zone "example.com" {
    type master;
    dnssec-policy "standard";
    inline-signing yes;
    also-notify { <IP-slave> key transfer-key; };
};

# Slaves (publics, dans les NS)
# Reçoivent les zones DÉJÀ SIGNÉES
zone "example.com" {
    type slave;
    masters { <IP-master> key transfer-key; };
    dnssec-policy "none";  # Pas de re-signature
};
```

---

**3. Monitoring DNSSEC**

**Script de vérification :**

```bash
#!/bin/bash

ZONE="monentreprise.local"
NS="192.168.1.100"

# Vérifier les DNSKEY
DNSKEY_COUNT=$(dig @$NS $ZONE DNSKEY +short | wc -l)

if [ $DNSKEY_COUNT -lt 2 ]; then
    echo "ALERTE : Moins de 2 DNSKEY pour $ZONE"
fi

# Vérifier expiration des signatures
EXPIRATION=$(dig @$NS www.$ZONE A +dnssec | grep RRSIG | awk '{print $9}')
EXPIRATION_DATE=$(echo $EXPIRATION | cut -c1-8)
TODAY=$(date +%Y%m%d)

if [ $EXPIRATION_DATE -le $TODAY ]; then
    echo "ALERTE : Signatures expirées pour www.$ZONE"
fi

# Vérifier validation
delv @$NS www.$ZONE A > /dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "ALERTE : Échec validation DNSSEC pour www.$ZONE"
fi
```

---

**4. Multi-signer DNSSEC (RFC 8901)**

**Deux serveurs autoritaires DIFFÉRENTS signent la MÊME zone.**

**Avantages :**
- Redondance des clés
- Pas de single point of failure
- Continuité en cas de compromission

**Configuration complexe, nécessite orchestration.**

---

**5. DNSSEC avec DANE (DNS-based Authentication of Named Entities)**

**DANE = Certificats SSL/TLS dans le DNS (TLSA records)**

```bind
_443._tcp.www.example.com. IN TLSA 3 1 1 A1B2C3... (hash du certificat)
```

**Avantages :**
- Alternative aux CA traditionnelles
- Certificat validé via DNSSEC
- Protection contre certificats frauduleux

---

## [COURS] CONCLUSION DE L'EXERCICE 4

**[OK] Félicitations ! Tu as implémenté DNSSEC de bout en bout ! [BRAVO]**

**Ce que tu as appris :**
- Comprendre les attaques DNS et les limites du DNS classique
- Maîtriser les concepts DNSSEC (KSK, ZSK, RRSIG, DNSKEY, DS, NSEC3)
- Configurer dnssec-policy pour gestion automatique
- Signer des zones DNS automatiquement
- Générer et publier des DS
- Activer la validation DNSSEC
- Diagnostiquer les problèmes de validation

**Compétences acquises :**
- [OK] DNSSEC (DNS Security Extensions) - niveau avancé
- [OK] Cryptographie appliquée (PKI, signatures)
- [OK] Chaîne de confiance
- [OK] Gestion de clés cryptographiques
- [OK] Troubleshooting DNSSEC

**Temps moyen de réalisation :** 3-4 heures

**Prochaine étape :** Exercice 5 - Sécurité avancée, performance et monitoring ! [RAPIDE]

---

Veux-tu que je continue avec l'exercice 5 (dernier exercice) ?

# [ROUGE] EXERCICE 5 : SÉCURITÉ AVANCÉE, PERFORMANCE ET MONITORING

## [LISTE] ÉNONCÉ

### Contexte professionnel

Ton infrastructure DNS est maintenant opérationnelle avec :
- [OK] Serveur DNS master/slave (haute disponibilité)
- [OK] DNS dynamique (DDNS) avec DHCP
- [OK] DNSSEC (sécurité cryptographique)

Le directeur IT te convoque : **"Notre DNS est critique pour l'entreprise. Je veux :**
1. **Le protéger contre les attaques DDoS et l'abus**
2. **Bloquer les domaines malveillants**
3. **Optimiser les performances**
4. **Monitorer en temps réel**
5. **Avoir des alertes automatiques en cas de problème"**

Ta mission : Transformer ton serveur DNS en une infrastructure **production-grade** sécurisée, performante et monitorée.

### Cahier des charges

Mettre en place :
- **Rate Limiting** (RRL) contre les attaques DDoS
- **Response Policy Zones** (RPZ) pour bloquer les domaines malveillants
- **ACLs avancées** et geo-blocking
- **Hardening** complet de BIND
- **Tuning de performance** (cache, workers, etc.)
- **Monitoring** avec Prometheus + Grafana
- **Logging centralisé** et analysé
- **Alertes automatiques**

### Objectifs techniques

- Implémenter RRL (Response Rate Limiting)
- Configurer RPZ pour le blocage DNS
- Créer des ACLs géographiques
- Durcir la sécurité de BIND
- Optimiser les paramètres de performance
- Installer et configurer Prometheus + BIND Exporter
- Créer des dashboards Grafana
- Mettre en place des alertes
- Configurer le logging avancé

### Contraintes

- Serveur BIND9 fonctionnel
- Serveur de monitoring (peut être séparé ou sur le même host)
- Listes de blocage à jour (malware, phishing, etc.)
- Temps estimé : 4-5 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Protéger DNS contre les attaques DDoS avec RRL
- [OK] Bloquer des domaines malveillants avec RPZ
- [OK] Créer des ACLs avancées
- [OK] Durcir la sécurité de BIND (hardening)
- [OK] Optimiser les performances DNS
- [OK] Monitorer DNS avec Prometheus/Grafana
- [OK] Créer des alertes automatiques
- [OK] Analyser les logs DNS
- [OK] Diagnostiquer les problèmes de performance

---

## [DOCS] PRÉREQUIS

- Exercices 1, 2, 3 et 4 terminés
- Serveur BIND9 opérationnel
- Compréhension des attaques réseau (DDoS, DNS amplification)
- Notions de monitoring

---

## [GUIDE] RAPPEL THÉORIQUE

### Attaque 1 : DNS Amplification (DDoS)

**Scénario :**

```
1. Attaquant envoie des requêtes DNS avec IP SOURCE USURPÉE (spoofed)
   Source: IP de la VICTIME
   Destination: Serveurs DNS publics
   Requête: ANY example.com (retourne TOUS les enregistrements)

2. Serveurs DNS répondent à l'IP usurpée
   Requête: 60 octets
   Réponse: 3000 octets (amplification x50)

3. La VICTIME reçoit des milliers de réponses DNS géantes
   -> Saturation de la bande passante
   -> Déni de service (DoS)

Exemple réel :
- Attaque de 300 Gbps contre Spamhaus (2013)
- Utilisation de DNS amplification
```

**Pourquoi DNS est utilisé pour l'amplification ?**

```
UDP = Pas de connexion établie
-> Facile d'usurper l'IP source

Requête petite, réponse grande
-> Facteur d'amplification élevé

Serveurs DNS ouverts (open resolvers)
-> Répondent à n'importe qui
-> Exploitables comme "réflecteurs"
```

---

### Solution 1 : Response Rate Limiting (RRL)

**RRL = Limitation du taux de réponses**

**Principe :**

```
1. BIND compte le nombre de réponses identiques/similaires
2. Si un même client (IP) fait trop de requêtes similaires
3. BIND limite les réponses :
   - Soit en les DROP (ignorées)
   - Soit en envoyant un SLIP (1 réponse sur N)

Exemple :
Client A (192.168.1.50) :
- Envoie 100 requêtes pour www.example.com en 1 seconde
- RRL détecte : Taux anormal
- BIND limite :
  - Répond aux 5 premières
  - DROP les 95 suivantes
  
Résultat :
[OK] Clients légitimes : Peu impactés (1-2 requêtes/sec)
[OK] Attaquants : Limités (pas d'amplification massive)
```

**Métriques RRL :**

```
responses-per-second : Nombre max de réponses identiques/sec
window : Fenêtre de temps pour compter (secondes)
slip : 1 réponse sur N (le reste est droppé)
qps-scale : Facteur d'échelle basé sur le QPS global
```

---

### Attaque 2 : Domaines malveillants

**Scénario :**

```
1. Malware infecte un poste utilisateur
2. Malware tente de contacter son serveur C&C (Command & Control)
   -> Requête DNS : malware-cnc.evil.com
3. DNS résout normalement
   -> Retourne l'IP du serveur malveillant
4. Malware communique avec le serveur
   -> Exfiltration de données
   -> Réception de commandes
   -> Propagation
```

**Types de domaines malveillants :**

```
- Malware C&C (Command & Control)
- Phishing (usurpation de sites légitimes)
- Ransomware (chiffrement + demande de rançon)
- Botnets (réseaux de machines infectées)
- Typosquatting (goooogle.com, faacebook.com)
- Cryptojacking (minage de cryptomonnaie)
```

---

### Solution 2 : Response Policy Zones (RPZ)

**RPZ = "Firewall DNS"**

**Principe :**

```
RPZ = Zone DNS spéciale contenant des politiques de filtrage

Format :
malware-cnc.evil.com  IN  CNAME  .
phishing-site.bad     IN  CNAME  .
ads-tracker.com       IN  CNAME  rpz-drop.

Actions possibles :
1. NXDOMAIN : "Domaine n'existe pas"
2. NODATA : Réponse vide
3. DROP : Pas de réponse (timeout)
4. Redirection : CNAME vers page de blocage
5. IP alternative : A 127.0.0.1

Processus :
1. Client demande : malware-cnc.evil.com
2. BIND consulte la RPZ AVANT la résolution normale
3. RPZ contient : malware-cnc.evil.com -> NXDOMAIN
4. BIND retourne : NXDOMAIN
5. Le malware ne peut pas contacter le C&C
```

**Sources de listes RPZ :**

```
- Abuse.ch (malware, botnet)
- Spamhaus DROP/EDROP (spam, malware)
- URLhaus (malware URLs)
- PhishTank (phishing)
- StevenBlack hosts (ads, malware)
```

---

### Attaque 3 : Reconnaissance et énumération

**Scénario :**

```
1. Attaquant scanne ton réseau DNS
   - Requêtes AXFR (transfert de zone)
   - Requêtes CHAOS (version.bind, hostname.bind)
   - Énumération de tous les enregistrements

2. Attaquant collecte des informations :
   - Version de BIND -> Recherche d'exploits
   - Liste complète des serveurs internes
   - Architecture réseau

3. Attaquant utilise ces infos pour :
   - Cibler des vulnérabilités spécifiques
   - Planifier une attaque
```

---

### Solution 3 : Hardening (durcissement)

**Mesures de sécurité :**

```
1. Cacher la version de BIND
   version "DNS Server";

2. Interdire les transferts de zone non autorisés
   allow-transfer { none; };

3. Désactiver la récursion pour les clients non autorisés
   allow-recursion { localhost; trusted-nets; };

4. Limiter les requêtes CHAOS
   allow-query-cache { localhost; };

5. Séparer résolveur et autoritaire
   Serveur autoritaire : Pas de récursion
   Serveur résolveur : Pas de zones autoritaires publiques

6. Chroot et utilisateur dédié
   Isolation du processus BIND

7. Pare-feu (iptables/ufw)
   Limiter les connexions entrantes
```

---

### Performance : Cache et optimisation

**Problèmes de performance :**

```
1. Serveur lent -> Timeouts clients
2. Cache insuffisant -> Trop de requêtes upstream
3. Workers insuffisants -> Saturation CPU
4. Mémoire saturée -> Crash
```

**Optimisations :**

```
1. Cache sizing
   max-cache-size : Taille max du cache
   max-cache-ttl : TTL max en cache

2. Workers
   -n <nombre> : Threads workers (1 par CPU)

3. Query optimization
   max-clients-per-query : Limite clients par requête
   clients-per-query : Clients par requête récursive

4. Logging
   Réduire le logging en production (performance)
```

---

## [OK] SOLUTION COMPLÈTE

### PARTIE 1 : RESPONSE RATE LIMITING (RRL)

**ÉTAPE 1 : Configurer RRL**

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter la section RRL (avant le `};` final) :**

```bind
// ═══════════════════════════════════════════════════════════════
// RESPONSE RATE LIMITING (ANTI-DDOS)
// ═══════════════════════════════════════════════════════════════

rate-limit {
    
    /*
     * rate-limit :
     * Active la limitation du taux de réponses (RRL)
     * 
     * Objectif :
     * Protéger contre les attaques par amplification DNS
     * 
     * Principe :
     * Si un client fait trop de requêtes similaires
     * -> BIND limite les réponses
     */
    
    // ───────────────────────────────────────────────────────────
    // PARAMÈTRES DE BASE
    // ───────────────────────────────────────────────────────────
    
    responses-per-second 5;
    
    /*
     * responses-per-second :
     * Nombre maximum de réponses IDENTIQUES par seconde
     * vers un même client (IP)
     * 
     * 5 = Maximum 5 réponses identiques/seconde
     * 
     * Exemple :
     * Client 192.168.1.50 fait 100 requêtes pour www.example.com
     * -> BIND répond aux 5 premières
     * -> BIND limite les 95 suivantes
     * 
     * Qu'est-ce qu'une réponse "identique" ?
     * - Même nom (QNAME)
     * - Même type (A, MX, etc.)
     * - Même réponse (ANSWER section)
     * 
     * Pourquoi 5 ?
     * - Client légitime : Rarement > 5 requêtes identiques/sec
     * - Attaquant : Fait des milliers de requêtes/sec
     * 
     * Recommandations :
     * - Résolveur public : 5-10 (strict)
     * - Résolveur interne : 10-20 (plus permissif)
     * - Serveur autoritaire : 5 (très strict)
     */
    
    window 15;
    
    /*
     * window :
     * Fenêtre de temps (en secondes) pour compter les réponses
     * 
     * 15 secondes = Fenêtre glissante de 15 secondes
     * 
     * Fonctionnement :
     * BIND compte les réponses dans une fenêtre de 15 secondes
     * 
     * Exemple :
     * T=0s  : Client fait 5 requêtes -> Réponses OK
     * T=1s  : Client fait 5 requêtes -> Limitées (total 10 > 5)
     * T=15s : Fenêtre se réinitialise -> Client peut refaire 5 requêtes
     * 
     * Pourquoi 15 secondes ?
     * - Compromis entre détection et faux positifs
     * - Plus court (5s) : Détection rapide, mais risque de bloquer clients légitimes
     * - Plus long (60s) : Moins de faux positifs, mais attaque plus longue avant détection
     * 
     * Recommandation : 10-15 secondes
     */
    
    // ───────────────────────────────────────────────────────────
    // SLIP (TRUNCATED RESPONSES)
    // ───────────────────────────────────────────────────────────
    
    slip 2;
    
    /*
     * slip :
     * Ratio de "glissement" (1 sur N)
     * 
     * Au lieu de DROP toutes les réponses limitées,
     * BIND envoie 1 réponse TRONQUÉE (TC=1) sur N
     * 
     * slip 2 = 1 réponse sur 2 est TRONQUÉE, les autres sont DROPPÉES
     * 
     * Réponse TRONQUÉE (TC=1) :
     * - Flag TC (Truncated) = 1
     * - Signale au client : "Réponse trop grande, utilise TCP"
     * - Le client intelligent retry en TCP
     * 
     * Pourquoi SLIP ?
     * 
     * Sans SLIP (slip 0) :
     * - Toutes les réponses limitées sont DROPPÉES
     * - Client attend timeout
     * - Mauvaise expérience utilisateur
     * 
     * Avec SLIP (slip 2) :
     * - 1 réponse sur 2 est TRONQUÉE
     * - Client sait qu'il doit retry en TCP
     * - Meilleure expérience (pas de timeout)
     * 
     * Compromis :
     * - slip 1 : Toutes les réponses limitées sont TC (pas de drop)
     *            [ATTENTION] Permet quand même une certaine amplification
     * 
     * - slip 2 : 50% TC, 50% DROP
     *            [OK] Équilibre entre UX et protection
     * 
     * - slip 10 : 10% TC, 90% DROP
     *             [OK] Protection maximale
     *             [ATTENTION] Clients légitimes peuvent être impactés
     * 
     * Recommandation : slip 2-5
     */
    
    // ───────────────────────────────────────────────────────────
    // TYPES DE RÉPONSES À LIMITER
    // ───────────────────────────────────────────────────────────
    
    errors-per-second 5;
    
    /*
     * errors-per-second :
     * Limite les réponses d'ERREUR (NXDOMAIN, SERVFAIL, REFUSED)
     * 
     * 5 = Maximum 5 erreurs/seconde vers un même client
     * 
     * Pourquoi limiter les erreurs ?
     * 
     * Attaque NXDOMAIN flood :
     * 1. Attaquant génère des noms aléatoires
     *    random1.example.com, random2.example.com, ...
     * 2. Serveur répond : NXDOMAIN
     * 3. Pas de cache possible (noms uniques)
     * 4. Serveur surchargé
     * 
     * Avec errors-per-second :
     * - BIND limite les NXDOMAIN
     * - Attaque atténuée
     * 
     * Recommandation : Identique à responses-per-second
     */
    
    nxdomains-per-second 5;
    
    /*
     * nxdomains-per-second :
     * Limite SPÉCIFIQUEMENT les réponses NXDOMAIN
     * 
     * Identique à errors-per-second mais SEULEMENT pour NXDOMAIN
     * 
     * Utile pour se protéger contre :
     * - NXDOMAIN flood
     * - DNS tunneling (exfiltration de données via DNS)
     * 
     * Recommandation : 5-10
     */
    
    // ───────────────────────────────────────────────────────────
    // EXEMPTIONS (WHITELIST)
    // ───────────────────────────────────────────────────────────
    
    exempt-clients { localhost; 192.168.1.0/24; };
    
    /*
     * exempt-clients :
     * Liste des clients EXEMPTÉS du RRL
     * 
     * Ces clients ne seront JAMAIS limités
     * 
     * Pourquoi exempter ?
     * 
     * 1. Serveurs internes critiques
     *    - Serveurs de monitoring (Prometheus)
     *    - Serveurs d'application (haute fréquence de requêtes)
     * 
     * 2. Réseau de confiance
     *    - Réseau interne (192.168.1.0/24)
     *    - Pas de risque d'attaque depuis l'interne
     * 
     * 3. Localhost
     *    - Requêtes locales (dig, nslookup)
     *    - Tests et debug
     * 
     * [ATTENTION] ATTENTION :
     * Ne PAS exempter des IPs publiques
     * Ne PAS exempter de larges plages (/8, /16)
     * 
     * Format :
     * exempt-clients { IP; IP/CIDR; ACL-name; };
     */
    
    // ───────────────────────────────────────────────────────────
    // QPS SCALE (AUTO-TUNING)
    // ───────────────────────────────────────────────────────────
    
    qps-scale 250;
    
    /*
     * qps-scale :
     * Facteur d'échelle basé sur le QPS (Queries Per Second) GLOBAL
     * 
     * 250 = Seuil de QPS pour activer le scaling
     * 
     * Fonctionnement :
     * 
     * Si QPS global < qps-scale (250) :
     * -> RRL utilise les limites NORMALES
     *   (responses-per-second = 5)
     * 
     * Si QPS global > qps-scale (250) :
     * -> RRL ajuste AUTOMATIQUEMENT les limites
     * 
     * Formule :
     * limite_ajustée = limite_base × (qps-scale / qps_actuel)
     * 
     * Exemple :
     * QPS actuel = 500 (serveur sous charge)
     * qps-scale = 250
     * responses-per-second = 5
     * 
     * Limite ajustée = 5 × (250 / 500) = 2.5 ≈ 2
     * 
     * Résultat :
     * - Serveur sous forte charge -> Limites PLUS STRICTES
     * - Protection renforcée automatiquement
     * - Préserve les ressources
     * 
     * Pourquoi QPS scale ?
     * 
     * Scénario 1 : Serveur tranquille (100 QPS)
     * - Pas besoin de limites strictes
     * - Clients peuvent faire 5 req/sec
     * 
     * Scénario 2 : Serveur sous attaque (10 000 QPS)
     * - Besoin de protection maximale
     * - Limites réduites automatiquement à 0.1 req/sec
     * - Attaque atténuée
     * 
     * Recommandations :
     * - Petit serveur (<1000 QPS normal) : qps-scale 100-250
     * - Serveur moyen : qps-scale 500-1000
     * - Gros serveur : qps-scale 2000-5000
     */
    
    // ───────────────────────────────────────────────────────────
    // LOGGING RRL
    // ───────────────────────────────────────────────────────────
    
    log-only no;
    
    /*
     * log-only :
     * Mode LOG SEULEMENT (sans réellement limiter)
     * 
     * no = RRL actif (limite réellement)
     * yes = RRL en mode observation (logs uniquement)
     * 
     * Utilité de "yes" :
     * - Phase de test
     * - Voir combien de requêtes seraient limitées
     * - Ajuster les paramètres sans impacter les clients
     * 
     * Processus recommandé :
     * 1. log-only yes -> Observer pendant 1 semaine
     * 2. Analyser les logs : Combien de faux positifs ?
     * 3. Ajuster responses-per-second si nécessaire
     * 4. log-only no -> Activer réellement
     * 
     * Recommandation :
     * - Production : log-only no (actif)
     * - Test : log-only yes (observation)
     */
    
    // ───────────────────────────────────────────────────────────
    // PARAMÈTRES AVANCÉS (OPTIONNELS)
    // ───────────────────────────────────────────────────────────
    
    max-table-size 20000;
    
    /*
     * max-table-size :
     * Taille maximale de la table de tracking RRL
     * 
     * 20000 = Peut tracker jusqu'à 20000 entrées simultanées
     * 
     * Une entrée = Une combinaison (IP client, QNAME, QTYPE)
     * 
     * Exemple :
     * Client 192.168.1.50 demande :
     * - www.example.com A
     * - mail.example.com MX
     * -> 2 entrées dans la table
     * 
     * Mémoire utilisée :
     * ~64 octets par entrée
     * 20000 entrées = ~1.25 MB
     * 
     * Recommandations :
     * - Petit serveur : 10000
     * - Serveur moyen : 20000-50000
     * - Gros serveur : 100000+
     * 
     * [ATTENTION] Si la table est pleine :
     * - Anciennes entrées expulsées (FIFO)
     * - Pas d'impact majeur (fenêtre glissante)
     */
    
    min-table-size 500;
    
    /*
     * min-table-size :
     * Taille minimale de la table (optimisation mémoire)
     * 
     * 500 = Allouer au moins de la mémoire pour 500 entrées
     * 
     * Évite les réallocations fréquentes si peu de trafic
     * 
     * Recommandation : 500-1000
     */
};
```

**Sauvegarde.**

---

**ÉTAPE 2 : Vérifier et recharger**

```bash
# Vérifier la syntaxe
sudo named-checkconf

# Recharger BIND
sudo rndc reload
```

---

**ÉTAPE 3 : Tester RRL**

**Simuler une attaque (depuis un client) :**

```bash
# Faire 20 requêtes rapides
for i in {1..20}; do dig @192.168.1.100 www.monentreprise.local; done
```

**Vérifier les logs BIND :**

```bash
sudo journalctl -u bind9 -n 50 | grep "rate limit"
```

**Tu devrais voir :**

```
Dec 16 17:00:00 ns1 named[12345]: client 192.168.1.50#54321 (www.monentreprise.local): rate limit drop
Dec 16 17:00:00 ns1 named[12345]: client 192.168.1.50#54322 (www.monentreprise.local): rate limit slip
```

**`rate limit drop` = Réponse droppée**
**`rate limit slip` = Réponse tronquée (TC=1)**

**[OK] RRL fonctionne !**

---

### PARTIE 2 : RESPONSE POLICY ZONES (RPZ)

**ÉTAPE 1 : Télécharger une liste de blocage**

**On va utiliser la liste de Steven Black (ads + malware) :**

```bash
# Créer un dossier pour les RPZ
sudo mkdir -p /etc/bind/rpz

# Télécharger la liste
sudo wget -O /tmp/hosts https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

# Convertir le format hosts en zone DNS
sudo python3 <<'EOF' > /etc/bind/rpz/db.rpz.blocked
# Script Python pour convertir hosts -> RPZ
import re

print("; RPZ Zone - Blocked domains")
print("$TTL 3600")
print("@  IN  SOA  localhost. root.localhost. (")
print("        2024121601  ; Serial")
print("        3600        ; Refresh")
print("        1800        ; Retry")
print("        604800      ; Expire")
print("        86400 )     ; Minimum")
print("@  IN  NS  localhost.")
print()

# Lire le fichier hosts
with open('/tmp/hosts', 'r') as f:
    for line in f:
        line = line.strip()
        # Ignorer commentaires et localhost
        if line.startswith('#') or not line or '127.0.0.1' not in line:
            continue
        # Extraire le domaine
        parts = line.split()
        if len(parts) >= 2:
            domain = parts[1]
            # Format RPZ : domaine CNAME .
            # CNAME . = NXDOMAIN
            print(f"{domain}  IN  CNAME  .")
EOF
```

**Le fichier `/etc/bind/rpz/db.rpz.blocked` contient maintenant des milliers de domaines malveillants.**

---

**ÉTAPE 2 : Configurer la RPZ**

**Éditer `/etc/bind/named.conf.local` :**

```bash
sudo nano /etc/bind/named.conf.local
```

**Ajouter (après les autres zones) :**

```bind
// ═══════════════════════════════════════════════════════════════
// RESPONSE POLICY ZONE (RPZ) - BLOCAGE DNS
// ═══════════════════════════════════════════════════════════════

// ───────────────────────────────────────────────────────────────
// ZONE RPZ
// ───────────────────────────────────────────────────────────────

zone "rpz.blocked" {
    type master;
    file "/etc/bind/rpz/db.rpz.blocked";
    allow-query { none; };
    
    /*
     * zone "rpz.blocked" :
     * Zone RPZ (nom arbitraire)
     * 
     * type master :
     * Serveur master pour cette zone
     * 
     * file :
     * Fichier contenant la liste de blocage
     * 
     * allow-query { none; } :
     * [ATTENTION] IMPORTANT : Empêcher les requêtes directes vers la RPZ
     * 
     * La RPZ est utilisée EN INTERNE par BIND
     * Les clients ne doivent PAS pouvoir interroger directement rpz.blocked
     * 
     * Sinon :
     * - Attaquant peut énumérer tous les domaines bloqués
     * - Fuite d'informations
     */
};

/*
 * ═══════════════════════════════════════════════════════════════
 * EXPLICATION DÉTAILLÉE : RESPONSE POLICY ZONES (RPZ)
 * ═══════════════════════════════════════════════════════════════
 * 
 * Qu'est-ce qu'une RPZ ?
 * 
 * RPZ = Zone DNS spéciale utilisée comme "firewall DNS"
 * 
 * Processus de résolution AVEC RPZ :
 * 
 * 1. Client demande : ads-tracker.com
 * 
 * 2. BIND consulte la RPZ EN PREMIER (avant résolution normale)
 * 
 * 3. BIND cherche dans db.rpz.blocked :
 *    ads-tracker.com  IN  CNAME  .
 *    -> Trouvé !
 * 
 * 4. BIND applique la politique :
 *    CNAME . = NXDOMAIN
 * 
 * 5. BIND retourne au client : NXDOMAIN
 *    (Le domaine n'existe pas)
 * 
 * 6. Le navigateur/application ne peut pas joindre ads-tracker.com
 * 
 * 7. [OK] Publicité/malware bloqué !
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * Actions RPZ possibles :
 * 
 * 1. NXDOMAIN (domaine n'existe pas) :
 *    ads-tracker.com  IN  CNAME  .
 * 
 * 2. NODATA (domaine existe mais pas d'enregistrement) :
 *    ads-tracker.com  IN  CNAME  *.
 * 
 * 3. Redirection vers IP locale :
 *    ads-tracker.com  IN  A  127.0.0.1
 * 
 * 4. Redirection vers page de blocage :
 *    ads-tracker.com  IN  CNAME  blocked.monentreprise.local.
 * 
 * 5. DROP (pas de réponse, timeout) :
 *    ads-tracker.com  IN  CNAME  rpz-drop.
 * 
 * 6. PASSTHRU (ne pas appliquer de politique, résolution normale) :
 *    trusted-ads.com  IN  CNAME  rpz-passthru.
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * Types de blocage RPZ :
 * 
 * 1. QNAME (nom de domaine) :
 *    ads-tracker.com  IN  CNAME  .
 *    -> Bloque ads-tracker.com
 * 
 * 2. IP (résolution) :
 *    32.1.2.3.4.rpz-ip  IN  CNAME  .
 *    -> Bloque toute résolution vers 1.2.3.4
 * 
 * 3. NSDNAME (serveur de noms) :
 *    evil-dns.com.rpz-nsdname  IN  CNAME  .
 *    -> Bloque toutes les zones hébergées par evil-dns.com
 * 
 * 4. Client IP :
 *    32.192.168.1.50.rpz-client-ip  IN  CNAME  rpz-drop.
 *    -> Bloque toutes les requêtes de 192.168.1.50
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * Avantages RPZ :
 * 
 * [OK] Blocage centralisé (tous les clients protégés)
 * [OK] Pas besoin de modifier les applications
 * [OK] Fonctionne pour tous les protocoles (HTTP, HTTPS, FTP, etc.)
 * [OK] Mise à jour facile (modifier la zone RPZ)
 * [OK] Logs centralisés (qui essaye d'accéder à quoi)
 * 
 * Inconvénients :
 * 
 * [ATTENTION] Peut être contourné (VPN, DNS alternatif)
 * [ATTENTION] Nécessite maintenance (listes à jour)
 * [ATTENTION] Risque de faux positifs (bloquer des domaines légitimes)
 * 
 * ───────────────────────────────────────────────────────────────
 * 
 * Cas d'usage :
 * 
 * 1. Entreprise :
 *    - Bloquer malware, phishing
 *    - Bloquer réseaux sociaux (productivité)
 *    - Bloquer sites de streaming (bande passante)
 * 
 * 2. FAI / ISP :
 *    - Bloquer malware, botnets
 *    - Conformité légale (contenus illégaux)
 * 
 * 3. Famille :
 *    - Contrôle parental
 *    - Bloquer contenus adultes
 *    - Bloquer publicités
 * 
 * ═══════════════════════════════════════════════════════════════
 */
```

**Sauvegarde.**

---

**ÉTAPE 3 : Activer la RPZ dans les options**

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter (dans le bloc `options {`) :**

```bind
    // ───────────────────────────────────────────────────────────
    // ACTIVATION DES RESPONSE POLICY ZONES
    // ───────────────────────────────────────────────────────────
    
    response-policy {
        zone "rpz.blocked" policy given;
    };
    
    /*
     * response-policy :
     * Active les RPZ
     * 
     * Format :
     * response-policy {
     *     zone "<zone-name>" policy <action> [options];
     * };
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * Paramètres :
     * 
     * zone "rpz.blocked" :
     * Nom de la zone RPZ (doit correspondre à la zone définie)
     * 
     * policy given :
     * Action par défaut = Utiliser la politique définie dans la zone
     * 
     * Autres actions possibles :
     * 
     * - policy given :
     *   Utilise l'action dans la RPZ (CNAME ., A 127.0.0.1, etc.)
     * 
     * - policy disabled :
     *   RPZ chargée mais désactivée (pour tests)
     * 
     * - policy passthru :
     *   RPZ consultée mais pas appliquée (logs seulement)
     * 
     * - policy drop :
     *   Tous les domaines matchés -> DROP (timeout)
     * 
     * - policy nxdomain :
     *   Tous les domaines matchés -> NXDOMAIN
     * 
     * - policy nodata :
     *   Tous les domaines matchés -> NODATA
     * 
     * - policy cname <domain> :
     *   Tous les domaines matchés -> CNAME vers <domain>
     *   Exemple : policy cname blocked.example.com.
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * Options avancées :
     * 
     * recursive-only yes/no :
     * Appliquer la RPZ seulement aux requêtes récursives
     * 
     * response-policy {
     *     zone "rpz.blocked" recursive-only yes;
     * };
     * 
     * Utile si :
     * - Serveur est à la fois autoritaire et résolveur
     * - On ne veut pas filtrer les zones autoritaires
     * 
     * max-policy-ttl <seconds> :
     * TTL maximum pour les réponses RPZ
     * 
     * response-policy {
     *     zone "rpz.blocked" max-policy-ttl 300;
     * };
     * 
     * Utile pour :
     * - Éviter que les blocages soient cachés trop longtemps
     * - Si erreur (faux positif), correction rapide
     * 
     * break-dnssec yes/no :
     * Casser DNSSEC pour les domaines bloqués
     * 
     * response-policy {
     *     zone "rpz.blocked" break-dnssec yes;
     * };
     * 
     * Par défaut : yes (casse DNSSEC)
     * 
     * Pourquoi ?
     * - Si domaine est signé DNSSEC
     * - Et RPZ retourne NXDOMAIN (falsification)
     * - Validation DNSSEC échoue -> SERVFAIL
     * - Client ne voit pas le blocage
     * 
     * Avec break-dnssec yes :
     * - BIND désactive DNSSEC pour les domaines bloqués
     * - Client reçoit NXDOMAIN (sans signature)
     * 
     * [ATTENTION] Casser DNSSEC = Réduire la sécurité
     * Mais nécessaire pour que les RPZ fonctionnent
     * 
     * ───────────────────────────────────────────────────────────
     * 
     * Plusieurs RPZ :
     * 
     * response-policy {
     *     zone "rpz.malware" policy given;
     *     zone "rpz.ads" policy given;
     *     zone "rpz.phishing" policy given;
     * };
     * 
     * Ordre d'application :
     * BIND consulte les RPZ dans l'ordre défini
     * La PREMIÈRE correspondance est appliquée
     * 
     * Exemple :
     * 1. rpz.malware bloque ads-tracker.com
     * 2. rpz.ads bloque AUSSI ads-tracker.com
     * -> Seule rpz.malware est appliquée (première)
     * 
     * Recommandation :
     * Ordre de priorité décroissant :
     * 1. Malware (plus critique)
     * 2. Phishing
     * 3. Ads
     * 
     * ═══════════════════════════════════════════════════════════
     */
```

**Sauvegarde.**

---

**ÉTAPE 4 : Vérifier et recharger**

```bash
# Vérifier la syntaxe de la zone RPZ
sudo named-checkzone rpz.blocked /etc/bind/rpz/db.rpz.blocked

# Vérifier la config globale
sudo named-checkconf

# Recharger BIND
sudo rndc reload
```

---

**ÉTAPE 5 : Tester le blocage RPZ**

**Choisir un domaine dans la liste (exemple : doubleclick.net) :**

```bash
grep doubleclick /etc/bind/rpz/db.rpz.blocked
```

**Résultat :**

```
doubleclick.net  IN  CNAME  .
```

---

**Tester la résolution :**

```bash
dig @localhost doubleclick.net
```

**Résultat attendu :**

```
;; status: NXDOMAIN
```

**[OK] Domaine bloqué par RPZ !**

---

**Vérifier les logs :**

```bash
sudo journalctl -u bind9 -n 20 | grep rpz
```

**Tu devrais voir :**

```
Dec 16 17:30:00 ns1 named[12345]: client 127.0.0.1#54321 (doubleclick.net): rpz QNAME NXDOMAIN rewrite doubleclick.net via rpz.blocked
```

**`rpz QNAME NXDOMAIN rewrite` = RPZ a bloqué la requête**

---

**Créer une page de blocage (optionnel) :**

**Au lieu de NXDOMAIN, rediriger vers une page explicative :**

**1. Créer un enregistrement pour la page de blocage :**

```bash
sudo nano /var/lib/bind/db.monentreprise.local
```

**Ajouter :**

```bind
blocked  IN  A  192.168.1.100
```

**Incrémenter le serial, sauvegarder.**

---

**2. Modifier la RPZ pour rediriger :**

```bash
sudo nano /etc/bind/rpz/db.rpz.blocked
```

**Remplacer `CNAME .` par `CNAME blocked.monentreprise.local.` :**

```bind
doubleclick.net  IN  CNAME  blocked.monentreprise.local.
```

---

**3. Installer un serveur web pour afficher la page :**

```bash
sudo apt install nginx -y
```

**Créer une page de blocage :**

```bash
sudo nano /var/www/html/blocked.html
```

**Contenu :**

```html
<!DOCTYPE html>
<html>
<head>
    <title>Accès bloqué</title>
</head>
<body>
    <h1>Accès bloqué</h1>
    <p>Ce site a été bloqué par la politique de sécurité de l'entreprise.</p>
    <p>Raison : Malware / Publicité / Phishing</p>
    <p>Contactez le support IT si vous pensez qu'il s'agit d'une erreur.</p>
</body>
</html>
```

---

**4. Configurer Nginx pour toutes les requêtes :**

```bash
sudo nano /etc/nginx/sites-available/default
```

**Remplacer par :**

```nginx
server {
    listen 80 default_server;
    server_name _;
    
    location / {
        root /var/www/html;
        try_files /blocked.html =404;
    }
}
```

**Redémarrer Nginx :**

```bash
sudo systemctl restart nginx
```

---

**5. Tester :**

```bash
curl http://doubleclick.net
```

**Résultat :**

```html
<h1>Accès bloqué</h1>
...
```

**[OK] Page de blocage affichée !**

---

### PARTIE 3 : ACLS AVANCÉES ET HARDENING

**ÉTAPE 1 : Créer des ACLs géographiques (concept)**

**Pour bloquer des pays entiers (nécessite GeoIP) :**

```bash
# Installer GeoIP
sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin -y
```

**Télécharger la base GeoIP (nécessite compte MaxMind gratuit) :**

```bash
# S'inscrire sur maxmind.com
# Télécharger GeoLite2-Country.mmdb
sudo mkdir -p /usr/share/GeoIP
sudo mv GeoLite2-Country.mmdb /usr/share/GeoIP/
```

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter :**

```bind
geoip-directory "/usr/share/GeoIP";

acl "blocked-countries" {
    geoip country CN;  // Chine
    geoip country RU;  // Russie
    geoip country KP;  // Corée du Nord
};

options {
    ...
    allow-query { !blocked-countries; any; };
    ...
};

/*
 * ACL géographique :
 * Bloquer les requêtes depuis certains pays
 * 
 * Utile pour :
 * - Réduire le risque d'attaques (certaines régions à risque)
 * - Conformité réglementaire (RGPD, etc.)
 * 
 * [ATTENTION] Attention aux faux positifs :
 * - VPN, proxies
 * - Employés en déplacement
 */
```

---

**ÉTAPE 2 : Hardening complet**

**Éditer `/etc/bind/named.conf.options` :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter/modifier :**

```bind
options {
    directory "/var/cache/bind";
    
    // ───────────────────────────────────────────────────────────
    // SÉCURITÉ : MASQUER LES INFORMATIONS
    // ───────────────────────────────────────────────────────────
    
    version "DNS Server";
    hostname "DNS Server";
    
    /*
     * version et hostname :
     * Masquer la version réelle de BIND
     * 
     * Par défaut :
     * dig @server version.bind txt chaos
     * -> Retourne : "9.18.28-Ubuntu"
     * 
     * Avec version "DNS Server" :
     * -> Retourne : "DNS Server"
     * 
     * Pourquoi masquer ?
     * - Attaquant ne connaît pas la version exacte
     * - Plus difficile de trouver des exploits ciblés
     * 
     * [ATTENTION] Security by obscurity (sécurité par l'obscurité)
     * Ce n'est PAS une vraie sécurité
     * Mais ça complique la tâche des attaquants
     */
    
    server-id none;
    
    /*
     * server-id :
     * Masquer l'identifiant du serveur
     * 
     * none = Ne pas répondre aux requêtes id.server
     */
    
    // ───────────────────────────────────────────────────────────
    // SÉCURITÉ : LIMITER LES ACCÈS
    // ───────────────────────────────────────────────────────────
    
    allow-query { localhost; 192.168.1.0/24; };
    allow-recursion { localhost; 192.168.1.0/24; };
    allow-query-cache { localhost; 192.168.1.0/24; };
    allow-transfer { none; };
    
    /*
     * Principe du moindre privilège :
     * N'autoriser QUE ce qui est nécessaire
     * 
     * allow-query :
     * Qui peut faire des requêtes DNS normales
     * -> Seulement le réseau interne
     * 
     * allow-recursion :
     * Qui peut faire des requêtes récursives
     * -> Seulement le réseau interne
     * 
     * [ATTENTION] IMPORTANT :
     * Un serveur DNS AUTORITAIRE ne devrait PAS faire de récursion
     * Un serveur DNS RÉSOLVEUR devrait limiter la récursion
     * 
     * allow-query-cache :
     * Qui peut accéder au cache
     * -> Seulement le réseau interne
     * 
     * allow-transfer :
     * Qui peut faire des transferts de zone
     * -> Personne par défaut (configuré zone par zone)
     */
    
    // ───────────────────────────────────────────────────────────
    // SÉCURITÉ : DÉSACTIVER LES FONCTIONNALITÉS INUTILES
    // ───────────────────────────────────────────────────────────
    
    empty-zones-enable no;
    
    /*
     * empty-zones-enable :
     * Désactiver les zones vides automatiques
     * 
     * BIND crée automatiquement des zones pour :
     * - localhost
     * - 127.in-addr.arpa
     * - Etc.
     * 
     * Si tu n'en as pas besoin -> Désactiver
     * Réduit la surface d'attaque
     */
    
    // ───────────────────────────────────────────────────────────
    // PERFORMANCE : OPTIMISATIONS
    // ───────────────────────────────────────────────────────────
    
    max-cache-size 512M;
    
    /*
     * max-cache-size :
     * Taille maximale du cache
     * 
     * 512M = 512 Mégaoctets
     * 
     * Recommandations :
     * - Petit serveur (<100 clients) : 256M
     * - Serveur moyen : 512M - 1G
     * - Gros serveur : 2G - 4G
     * 
     * [ATTENTION] Ne pas mettre unlimited :
     * Risque de saturation mémoire
     */
    
    max-cache-ttl 86400;
    
    /*
     * max-cache-ttl :
     * TTL maximum en cache
     * 
     * 86400 = 1 jour
     * 
     * Même si un enregistrement a TTL 604800 (7 jours)
     * BIND le cache maximum 1 jour
     * 
     * Avantages :
     * - Enregistrements obsolètes moins longtemps
     * - Changements DNS propagés plus vite
     */
    
    max-ncache-ttl 3600;
    
    /*
     * max-ncache-ttl :
     * TTL maximum pour le cache NÉGATIF (NXDOMAIN)
     * 
     * 3600 = 1 heure
     * 
     * Cache négatif :
     * Si un domaine n'existe pas (NXDOMAIN)
     * BIND met en cache cette information
     * 
     * Évite de redemander au serveur autoritaire
     */
    
    clients-per-query 10;
    max-clients-per-query 100;
    
    /*
     * clients-per-query :
     * Nombre de clients par requête récursive
     * 
     * 10 = Maximum 10 clients peuvent partager une même requête
     * 
     * Processus :
     * 1. Client A demande : www.example.com
     * 2. BIND commence la résolution récursive
     * 3. Client B demande : www.example.com (pendant ce temps)
     * 4. BIND groupe les deux clients
     * 5. Une seule résolution pour les deux
     * 
     * Performance :
     * [OK] Réduit le nombre de requêtes upstream
     * [OK] Économise de la bande passante
     * 
     * max-clients-per-query :
     * Limite absolue (protection contre abus)
     */
    
    recursive-clients 1000;
    
    /*
     * recursive-clients :
     * Nombre maximal de clients récursifs simultanés
     * 
     * 1000 = Maximum 1000 résolutions récursives en parallèle
     * 
     * Recommandations :
     * - Petit serveur : 100-500
     * - Serveur moyen : 1000-5000
     * - Gros serveur : 10000+
     * 
     * [ATTENTION] Chaque résolution consomme de la mémoire
     * Ajuster selon la RAM disponible
     */
    
    tcp-clients 100;
    
    /*
     * tcp-clients :
     * Nombre maximal de connexions TCP simultanées
     * 
     * 100 = Maximum 100 clients TCP en parallèle
     * 
     * TCP est utilisé pour :
     * - Transferts de zone (AXFR)
     * - Réponses trop grandes pour UDP (>512 octets)
     * - DNSSEC (réponses volumineuses)
     * 
     * Recommandation : 50-200
     */
    
    // ───────────────────────────────────────────────────────────
    // LOGGING : RÉDUIRE EN PRODUCTION
    // ───────────────────────────────────────────────────────────
    
    querylog no;
    
    /*
     * querylog :
     * Logger TOUTES les requêtes DNS
     * 
     * no = Désactivé (recommandé en production)
     * 
     * Pourquoi désactiver ?
     * - Performance : Logging = I/O disque (lent)
     * - Espace disque : Serveur chargé = Go de logs/jour
     * - Vie privée : Logs contiennent les requêtes des users
     * 
     * Quand activer ?
     * - Debug
     * - Investigation d'incident
     * - Analyse de trafic
     * 
     * Activation temporaire :
     * rndc querylog on
     * (logs jusqu'au prochain redémarrage)
     */
};
```

**Sauvegarde.**

---

**ÉTAPE 3 : Configuration workers (multi-threading)**

**Par défaut, BIND utilise 1 worker par CPU.**

**Pour ajuster manuellement :**

```bash
sudo nano /etc/default/named
```

**Ajouter :**

```bash
OPTIONS="-u bind -n 4"

# -u bind : Utilisateur
# -n 4 : 4 workers (threads)
```

**Redémarrer BIND :**

```bash
sudo systemctl restart bind9
```

**Vérifier :**

```bash
ps aux | grep named
```

**Tu devrais voir plusieurs threads.**

---

### PARTIE 4 : MONITORING AVEC PROMETHEUS ET GRAFANA

**ÉTAPE 1 : Installer BIND Exporter**

```bash
# Télécharger BIND Exporter
wget https://github.com/prometheus-community/bind_exporter/releases/download/v0.7.0/bind_exporter-0.7.0.linux-amd64.tar.gz

# Extraire
tar xvfz bind_exporter-0.7.0.linux-amd64.tar.gz

# Installer
sudo mv bind_exporter-0.7.0.linux-amd64/bind_exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/bind_exporter
```

---

**Activer les statistiques BIND :**

```bash
sudo nano /etc/bind/named.conf.options
```

**Ajouter :**

```bind
    statistics-channels {
        inet 127.0.0.1 port 8053 allow { 127.0.0.1; };
    };
    
    /*
     * statistics-channels :
     * Expose les statistiques BIND en HTTP
     * 
     * inet 127.0.0.1 port 8053 :
     * Écoute sur localhost:8053
     * 
     * allow { 127.0.0.1; } :
     * Seulement localhost peut accéder
     * 
     * [ATTENTION] IMPORTANT :
     * Ne JAMAIS exposer sur 0.0.0.0 (tout le monde)
     * Les stats contiennent des infos sensibles
     */
```

**Recharger BIND :**

```bash
sudo rndc reload
```

---

**Tester les statistiques :**

```bash
curl http://127.0.0.1:8053/
```

**Résultat : XML avec toutes les statistiques BIND.**

---

**Créer un service systemd pour bind_exporter :**

```bash
sudo nano /etc/systemd/system/bind-exporter.service
```

**Contenu :**

```ini
[Unit]
Description=BIND Exporter for Prometheus
After=network.target

[Service]
Type=simple
User=bind
ExecStart=/usr/local/bin/bind_exporter --bind.stats-url=http://127.0.0.1:8053/ --web.listen-address=:9119
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

**Activer et démarrer :**

```bash
sudo systemctl daemon-reload
sudo systemctl enable bind-exporter
sudo systemctl start bind-exporter
```

**Vérifier :**

```bash
curl http://localhost:9119/metrics
```

**Résultat : Métriques Prometheus.**

---

**ÉTAPE 2 : Installer Prometheus**

```bash
# Télécharger Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz

# Extraire
tar xvfz prometheus-2.48.0.linux-amd64.tar.gz

# Déplacer
sudo mv prometheus-2.48.0.linux-amd64 /opt/prometheus

# Créer l'utilisateur
sudo useradd --no-create-home --shell /bin/false prometheus

# Créer les dossiers
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus
```

---

**Configurer Prometheus :**

```bash
sudo nano /etc/prometheus/prometheus.yml
```

**Contenu :**

```yaml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'bind'
    static_configs:
      - targets: ['localhost:9119']
```

---

**Créer le service :**

```bash
sudo nano /etc/systemd/system/prometheus.service
```

**Contenu :**

```ini
[Unit]
Description=Prometheus
After=network.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/opt/prometheus/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus/

[Install]
WantedBy=multi-user.target
```

**Activer :**

```bash
sudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
```

**Accéder à Prometheus :**

```
http://<IP-serveur>:9090
```

---

**ÉTAPE 3 : Installer Grafana**

```bash
# Ajouter le repo Grafana
sudo apt install -y software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -

# Installer
sudo apt update
sudo apt install grafana -y

# Démarrer
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
```

**Accéder à Grafana :**

```
http://<IP-serveur>:3000
Login: admin / admin
```

---

**Ajouter Prometheus comme datasource :**

1. Configuration -> Data Sources -> Add data source
2. Choisir Prometheus
3. URL : `http://localhost:9090`
4. Save & Test

---

**Importer un dashboard BIND :**

1. Dashboards -> Import
2. ID Grafana.com : `12309` (BIND Dashboard)
3. Select Prometheus datasource
4. Import

**[OK] Dashboard BIND opérationnel !**

---

### [OK] TESTS DE VALIDATION

**1. RRL actif**
- [ ] Faire 20 requêtes rapides
- [ ] Logs indiquent "rate limit drop/slip"
- [ ] Certaines requêtes timeoutent

**2. RPZ bloque les domaines**
- [ ] `dig doubleclick.net` -> NXDOMAIN
- [ ] Logs indiquent "rpz QNAME NXDOMAIN rewrite"

**3. Version masquée**
- [ ] `dig @localhost version.bind txt chaos` -> "DNS Server"

**4. Statistiques exposées**
- [ ] `curl http://127.0.0.1:8053/` -> XML
- [ ] `curl http://localhost:9119/metrics` -> Métriques

**5. Monitoring opérationnel**
- [ ] Prometheus : `http://<IP>:9090`
- [ ] Grafana : `http://<IP>:3000`
- [ ] Dashboard BIND affiche les métriques

---

## [COURS] CONCLUSION DE L'EXERCICE 5

**[OK] Félicitations ! Tu as transformé ton DNS en infrastructure production-grade ! [BRAVO]**

**Ce que tu as appris :**
- Protéger DNS contre les DDoS avec RRL
- Bloquer des domaines malveillants avec RPZ
- Durcir la sécurité de BIND (hardening)
- Optimiser les performances
- Monitorer avec Prometheus + Grafana
- Créer des dashboards de monitoring

**Compétences acquises :**
- [OK] RRL (Response Rate Limiting) - niveau expert
- [OK] RPZ (Response Policy Zones) - niveau expert
- [OK] Hardening DNS - niveau expert
- [OK] Performance tuning - niveau expert
- [OK] Monitoring avec Prometheus/Grafana - niveau avancé

**Temps moyen de réalisation :** 4-5 heures

---

## [BRAVO] CONCLUSION GÉNÉRALE DE LA SÉRIE DNS BIND9

**Tu as complété les 5 exercices ! Tu maîtrises maintenant :**

1. [OK] DNS de base (zones, enregistrements, résolution)
2. [OK] Haute disponibilité (master/slave, failover)
3. [OK] DNS dynamique (DDNS + DHCP)
4. [OK] Sécurité cryptographique (DNSSEC)
5. [OK] Sécurité avancée et monitoring (RRL, RPZ, Prometheus)

**Tu es maintenant capable de gérer une infrastructure DNS professionnelle de bout en bout ! [RAPIDE]**

Bravo pour ton travail ! [CLAPPING_HANDS_SIGN]