Pics de charge DNS : limiter le débit et survivre aux attaques sans interruption

Cet article vous a aidé ?

Le DNS est la dépendance que tout le monde oublie jusqu’à ce qu’il prenne feu. Votre couche web peut s’auto-dimensionner, vos caches peuvent absorber, vos bases de données peuvent se dégrader. Le DNS ? Le DNS répond aux questions jusqu’à ce qu’il ne puisse plus—et alors tout a l’air « en panne » même si vos serveurs vont bien.

Les pics de charge frappent le DNS de manière brutale : popularité soudaine, retries client cassés, scans de bots, inondations NXDOMAIN, attaques par réflexion, ou un changement « utile » qui transforme une zone tranquille en chaos. L’astuce n’est pas seulement de bloquer le trafic. C’est limiter les bonnes choses, au bon niveau, sans mentir aux clients légitimes ni déclencher votre propre perte de disponibilité.

Ce qui casse réellement lors des pics DNS

Quand le DNS lâche, vous n’obtenez habituellement pas une alerte claire « DNS en panne ». Vous obtenez un cortège de symptômes de second ordre : échecs de connexion, timeouts API aléatoires, nœuds Kubernetes qui « oscillent », et un PDG qui ne parvient pas à atteindre le site marketing (qui, tragiquement, devient « P0 »).

Mode de défaillance 1 : la gestion des paquets s’effondre avant le CPU

La plupart des démons DNS sont rapides, mais ils dépendent du noyau pour recevoir les paquets, les mettre en file et les livrer à l’espace utilisateur. Sous des QPS en rafales, vous pouvez rencontrer :

  • Epuisement des anneaux NIC (drops au niveau du pilote).
  • Débordements des buffers de réception de socket (drops au niveau du noyau).
  • Goulots d’étranglement mono‑thread (le démon ne peut pas vider les files).

Résultat : les clients voient des timeouts et retentent, ce qui multiplie le trafic et transforme un « pic » en « spirale ». Le DNS est un des rares lieux où « timeout » n’est pas juste un symptôme—c’est un amplificateur de trafic.

Mode de défaillance 2 : la latence vous tue bien avant les erreurs

Les clients DNS attendent souvent seulement quelques centaines de millisecondes avant de retenter ou d’effectuer un basculement. Votre serveur peut encore répondre, mais si le p95 passe de 5 ms à 200 ms vous verrez des « pannes » aléatoires dans les applications.

Mode de défaillance 3 : le mauvais trafic gagne

Toutes les requêtes ne méritent pas le même traitement. Pendant les attaques, vous verrez des flots de :

  • Requêtes de sous-domaines aléatoires (par ex. asdf123.example.com) conçues pour contourner les caches et générer du travail NXDOMAIN ou NODATA.
  • Requêtes ANY (moins pertinentes aujourd’hui mais encore observées) ou types qui déclenchent de grosses réponses.
  • Sondes activant EDNS qui cherchent à forcer de larges réponses UDP pour la réflexion.

Si votre infrastructure traite ces requêtes comme du trafic normal, vous finissez par protéger le QPS de l’attaquant pendant que les clients légitimes font la queue derrière. Ce n’est pas de la neutralité ; c’est s’infliger un tort opérationnel.

Mode de défaillance 4 : votre « protection » devient la panne

Limiter le débit de façon maladroite est indiscernable d’une attaque. Trop strict, et vous jetez dans le noir de vrais utilisateurs derrière NAT ou CGNAT. Trop malin, et vous bridez vos propres résolveurs récursifs ou contrôles de santé. L’objectif est une dégradation contrôlée : certaines réponses ralentissent ou sont tronquées, mais le service reste joignable et se rétablit rapidement.

Une vérité sèche : le DNS est l’endroit où les configurations « simples » deviennent des systèmes distribués. Vous négociez avec des stub resolvers, des résolveurs récursifs, des caches, des middleboxes et des personnes utilisant du firmware antique dans des routeurs Wi‑Fi d’hôtel.

Une citation à retenir (idée paraphrasée) : « L’espoir n’est pas une stratégie », souvent attribuée à des ingénieurs et opérateurs discutant fiabilité. Traitez les pics DNS de la même manière : concevez, mesurez, répétez.

Blague #1 : Le DNS est le seul système où le meilleur résultat est d’être ignoré parce que tout le monde vous a mis en cache.

Faits intéressants et contexte historique

  • Le DNS précède le web moderne : il a été conçu au début des années 1980 pour remplacer le modèle de distribution HOSTS.TXT.
  • UDP était le choix pour la vitesse : DNS sur UDP a été choisi pour éviter l’établissement de connexion, ce qui est excellent jusqu’à ce que vous rencontriez l’usurpation et les abus par réflexion.
  • Le cache DNS est un shedding de charge délibéré : les TTL ne sont pas que des contrôles de correction ; ils sont un système économique pour le QPS.
  • Le système des serveurs racine n’est pas une seule boîte : c’est une constellation anycastée globale ; « la racine est en panne » est presque toujours votre problème local.
  • Les requêtes ANY sont devenues un outil de DDoS : beaucoup d’opérateurs minimisent ou restreignent maintenant les réponses ANY, car elles étaient utilisées pour déclencher des réponses surdimensionnées.
  • DNSSEC augmente la taille des réponses : ajouter des signatures améliore l’intégrité mais peut aggraver la fragmentation et le risque d’amplification si vous ne gérez pas les tailles EDNS.
  • RRL (Response Rate Limiting) est né de la douleur : les opérateurs autoritatifs avaient besoin d’un moyen pour réduire l’utilité de la réflexion sans se mettre hors ligne.
  • Les attaques NXDOMAIN sont anciennes : les inondations de sous-domaines aléatoires sont utilisées depuis des années parce qu’elles contournent le comportement normal du cache.
  • Anycast a changé la donne : répartir l’autoritatif DNS sur plusieurs POPs réduit la saturation d’un site unique mais ajoute de la complexité au débogage.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Voici la séquence « arrêter de deviner ». Vous pouvez la faire en 10 minutes pendant que tout le monde se dispute sur Slack.

