Mettre en place un rate limiting anti-DDoS L7
Section intitulée « Mettre en place un rate limiting anti-DDoS L7 »Un déni de service distribué de couche 7, ou DDoS (Distributed Denial of Service), vise l’application plutôt que le débit réseau brut. Quelques requêtes coûteuses, répétées avec discipline, suffisent à épuiser les connexions, les travailleurs, la base de données ou un service tiers facturé à l’appel.
Le rate limiting ressemble au contrôle d’accès d’une salle de concert : laisser entrer les personnes au rythme que le lieu peut absorber, puis arrêter celles qui tentent de bloquer l’entrée en revenant sans cesse. Le but est de préserver les visiteurs normaux quand certains transforment une file d’attente en sport de combat.
→ Lire l’explication complète de la marmotte
Le compromis est frontal : limiter trop bas refuse du trafic légitime, limiter trop haut ne protège rien quand cela compte. La recommandation est de filtrer grossièrement avant l’application, puis de limiter finement par identité applicative. Un seul quota global est une décoration de sécurité, pratique pour les slides et inutile dès que l’attaquant varie ses adresses.
Exposition DDoS de couche 7 et inventaire des endpoints
Section intitulée « Exposition DDoS de couche 7 et inventaire des endpoints »-
Lister les points de terminaison exposés. Un endpoint est une route HTTP (Hypertext Transfer Protocol) accessible depuis un client. Recenser les routes publiques, leurs méthodes, leur exigence d’authentification et leurs dépendances : base de données, cache, moteur de recherche, stockage objet, fournisseur d’identité, service de messagerie.
Classer en priorité :
/search, recherche plein texte, autocomplétion et filtres combinables ;/exports, génération de fichiers, rapports et agrégats ;/login, réinitialisation de mot de passe et envoi de codes ;- routes d’API (Application Programming Interface) qui déclenchent des calculs ou des appels tiers ;
- endpoints de diagnostic accidentellement publics, notamment métriques et prévisualisations.
-
Mesurer le coût réel de chaque route. Le temps de réponse seul ne suffit pas. Une requête peut répondre vite grâce à un pool saturé en arrière-plan, puis transformer la minute suivante en exercice de spéléologie dans les journaux. Capturer au minimum : durée p50, p95 et p99, nombre de requêtes vers la base, consommation de processeur, mémoire, connexions ouvertes et appels sortants.
Instrumenter chaque requête avec son nom de route normalisé, jamais avec l’URL brute.
/users/123et/users/456doivent alimenter la même série/users/:id, sinon la cardinalité des métriques devient elle-même une attaque de déni de service. Les fondations d’observabilité et d’architecture doivent déjà fournir métriques, traces et journaux corrélables. -
Déterminer la capacité avant l’incident. Fixer une charge stable, par exemple avec 20, puis 40, puis 80 requêtes concurrentes. La capacité retenue est le dernier palier où la latence p95 reste dans l’objectif de service, où les erreurs restent sous le seuil accepté et où les files de connexions ne croissent pas continûment.
Pour une route d’export, compter les tâches simultanées et non les requêtes HTTP. Une réponse
202 Acceptedpeut coûter une tâche d’arrière-plan pendant dix minutes. Limiter uniquement la route de soumission sans borner la file revient à déplacer l’incendie vers la remise suivante. -
Attribuer une classe de coût. Une recherche indexée peut accepter plusieurs requêtes par seconde et par identité. Un export lourd doit souvent accepter une création par minute, avec un plafond de tâches actives. L’authentification doit distinguer l’adresse source, le compte ciblé et l’empreinte du client : limiter seulement par compte permet le blocage ciblé d’un utilisateur, limiter seulement par adresse laisse passer un botnet.
Seuils de rate limiting et identités de comptage
Section intitulée « Seuils de rate limiting et identités de comptage »Le rate limiting mesure un nombre d’événements dans une période. Deux paramètres comptent : le débit soutenu et le burst, c’est-à-dire la petite rafale tolérée. Une fenêtre fixe de 60 secondes est facile à exploiter à la frontière des minutes. Préférer le seau à jetons : chaque identité reçoit des jetons à débit constant, une requête consomme un jeton, une courte rafale reste possible dans la limite du seau.
Construire la clé de comptage selon la route :
| Route | Clé primaire | Clé secondaire | Politique recommandée |
|---|---|---|---|
| Recherche publique | adresse source validée | empreinte de session | débit modéré, burst court |
| Connexion | adresse source | compte ou identifiant demandé | plafonds indépendants |
| API authentifiée | clé API ou identifiant de service | adresse source | quota par contrat, plafond anti-abus |
| Export | identifiant utilisateur | organisation ou locataire | file bornée, concurrence limitée |
L’adresse IP (Internet Protocol) n’est pas une identité. Les réseaux d’entreprise, les opérateurs mobiles et les relais partagés concentrent des utilisateurs légitimes. À l’inverse, un attaquant distribue des requêtes sur des milliers d’adresses. L’identité authentifiée devient donc la clé principale après connexion, mais l’adresse reste nécessaire avant authentification et comme signal de détection.
Ne faire confiance aux en-têtes X-Forwarded-For ou Forwarded que s’ils sont ajoutés par un proxy connu et supprimés à l’entrée publique. Sans cette règle, l’attaquant choisit l’adresse comptée dans l’en-tête. C’est moins du rate limiting que du libre-service.
Les seuils doivent venir des essais de capacité. Si une recherche coûteuse tient 30 requêtes par seconde sur une instance avec la latence cible, réserver une marge pour les pointes légitimes et les défaillances partielles. Commencer, par exemple, par 10 requêtes par seconde par identité, un burst de 15, et un plafond global inférieur à la capacité mesurée. Le chiffre exact n’est pas universel, la méthode l’est.
Filtrage reverse proxy et limitation applicative
Section intitulée « Filtrage reverse proxy et limitation applicative »Le premier niveau doit vivre au reverse proxy ou au CDN (Content Delivery Network), devant le code applicatif. Il bloque les rafales anonymes, les méthodes non attendues, les corps excessifs et les sources manifestement abusives sans consommer de connexions applicatives. Un CDN absorbe du volume, pas une requête légitime mais coûteuse envoyée avec un jeton volé. La nuance ne tient pas sur une brochure vendeur, ce qui explique qu’elle y soit rarement.
Le second niveau vit dans l’application ou un composant proche, avec un stockage partagé tel que Redis. Sans état partagé, deux instances accordent chacune leur quota, et un équilibrage de charge double mécaniquement le débit autorisé. En déploiement multi-zone, Redis doit être disponible depuis toutes les instances avec une latence prévisible. Une base relationnelle n’est pas un compteur de rafales : lui demander ce métier sous attaque revient à engager le gardien de la porte comme comptable de l’émeute.
Exemple Nginx et Redis reproductible
Section intitulée « Exemple Nginx et Redis reproductible »Cet exemple configure Nginx pour limiter le trafic anonyme par adresse source, puis réserve la granularité par clé API à l’application. La variable $binary_remote_addr est compacte et évite de stocker l’adresse en texte.
# Zone partagée : 10 Mo stockent environ 160 000 états IPv4.limit_req_zone $binary_remote_addr zone=anon_api:10m rate=10r/s;limit_req_status 429;limit_req_log_level warn;
server { listen 443 ssl http2; server_name api.example.net;
# Le proxy frontal doit être la seule source autorisée à fournir l'IP client. set_real_ip_from 192.0.2.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on;
location /api/ { # Autorise une rafale de 20, rejette l'excédent sans mise en attente. limit_req zone=anon_api burst=20 nodelay;
proxy_set_header X-Request-ID $request_id; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://application_pool; }}Le statut 429 Too Many Requests doit inclure Retry-After quand la durée d’attente est calculable. Documenter cette réponse pour les consommateurs d’API évite que leurs clients transforment une limitation temporaire en boucle de réessai furieuse. Les mécanismes d’identité et de clés API appartiennent au domaine des identités et contrôles d’accès, pas à une adresse IP maquillées en identité.
Dans l’application, utiliser un script atomique Redis pour décrémenter le seau et calculer sa recharge. Une séquence GET, calcul local, puis SET n’est pas atomique : sous concurrence, elle accorde plus de jetons que prévu. Le verrouillage distribué ajouté pour corriger cela finit souvent par coûter plus cher que le problème initial.
Tests k6, supervision et déploiement progressif
Section intitulée « Tests k6, supervision et déploiement progressif »-
Écrire un scénario normal. k6 doit reproduire des parcours attendus : connexion, recherche, consultation, attente réaliste entre appels. Mesurer le taux de
429, la latence et les erreurs métier. Un test qui martèle la même route sans pause valide une mitrailleuse, pas un comportement utilisateur. -
Écrire un scénario abusif isolé. Faire croître la charge sur une route coûteuse avec plusieurs identités, plusieurs adresses si l’environnement le permet, et des requêtes valides. Vérifier que le proxy retourne
429avant saturation et que l’application conserve ses objectifs pour un flux normal simultané.
// rate-limit.js : exécuter avec k6 run rate-limit.jsimport http from 'k6/http';import { check, sleep } from 'k6';
export const options = { scenarios: { normal: { executor: 'constant-vus', vus: 5, duration: '60s', exec: 'normal' }, abuse: { executor: 'constant-arrival-rate', rate: 40, timeUnit: '1s', duration: '60s', preAllocatedVUs: 50, exec: 'abuse' }, },};
export function normal() { const r = http.get(`${__ENV.BASE_URL}/api/search?q=network`); check(r, { 'normal n est pas limite': (x) => x.status === 200 }); sleep(2);}
export function abuse() { const r = http.get(`${__ENV.BASE_URL}/api/search?q=network`); check(r, { 'abus est bloque ou servi': (x) => x.status === 200 || x.status === 429 });}-
Déployer en mode observation. Journaliser d’abord les décisions qui auraient refusé une requête, avec la route, le type de clé et le seuil, sans enregistrer jeton, cookie ni clé API. Comparer les refus simulés aux parcours connus. Passer ensuite au blocage sur les routes les plus coûteuses, puis étendre.
-
Superviser et préparer la reprise. Alerter sur le taux de
429, les refus par clé, la saturation Redis, les erreurs applicatives et la latence p95 des routes protégées. Sauvegarder la configuration de proxy, les scripts Redis et les seuils avec le code. Les compteurs de rate limiting n’ont généralement pas besoin de sauvegarde : les restaurer après sinistre recrée des états périmés. En revanche, la perte du stockage partagé doit avoir une politique explicite : refuser les routes coûteuses par défaut, ou appliquer un plafond local très conservateur.
Le rate limiting ne protège pas contre une vulnérabilité applicative, une saturation de bande passante en amont, un épuisement causé par une requête unique légitime mais monstrueuse, ni le vol d’une clé API. Il faut compléter par cache, quotas métier, limites de taille, files bornées, protection anti-automatisation et révocation des identifiants compromis. Pour la partie réseau, consulter les mécanismes de filtrage et d’exposition réseau.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans limitation de débit applicative, la porte reste ouverte au rythme choisi par l’appelant. Une poignée de clients suffit à saturer les pools de connexions et les files de tâches, et la panne se propage aux dépendances partagées : base, cache, fournisseur d’identité, services tiers facturés à l’appel, dont la note grimpe sans plafond. L’élasticité automatique ne corrige rien, elle achète du temps au prix fort. La détection s’appauvrit aussi : sans compteurs par identité ni taux de refus à observer, rien ne distingue une pointe légitime d’un abus distribué, et les journaux gonflent au point de gêner l’analyse. Aucun levier de bridage n’existe pendant l’incident, ce qui laisse pour seules options l’arrêt d’une route ou le blocage large, avec les utilisateurs normaux dans la même charrette. Les tentatives répétées sur l’authentification passent alors sans frein.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Une attaque de déni de service cherche à rendre un service inaccessible en lui envoyant trop de demandes. Certaines demandes sont très coûteuses : chercher dans beaucoup de données, fabriquer un fichier ou vérifier une connexion. La première étape consiste à repérer ces fonctions et à mesurer combien de demandes elles supportent avant de ralentir ou de produire des erreurs.
Ensuite, on fixe des limites différentes selon la fonction et selon l’identité de la personne ou du programme qui appelle le service. Une recherche peut accepter plusieurs demandes rapprochées. La création d’un gros fichier doit être beaucoup plus rare. Avant qu’une personne soit reconnue, le système compte aussi les demandes provenant de la même adresse réseau, mais cette adresse ne suffit pas à identifier quelqu’un.
Un premier filtre placé devant l’application bloque les rafales grossières. L’application applique ensuite des limites plus précises pour chaque compte ou clé d’accès. Les compteurs doivent être partagés entre les machines qui exécutent l’application, sinon chaque machine accorde sa propre limite.
Avant activation, un programme de test envoie à la fois un trafic normal et un trafic excessif. Le résultat attendu est que les demandes anormales reçoivent un refus temporaire, tandis que les demandes normales continuent de fonctionner. Si le stockage des compteurs tombe en panne, les fonctions coûteuses doivent être limitées davantage, car continuer sans contrôle transforme une panne secondaire en saturation générale.
À lire aussi
- Défendre un DDoS volumétrique et applicatifDifférencier, détecter et contenir les attaques par déni de service distribué volumétriques et applicatives avec une défense en couches.
- Attaque cache deception CDN et contre-mesuresDémonstration en laboratoire de l’attaque cache deception contre un CDN, ses conditions, ses impacts et les contre-mesures d’architecture.
- Configurer un WAF sans casser les fonctions métierGuide pratique pour déployer un pare-feu applicatif web en observation, calibrer ses règles et activer le blocage sans casser les usages légitimes.
- Circuit breaker et bulkhead contre la propagation des pannesLes patterns circuit breaker et bulkhead limitent la propagation des défaillances applicatives et réduisent l'impact indirect des attaques par déni de service.
Pages voisines
La citent
- Circuit breaker et bulkhead contre la propagation des pannes
- Cloud networking, VPC/VNet, CDN et équilibrage
- Défendre un DDoS volumétrique et applicatif
- Docker ou Podman en auto-hébergement : root, rootless, isolation
- Fenêtre de contexte et mémoire d’un LLM local
- Sécuriser l'accès des flottes de véhicules connectés
- Sécuriser la traçabilité RFID et IoT du fret
- Sécuriser une API gateway comme point de contrôle
Mettre en place un rate limiting anti-DDoS L7
Elle cite
: les deux pages se citent l’une l’autre.