Premier : confirmer que c’est le DNS, pas un problème « en forme de DNS »

  1. Depuis un réseau client affecté, interrogez directement votre serveur autoritatif (contournez la récursion). Vérifiez la latence et les timeouts.
  2. Depuis l’intérieur du datacenter/VPC, faites de même. Si l’interne est OK et l’externe non, suspectez une saturation de bordure ou un filtrage en amont.
  3. Vérifiez si le pic touche l’autoritatif, le récursif, ou les deux. Ils échouent différemment.

Second : localiser la couche goulot

  1. Ingress réseau : pertes de paquets au NIC/noyau, orages conntrack, limites PPS.
  2. Démon : CPU par thread, contention sur verrous, tempêtes de cache miss, coûts DNSSEC de signature ou validation.
  3. Dépendances back-end : backends dynamiques (bases de données), transferts de zone lents, journaux ou sinks télémétriques surchargés.

Troisième : appliquer une contention sûre, puis optimiser

  1. Déployez la limitation de débit en bordure (dnsdist / pare‑feu / load balancer) avant de toucher les internals du démon.
  2. Priorisez : gardez A/AAAA/CNAME/SOA/NS fonctionnels. Dégradez le « agréable à avoir » (ANY, TXT, grandes réponses).
  3. Stabilisez la latence (p95) d’abord. Ensuite, traquez le QPS absolu.

Mesurer d’abord : tâches, commandes, sorties, décisions

Vous ne pouvez pas vous limiter la bande passante sans savoir ce qui se passe. Ci‑dessous des tâches pratiques à exécuter pendant un incident ou une répétition. Chaque tâche inclut une commande, un exemple de sortie, ce que cela signifie et la décision à prendre.

Tâche 1 : Vérifier la réponse autoritative et la latence (requête directe)

cr0x@server:~$ dig @203.0.113.53 www.example.com A +tries=1 +time=1

; <<>> DiG 9.18.24 <<>> @203.0.113.53 www.example.com A +tries=1 +time=1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43112
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; ANSWER SECTION:
www.example.com. 60 IN A 198.51.100.10
;; Query time: 12 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (UDP)
;; WHEN: Tue Dec 31 12:00:00 UTC 2025
;; MSG SIZE  rcvd: 93

Ce que ça signifie : Vous obtenez une réponse autoritative (drapeau aa), avec une faible latence.

Décision : Si ceci est rapide mais que les utilisateurs se plaignent, le problème peut venir des résolveurs récursifs, du chemin réseau, ou du comportement de cache négatif—pas de l’autoritatif lui-même.

Tâche 2 : Comparer le comportement UDP vs TCP (détecter fragmentation/EDNS)

cr0x@server:~$ dig @203.0.113.53 example.com DNSKEY +dnssec +time=1 +tries=1

;; Truncated, retrying in TCP mode.
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5321
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; Query time: 210 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (TCP)

Ce que ça signifie : La troncature UDP a forcé un retry en TCP. Sous charge, le TCP coûte plus (état, files d’accept, overhead noyau).

Décision : Ajustez la taille du buffer EDNS et le comportement DNSSEC ; envisagez de limiter les grandes réponses et assurez-vous que la capacité de gestion TCP est raisonnable.

Tâche 3 : Vérifier le QPS côté serveur et les qtypes principaux sur BIND (autoritatif)

cr0x@server:~$ sudo rndc stats
cr0x@server:~$ sudo tail -n 20 /var/cache/bind/named.stats
++ Incoming Requests ++
[View: default]
                          1987632 QUERY
                           504112 NOTIFY
++ Incoming Queries ++
[View: default]
                           912331 A
                           701221 AAAA
                           389002 TXT
                           211332 DNSKEY
                           122880 ANY

Ce que ça signifie : Vous avez un fort mix TXT/DNSKEY/ANY. C’est une signature classique « rendre les réponses plus grosses ».

Décision : Envisagez de durcir la politique de réponses : minimiser ANY, limiter les qtypes abusés, et revoir DNSSEC/EDNS sizing.

Tâche 4 : Inspecter rapidement les statistiques d’Unbound (récursif)

cr0x@server:~$ sudo unbound-control stats_noreset | egrep 'total\.num\.queries|num\.query\.type|unwanted|cache\.hits|cache\.miss|avg\.recursion'
total.num.queries=18422301
num.query.type.A=10233444
num.query.type.AAAA=6012231
num.query.type.TXT=1589222
unwanted.queries=433221
msg.cache.hits=11022334
msg.cache.misses=7401130
avg.recursion.time=0.145000

Ce que ça signifie : Les cache misses sont élevés et le temps de récursion augmente. Les requêtes indésirables sont non‑négligeables—probablement des abus ou des clients mal configurés.

Décision : Ajoutez une limitation par client, resserrez le contrôle d’accès (qui peut utiliser la récursion), et augmentez le cache là où c’est sûr. Si le temps de récursion est élevé à cause de timeouts amont, considérez une stratégie de forwarding ou la reachabilité root/TLD.

Tâche 5 : Identifier les principaux émetteurs et noms de requête (échantillon de paquets)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -c 50
12:00:01.001234 IP 192.0.2.10.53211 > 203.0.113.53.53: 1234+ A? asdf91k2.example.com. (38)
12:00:01.001260 IP 192.0.2.10.53212 > 203.0.113.53.53: 2234+ AAAA? asdf91k2.example.com. (38)
12:00:01.001289 IP 198.51.100.77.41922 > 203.0.113.53.53: 3321+ ANY? example.com. (28)
...

Ce que ça signifie : Des labels aléatoires pour votre zone suggèrent une inondation de contournement de cache NXDOMAIN/NODATA ; des requêtes ANY suggèrent des sondes d’amplification.

Décision : Appliquez des limites par source et par qname/qtype en bordure, et envisagez de servir des réponses « synthétisées » minimales là où c’est approprié (avec précaution) ou des réglages agressifs de cache négatif.

Tâche 6 : Vérifier les drops du noyau et les erreurs de réception UDP

cr0x@server:~$ netstat -su
Udp:
    1283221 packets received
    0 packets to unknown port received
    22111 packet receive errors
    904321 packets sent
    22111 receive buffer errors

Ce que ça signifie : Les erreurs de buffer de réception impliquent que le noyau abandonne des UDP parce que l’appli ne peut pas vider assez vite ou que les buffers sont trop petits.

Décision : Augmentez les buffers de socket et ajustez le réseau du noyau ; réduisez aussi le CPU par paquet en déplaçant la limitation de débit en amont (dnsdist, XDP, pare‑feu) et en réduisant l’overhead de journalisation.

Tâche 7 : Vérifier les drops au niveau NIC et noyau

cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    RX:  bytes  packets  errors  dropped overrun mcast
    9876543210 12345678  0       4321    0       0
    TX:  bytes  packets  errors  dropped carrier collsns
    8765432109 11223344  0       0       0       0

Ce que ça signifie : Des drops RX à l’interface se produisent déjà avant que votre démon voie le trafic.

Décision : Ajoutez de la capacité (plus d’instances/anycast), utilisez des NICs adaptés au PPS élevé, ou imposez un filtrage/limitation en amont pour que l’hôte ne voie jamais le pire.

Tâche 8 : Confirmer que conntrack n’est pas impliqué accidentellement

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 982312
net.netfilter.nf_conntrack_max = 1048576

Ce que ça signifie : Vous êtes proche du max conntrack. DNS over UDP n’a pas besoin de conntrack dans beaucoup de designs, mais les pare‑feu/NAT peuvent l’y amener.

Décision : Evitez le suivi d’état pour un DNS à haut QPS si possible ; déplacez le filtrage vers des règles sans état ou des dispositifs de bord dédiés, ou augmentez les limites avec précaution.

Tâche 9 : Valider la santé du démon et la saturation des threads (systemd + CPU)

cr0x@server:~$ systemctl status named --no-pager
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled)
     Active: active (running) since Tue 2025-12-31 11:20:12 UTC; 39min ago
   Main PID: 1023 (named)
      Tasks: 42
     Memory: 1.3G
        CPU: 18min 22.331s
cr0x@server:~$ top -b -n1 | head -n 15
top - 12:00:10 up 10 days,  3:22,  1 user,  load average: 18.21, 17.44, 16.02
%Cpu(s): 92.1 us,  4.1 sy,  0.0 ni,  1.2 id,  0.0 wa,  0.0 hi,  2.6 si,  0.0 st
MiB Mem :  32110.0 total,   2100.0 free,  12000.0 used,  18010.0 buff/cache
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 1023 bind      20   0  2460.0m  1320.0m   8.1m R  580.0   4.1  18:25.12 named

Ce que ça signifie : Le CPU est chaud ; named consomme plusieurs cœurs. Si la latence est toujours mauvaise, le CPU n’est pas le seul goulot—vérifiez les drops et la mise en file.

Décision : Si le CPU est le limiteur, scalez horizontalement et/ou réduisez le travail coûteux (signatures/validation DNSSEC, journalisation, updates dynamiques). Si des drops sont présents, limitez le débit avant le démon.

Tâche 10 : Vérifier la distribution des tailles de réponses DNS (repérer le risque d’amplification)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -vv -c 10
12:00:12.100001 IP 203.0.113.53.53 > 192.0.2.10.53211: 1234 NXDomain 0/1/0 (112)
12:00:12.100120 IP 203.0.113.53.53 > 198.51.100.77.41922: 3321 4/0/6 (1452)

Ce que ça signifie : Des réponses UDP de 1452 octets flirtent avec la fragmentation (selon le PMTU). La fragmentation augmente la perte et peut faire de vous une meilleure arme de réflexion.

Décision : Limitez la taille EDNS UDP (souvent ~1232 octets est un choix pragmatique), réduisez les enregistrements additionnels, et assurez‑vous que le fallback TC=1 est acceptable.

Tâche 11 : Vérifier les statistiques frontales de dnsdist (limiteur de bord)

cr0x@server:~$ sudo dnsdist -c -e 'showStats()'
aclDrops                                 12345
responses                                9812234
queries                                  9921100
rdQueries                                221001
ruleDrop                                 88321
ruleNXDomain                             0
latency0_1                                7122331
latency1_10                               2501123
latency10_50                              210992
latency50_100                             12012
latency100_1000                            542

Ce que ça signifie : Vous droppez du trafic via ACL/règles tout en gardant la plupart des latences sous 10 ms. C’est la forme souhaitée pendant une attaque.

Décision : Si les drops sont trop élevés et impactent les utilisateurs légitimes, affinez les règles (par blocs réseau, par qtype, par qname) plutôt que d’augmenter des limites globales.

Tâche 12 : Valider la correction de la zone et le TTL de cache négatif (SOA)

cr0x@server:~$ dig @203.0.113.53 example.com SOA +noall +answer
example.com. 300 IN SOA ns1.example.com. hostmaster.example.com. 2025123101 7200 3600 1209600 60

Ce que ça signifie : Le dernier champ (minimum/TTL négatif en pratique moderne) est 60 secondes. Il gouverne combien de temps les résolveurs peuvent mettre en cache NXDOMAIN/NODATA.

Décision : Pendant des inondations NXDOMAIN, un TTL négatif trop bas aggrave la situation car les résolveurs repromènent constamment des requêtes. Augmentez‑le prudemment (pas à des jours ; à quelques minutes ou une heure selon votre cadence de changement).

Tâche 13 : Vérifier si les clients retentent excessivement (échantillonnage des logs)

cr0x@server:~$ sudo journalctl -u named --since "10 min ago" | egrep 'client|query' | head
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0a: query (cache) 'asdf91k2.example.com/A/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0b: query (cache) 'asdf91k2.example.com/AAAA/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0c: query (cache) 'asdf91k2.example.com/A/IN' denied

Ce que ça signifie : Vous voyez des requêtes répétées pour le même nom aléatoire, potentiellement depuis des résolveurs récursifs. Les denies peuvent être des ACLs ou des décisions de limitation.

Décision : Si des résolveurs légitimes se voient refuser l’accès, vous allez trop loin. Préférez des stratégies de « slip »/troncature ou du shaping par source plutôt que des refus massifs.

Tâche 14 : Confirmer la synchronisation temporelle (DNSSEC et sanity TTL)

cr0x@server:~$ timedatectl
               Local time: Tue 2025-12-31 12:00:30 UTC
           Universal time: Tue 2025-12-31 12:00:30 UTC
                 RTC time: Tue 2025-12-31 12:00:29
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active

Ce que ça signifie : Le temps est sain. Une mauvaise synchronisation peut causer des échecs de validation DNSSEC et des comportements étranges de cache.

Décision : Si non synchronisé, corrigez NTP en priorité. Déboguer le DNS avec un décalage temporel, c’est comme déboguer le stockage pendant qu’un disque est en feu.

Patrons de limitation de débit efficaces (et ce qu’il faut éviter)

Limiter le débit sur le DNS n’est pas « bloquer de mauvaises IP ». Le trafic d’attaque est souvent usurpé, distribué, ou provient de résolveurs légitimes qui sont eux‑mêmes surchargés. Vous façonnez un système où l’identité client est floue et le transport est souvent UDP.

Principe : limiter en bordure, pas à l’intérieur du cerveau

Votre démon autoritatif devrait dépenser du CPU à répondre aux requêtes légitimes, pas à jouer le gendarme. Mettez une couche en avant :

  • dnsdist pour filtrage et shaping DNS‑aware.
  • iptables/nftables pour des limites PPS grossières et des ACLs.
  • Anycast + plusieurs POPs pour transformer « une cible » en plusieurs cibles plus petites.

Ne faites pas en sorte que votre serveur autoritatif parse et log toutes les requêtes abusives en debug. Ce n’est pas de l’observabilité. C’est imprimer le DDoS sur papier.

Patron 1 : seau à jetons par source (avec la réalité NAT)

Une limite QPS par IP est le contrôle le plus simple. C’est aussi comme ça que vous bloquez accidentellement un opérateur mobile entier derrière CGNAT. Utilisez‑le, mais :

  • Fixez des limites suffisamment élevées pour les gros résolveurs.
  • Privilégiez des limites par /24 ou /56 seulement si vous comprenez les dommages collatéraux.
  • Whitelist les résolveurs récursifs connus sur lesquels vous dépendez (les vôtres, les grands publics si approprié).

Patron 2 : limiter par motif de qname (inondations de sous‑domaines aléatoires)

Les sous‑domaines aléatoires sont conçus pour provoquer des cache misses. Limiter par suffixe de qname et par « entropie » peut être efficace :

  • Throttlez les réponses NXDOMAIN par source.
  • Throttlez les requêtes pour des labels « profonds » (par ex. préfixe aléatoire >20 caractères) si votre activité n’en a pas besoin.
  • Considérez les enregistrements wildcard avec prudence—les wildcards peuvent transformer NXDOMAIN en NOERROR, ce qui change l’économie d’attaque et du cache.

Patron 3 : minimiser la valeur d’amplification

Les attaques par réflexion veulent de grosses réponses pour de petites requêtes. Faites de votre serveur un mauvais amplificateur :

  • Minimisez les réponses ANY (beaucoup de serveurs autoritatifs répondent de façon minimale ou refusent ANY).
  • Limitez la taille EDNS UDP pour réduire la fragmentation et les réponses surdimensionnées.
  • Evitez les enregistrements additionnels gratuits (comme des glue supplémentaires) sauf si nécessaire.
  • Assurez‑vous de ne pas être un résolveur ouvert si vous êtes autoritatif. Cette erreur ne meurt jamais.

Patron 4 : « slip » (troncature) au lieu du drop dur, quand c’est utile

Certaines implémentations de limitation peuvent « sliper » les réponses : envoyer des réponses tronquées (TC=1) occasionnellement pour que les résolveurs légitimes retentent en TCP, tandis que les attaquants perdent en efficacité. Ce n’est pas magique—le TCP peut aussi être attaqué—mais ça peut renvoyer le coût vers le demandeur.

Ce qu’il faut éviter : plafonds QPS globaux sans classifier le trafic

Un plafond global dit « je ne sais pas ce qui se passe, donc je vais faire du mal à tout le monde ». C’est une façon rapide de laisser l’attaque continuer pendant que vos clients se détournent.

Blague #2 : La seule chose plus effrayante qu’un DDoS DNS est un DDoS DNS plus une « augmentation d’urgence des logs » de quelqu’un qui a raté les années 1990.

Autoritatif vs récursif : ennemis différents, contrôles différents

DNS autoritatif : protéger vos zones et votre réputation

Les serveurs autoritatifs répondent pour votre domaine. Le trafic d’attaque les cible souvent parce qu’ils sont publics et prévisibles. Abus courants :

  • Réflexion : adresses source usurpées ; votre serveur « attaque » quelqu’un d’autre.
  • Inondations NXDOMAIN : sous‑domaines aléatoires ; vous calculez des réponses négatives en boucle.
  • Amplification DNSSEC : grosses réponses DNSKEY/DS/NSEC*.

Bons contrôles pour l’autoritatif :

  • RRL (Response Rate Limiting) pour des réponses similaires à de nombreux clients.
  • Règles basées sur le qtype (par ex. restreindre ANY, surveiller les motifs TXT/DNSKEY).
  • Distribution anycast et transit en amont diversifié.
  • Contenu de zone court et sensé (évitez de gros TXT à moins que nécessaire).

DNS récursif : protéger vos utilisateurs et votre amont

Les résolveurs récursifs récupèrent des réponses sur Internet pour le compte des clients. Ils sont abusés via :

  • Récursion ouverte : des étrangers utilisent votre résolveur ; vous payez la bande passante et on vous blâme.
  • Contournement du cache : qnames aléatoires forcent des recherches en amont et tiennent votre récursif occupé.
  • Orages de retries clients : applications mal configurées ou stub resolvers cassés.

Bons contrôles pour le récursif :

  • Contrôle d’accès : seule votre flotte/réseaux peuvent interroger la récursion.
  • Cache agressif là où c’est sûr ; préfetch des enregistrements populaires.
  • Limitation par client et mitigation des « unwanted query ».
  • Servir des réponses expirées (avec prudence) pour traverser des pannes amont.

Le piège : mêler autoritatif et récursif sur la même machine

Oui, ça « marche ». Ça couple aussi des domaines de défaillance. En attaque, votre récursif peut affamer l’autoritatif, ou inversement. Séparez les rôles sauf si vous avez un petit environnement et aimez vivre dangereusement.

Concevoir pour survivre : architecture et ajustements de capacité

Utilisez anycast, mais ne l’adorer pas aveuglément

Anycast répartit la charge de requêtes sur plusieurs sites en annonçant la même IP depuis de nombreux emplacements. C’est la norme industrielle pour l’autoritatif à grande échelle. Cela introduit aussi des réalités opérationnelles :

  • Le trafic suit BGP, pas votre intention. Un flap de route peut déplacer la DNS d’une moitié de continent vers un seul POP.
  • Le débogage « pourquoi ce résolveur frappe ce POP ? » devient un exercice réseau.
  • L’état doit être minimal : le contenu de zone et les clés doivent se répliquer de façon fiable.

Faites de l’anycast si vous pouvez l’exploiter correctement. Sinon, utilisez plusieurs NS unicast avec une protection DDoS amont solide. L’objectif fiabilité est la diversité.

Séparez « répondre » et « réfléchir »

Les meilleurs systèmes autoritatifs effectuent un minimum de calcul par requête :

  • Zones pré‑signées (si vous utilisez DNSSEC) ou infrastructure de signature efficace.
  • Données de zone en mémoire.
  • Pas d’appels synchrones à des bases de données sur le chemin de requête. Si vous devez absolument avoir des réponses dynamiques, mettez‑les derrière un cache et des coupe‑circuit stricts.

Ajustez EDNS et la taille UDP comme si vous le pensiez

Les grosses réponses UDP se fragmentent. Les fragments sont perdus. Les fragments perdus déclenchent des retries. Les retries multiplient le QPS. C’est ainsi que vous obtenez un « pic mystérieux » qui ressemble à un internet ayant collectivement oublié comment mettre en cache.

Mouvement pragmatique : gardez les réponses UDP à une taille raisonnable. Limitez la taille EDNS UDP à une valeur conservatrice ; acceptez que le fallback TCP soit parfois nécessaire et concevez pour cela.

Stratégie TTL : le cache est votre capacité la moins coûteuse

Les TTL courts donnent l’impression d’agilité. Ils sont aussi coûteux. Sous attaque ou trafic viral, la différence entre TTL 30 et TTL 300 fait un facteur 10 sur le volume de requêtes des résolveurs qui respectent le TTL.

Ne définissez pas les TTL sur des impressions. Définissez‑les selon :

  • La rapidité réelle à laquelle vous devez changer des enregistrements en urgence.
  • Si vous disposez d’autres contrôles de routage (load balancers, anycast, basculement).
  • Votre tolérance au cache stale pendant les incidents.

Journalisation : échantillonnez, ne vous noyez pas

La journalisation de requêtes à plein régime pendant les pics est un classique auto‑infligé. Utilisez :

  • Échantillonnage (1 requête sur N).
  • Métriques agrégées (comptes par qtype, taux NXDOMAIN, top clients par PPS).
  • Pcap courts avec filtres serrés.

Gardez votre sous‑système de stockage hors du rayon d’explosion. Le DNS est un service réseau ; ne le transformez pas en benchmark disque.

Trois mini-récits d’entreprise du terrain

Mini-récit 1 : l’incident causé par une mauvaise hypothèse

Une entreprise SaaS de taille moyenne exécutait le DNS autoritatif sur deux VM derrière un load balancer cloud « fiable ». L’équipe croyait que le load balancer fournissait « une protection DDoS par défaut », parce qu’il venait d’un grand fournisseur et avait un joli tableau de bord.

Puis un partenaire a intégré un nouveau SDK. Le SDK faisait un lookup SRV au démarrage d’une appli, pour chaque requête, parce que quelqu’un avait mal lu une guideline de cache. Cela a créé un pic parfaitement légitime : pas une attaque, juste cent mille clients enthousiastes. Les serveurs autoritatifs ont été submergés par des requêtes répétitives contournant le cache parce que les enregistrements avaient un TTL de 30 secondes « pour la flexibilité ».

La latence a grimpé. Les timeouts ont augmenté. Les clients ont retenté. Le load balancer a commencé à mettre en file, et finalement les checks de santé ont échoué parce que les serveurs DNS étaient occupés à répondre au trafic réel. Le balancer les a évacués, ce qui a concentré la charge, et aggravé la situation. Boucle de rétroaction positive classique, maintenant avec un service managé au milieu qui ajoute du mystère.

La mauvaise hypothèse n’était pas « le cloud est peu fiable ». C’était croire qu’un load balancer générique équivaut à un edge DNS‑aware. Ils ont corrigé cela en augmentant les TTL, en ajoutant dnsdist devant avec un shaping client sensé, et en séparant les checks de santé des chemins de requêtes surchargés. Ils ont aussi écrit un test simulant le pattern de lookup du SDK, car le prochain incident serait plus étrange.

Mini-récit 2 : l’optimisation qui a mal tourné

Une grande équipe réseau d’entreprise a décidé d’« optimiser la latence DNS » en forçant tous les clients internes à utiliser un petit ensemble de résolveurs récursifs dans un data center. Ils ont monté ces résolveurs : beaucoup de RAM, gros CPU, NVMe pour les logs. Le changement fonctionnait bien lors d’un test en bureau unique.

Deux mois plus tard, un incident de transit a dégradé la connectivité depuis ce data center vers plusieurs serveurs de zone TLD. Rien n’était complètement en panne, juste plus lent. Le temps de résolution récursive a augmenté, les cache misses sont devenus douloureux, et les résolveurs ont commencé à accumuler du backlog. Les clients—surtout des endpoints Windows et certains appareils IoT—retentaient agressivement lors de la lenteur perçue.

L’« optimisation » a créé un domaine de défaillance centralisé. Pire : l’équipe avait activé la journalisation détaillée des requêtes pour prouver l’amélioration, et pendant les pics le pipeline de logs a saturé l’I/O disque et le CPU. Les résolveurs n’étaient pas seulement lents parce qu’Internet était lent ; ils étaient lents parce qu’ils racontaient leur souffrance sur disque.

La correction fut peu glamour : distribuer la récursion entre régions, réduire la journalisation à de l’échantillonnage/agrégats, et activer serve‑expired avec garde‑fous pour que la lenteur amont transitoire ne devienne pas instantanément une tempête de retries client. Ils ont aussi arrêté de traiter le DNS comme un service web où « un grand cluster » est toujours une victoire.

Mini-récit 3 : la pratique ennuyeuse mais correcte qui a sauvé la mise

Une société financière exécutait le DNS autoritatif en anycast sur plusieurs POPs. Rien de fou dans la zone—A, AAAA, CNAME, quelques TXT. La partie ennuyeuse était leur discipline : chaque changement passait par une zone de staging, ils suivaient l’intention des TTL, et ils répétaient un runbook DDoS trimestriellement.

Un après‑midi, une attaque démarre : QPS élevé de sous‑domaines aléatoires plus sondes TXT et DNSKEY. Leur monitoring signale une forte hausse du taux NXDOMAIN et des erreurs de réception UDP sur un POP. L’on‑call ne panique pas. Ils suivent le playbook : confirmer les drops, confirmer le mix de requêtes, activer des limites plus strictes pour les réponses NXDOMAIN, limiter la taille EDNS, et temporiser le dé‑préférencement du POP sur le BGP.

L’impact client fut minime. Certains résolveurs sont tombés en TCP ; certaines requêtes ont été ralenties ; mais le domaine est resté résoluble. L’attaque est passée, comme souvent quand vous cessez d’être une cible amusante.

La pratique salvatrice n’était pas un produit secret. C’était avoir des bases mesurées, des contrôles répétées, et l’autorité (organisationnelle) pour les appliquer rapidement. Le compte‑rendu d’incident fut court, ce qui est le mieux.

Erreurs courantes : symptôme → cause racine → correction

1) Symptom : beaucoup de timeouts, mais le CPU n’est pas saturé

Cause racine : Pertes de paquets au NIC/noyau (anneaux, buffers socket), ou congestion amont.

Correction : Vérifiez ip -s link et netstat -su ; augmentez les buffers, réduisez l’overhead par paquet, ajoutez de la limitation en bordure, scalez horizontalement/anycast.

2) Symptom : pic soudain de réponses NXDOMAIN

Cause racine : Inondation de sous‑domaines aléatoires, ou un client mal configuré générant des qnames absurdes.

Correction : Augmentez prudemment le TTL négatif, appliquez des limites NXDOMAIN, et identifiez les blocs réseau sources générant des qnames à forte entropie.

3) Symptom : augmentation massive des connexions DNS TCP

Cause racine : Troncature due à des réponses UDP surdimensionnées (DNSSEC, gros TXT), EDNS mal paramétré, ou forçage délibéré vers TCP pour épuiser l’état.

Correction : Limitez la taille EDNS UDP, minimisez les grandes réponses, assurez la capacité TCP, et limitez les qtypes abusifs.

4) Symptom : échecs clients « aléatoires » derrière des réseaux mobiles

Cause racine : Limitation par IP punissant des populations NATées ou de grands résolveurs.

Correction : Utilisez des limites par IP plus élevées, whitelist les résolveurs majeurs dont vous dépendez, ou passez à des limites par qname/qtype ciblant les motifs abusifs.

5) Symptom : les serveurs autoritatifs deviennent des résolveurs ouverts « accidentellement »

Cause racine : Récursion activée ou ACLs trop larges ; parfois introduit en copiant une config récursive dans l’autoritatif.

Correction : Désactivez la récursion sur l’autoritatif ; auditez la gestion de configuration ; validez externement que la récursion est refusée.

6) Symptom : tout casse après activation de la journalisation complète

Cause racine : Overhead I/O et CPU ; saturation du pipeline de logs ; contention de verrous dans le démon.

Correction : Coupez‑la d’abord. Puis implémentez échantillonnage et métriques agrégées. Capturez de courts tcpdump au lieu d’essayer de logger l’apocalypse.

7) Symptom : le trafic « bouge » pendant une attaque et un POP fond

Cause racine : Changements de chemin anycast, quirks de préférence BGP, ou ciblage spécifique d’un POP.

Correction : Contrôlez le routage : dé‑préférez les routes pour le POP chaud, assurez la symétrie de capacité, et confirmez que chaque POP a un traitement DDoS amont.

8) Symptom : le temps de récursion explose, le hit rate du cache chute

Cause racine : Contournement du cache via qnames aléatoires ; problèmes de reachabilité amont ; caches trop petits.

Correction : Limitez les clients, activez les protections (mitigation des requêtes indésirables), scalez horizontalement les résolveurs, et assurez la diversité de connectivité amont.

Listes de contrôle / plan étape par étape

Phase 0 : avant d’être attaqué (faites‑le un mardi calme)

  1. Basez votre normal. Enregistrez le QPS typique, le mix qtype, le taux NXDOMAIN, la latence p50/p95, la répartition UDP/TCP.
  2. Séparez les rôles. Autoritatif et récursif sur des instances séparées et idéalement sur des sous‑réseaux/edges distincts.
  3. Fixez des TTL sensés. N’exécutez pas des TTL à 30 secondes pour des enregistrements qui changent une fois par mois.
  4. Décidez d’une politique EDNS. Limitez la taille UDP et vérifiez le comportement avec DNSSEC.
  5. Mettez en place un edge DNS‑aware. dnsdist ou équivalent, avec un jeu de règles d’urgence testé que vous pouvez activer rapidement.
  6. Répétez le playbook. Simulez des inondations NXDOMAIN et des sondes de grandes réponses en staging.

Phase 1 : pendant un pic (gardez‑le en ligne d’abord)

  1. Confirmez où ça fait mal. dig direct à l’autoritatif ; comparez interne vs externe.
  2. Trouvez le limiteur. Drops vs CPU vs latence amont (utilisez les tâches ci‑dessus).
  3. Appliquez la contention en bordure. Limitez par source, puis par qtype/qname, ensuite limitez la taille des réponses.
  4. Stabilisez la latence p95. Une « erreur rapide » vaut souvent mieux qu’un succès lent en DNS, car le succès lent entraîne des retries.
  5. Réduisez temporairement les fonctionnalités coûteuses. Désactivez la journalisation verbeuse ; considérez minimiser certaines réponses si votre logiciel le supporte sans risque.
  6. Scalez si vous pouvez le faire proprement. Plus d’instances derrière anycast/unicast NS, mais assurez‑vous de ne pas juste répliquer une mauvaise config.

Phase 2 : après le pic (réduire la probabilité la prochaine fois)

  1. Classifiez le trafic. Réflexion ? NXDOMAIN ? Pic légitime ? Client malveillant ?
  2. Corrigez les incitations économiques. Augmentez les TTL, réduisez la taille des réponses, minimisez l’amplification, et bloquez la récursion ouverte.
  3. Automatisez les garde‑fous. Règles de limitation approuvées à l’avance et toggles sûrs ; tableaux de bord montrant le mix qtype et le taux NXDOMAIN.
  4. Rédigez un addendum d’incident en une page. Ce que vous avez changé, ce que vous avez observé, et quels compteurs l’ont prouvé.

FAQ

1) Dois‑je limiter par adresse IP pour le DNS ?

Oui, mais considérez‑le comme un instrument brutal. Les limites basées sur l’IP peuvent punir les populations NATées et les grands résolveurs publics. Combinez‑les avec des contrôles qtype/qname.

2) Quelle est la première limitation la plus sûre à appliquer pendant une attaque ?

Commencez par un shaping en bordure ciblant les motifs clairement abusifs : NXDOMAIN excessif par source, qtypes suspects (rafales ANY, inondations TXT), et réponses surdimensionnées. Evitez les plafonds globaux.

3) Le fallback TCP est‑il bon ou mauvais ?

Les deux. Le TCP réduit l’utilité des réflexions usurpées et évite la fragmentation, mais il coûte plus par requête et peut aussi être ciblé. Prévoyez une capacité TCP, sans forcer tout dans TCP.

4) Les TTL courts aggravent‑ils les attaques DNS ?

Ils aggravent tout pic, attaque ou non, parce que les résolveurs doivent rafraîchir plus souvent. Utilisez des TTL courts seulement là où vous avez vraiment besoin d’un basculement rapide.

5) Comment savoir si j’ai été utilisé pour amplification ?

Cherchez beaucoup de requêtes avec sources usurpées (difficile à prouver directement), des qtypes inhabituels (DNSKEY, ANY), et un ratio octets réponse/requête étrange. Des échantillons de paquets aident.

6) Puis‑je simplement compter sur mon fournisseur DNS et arrêter de m’en soucier ?

Vous pouvez externaliser l’infrastructure, pas la responsabilité. Vous avez toujours besoin de TTL sensés, d’un contenu de zone raisonnable, et d’un plan d’incident. Les fournisseurs ne peuvent pas corriger une zone conçue pour amplifier.

7) Quelle est la différence entre NXDOMAIN et NODATA, et pourquoi est‑ce important ?

NXDOMAIN signifie que le nom n’existe pas. NODATA signifie que le nom existe mais pas pour le type demandé. Les attaques utilisent les deux pour contourner les caches ; le TTL de cache négatif détermine la fréquence des réinterrogations.

8) Dois‑je désactiver complètement les requêtes ANY ?

Sur l’autoritatif, vous devriez au moins les minimiser. Certains clients demandent encore ANY pour du diagnostic. Fournissez une réponse minimale et sûre plutôt qu’une réponse énorme.

9) Pourquoi mon DNS « fonctionne » depuis le VPC mais pas depuis Internet ?

Le trafic interne évite la congestion de bord et le filtrage amont. Les pannes externes indiquent souvent une saturation PPS, des problèmes de scrubbing DDoS, des changements de routage anycast, ou des problèmes MTU/fragmentation.

10) Quelles métriques doivent figurer sur le tableau de bord DNS ?

QPS, PPS, latence p50/p95, ratio UDP vs TCP, taux NXDOMAIN, top qtypes, distribution des tailles de réponses, drops noyau, et hit/miss du cache (pour la récursion).

Conclusion : prochaines étapes qui réduisent vraiment les interruptions

Si vous voulez que le DNS survive aux pics sans interruption, arrêtez de penser en termes de « bloquer l’attaquant ». Pensez à protéger la latence pour le trafic légitime tout en rendant l’abus coûteux et peu intéressant.

  1. Mettez en place un edge DNS‑aware (dnsdist ou équivalent) et pré‑stabilisez un jeu de règles d’urgence pour les inondations NXDOMAIN et les qtypes abusifs.
  2. Limitez la taille EDNS UDP et vérifiez le comportement DNSSEC pour éviter de vous fragmenter en pannes.
  3. Corrigez la stratégie TTL : augmentez les TTL là où vous le pouvez, relevez le TTL de cache négatif à une valeur sensée, et gardez le basculement rapide pour les rares enregistrements qui en ont vraiment besoin.
  4. Instrumentez les drops et la latence au niveau NIC/noyau et démon. Les graphiques CPU seuls transforment les incidents en folklore.
  5. Répétez le playbook trimestriellement. Le moment d’apprendre quel bouton fait mal aux clients n’est pas pendant une attaque.

Le DNS est censé être ennuyeux. Rendez‑le à nouveau ennuyeux—en l’ingénierant comme s’il était critique, parce que c’est le cas.

← Précédent
L’effondrement de Nokia : comment le roi du téléphone a raté le virage
Suivant →
Proxmox pvedaemon.service en échec : pourquoi les tâches ne démarrent pas et comment réparer

Laisser un commentaire