Une limite de charge bien posée refuse l'abus et laisse passer les utilisateurs légitimes ; mal posée, elle fait l'inverse. Cette leçon enseigne les quatre familles de limites de Nginx, le débit (limit_req), les connexions simultanées (limit_conn), la taille des requêtes (client_max_body_size) et les délais accordés à un client, puis le point qui décide de tout : la clé qui regroupe les appelants. Elle s'adresse à une personne qui publie déjà une API derrière Nginx. Elle ne traite pas la protection de l'administration et des routes, objet de la leçon Protéger et observer Nginx.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »La leçon va de la limite simple à son piège principal, la clé de regroupement.
- Poser une limite de débit avec une zone, une rafale (le nombre de requêtes en excès que Nginx tolère) et un code de refus lisible.
- Limiter les connexions simultanées et dire ce que compte réellement le compteur.
- Borner la taille du corps et les délais accordés à un client.
- Choisir une clé de regroupement que l'appelant ne peut pas forger.
- Prouver qu'un refus résulte d'un dépassement reproductible.
Prérequis
Section intitulée « Prérequis »La leçon suppose que vous savez publier une application derrière Nginx et lire un code de statut HTTP.
- Publier une application avec
proxy_pass: Publier une application avec Nginx. - Le vocabulaire HTTP (méthode, en-tête, code de statut) : Lire HTTP avant de configurer un proxy.
- Valider et recharger une configuration : Installer Nginx.
- Un compte avec
sudosur une machine Debian 13.
Que limiter, et comment choisir des valeurs ?
Section intitulée « Que limiter, et comment choisir des valeurs ? »Une limite se choisit à partir du trafic légitime mesuré, jamais d'un chiffre trouvé en ligne : trop basse, elle devient une panne que vous vous infligez. Quatre familles de limites existent dans Nginx, et chacune répond à une menace différente.
| Famille | Directives principales | Ce qu'elle contient |
|---|---|---|
| Débit de requêtes | limit_req_zone, limit_req | Un client qui envoie trop de requêtes par seconde |
| Connexions simultanées | limit_conn_zone, limit_conn | Un client qui ouvre trop de connexions à la fois |
| Taille | client_max_body_size | Un corps de requête démesuré |
| Délais | client_body_timeout, client_header_timeout | Un client qui envoie très lentement |
Le tableau se lit en colonnes : la dernière dit contre quoi chaque famille protège. Elles se combinent : un client lent qui garde mille connexions ouvertes ne dépasse peut-être aucun débit, mais il épuise les connexions.
Avant de fixer une valeur, mesurez. Les journaux d'accès donnent le nombre de requêtes par client et par seconde en usage normal ; la valeur retenue se place au-dessus du pic légitime observé, avec une marge. Nginx permet même de tester sans refuser : la directive limit_req_dry_run on; (disponible depuis la version 1.17.1) compte les dépassements dans la zone sans limiter personne : vous posez la limite en observation, puis vous l'appliquez pour de bon une fois la valeur jugée sûre.
Comment limiter le débit avec limit_req ?
Section intitulée « Comment limiter le débit avec limit_req ? »limit_req_zone déclare une zone mémoire, une clé et un débit ; limit_req applique la zone à un location. La zone est l'espace partagé entre les workers où Nginx retient l'état de chaque clé. Le débit s'exprime en requêtes par seconde (r/s) ou par minute (r/m), et la clé décide qui est compté ensemble. La leçon Protéger et observer Nginx en montre le cas minimal ; ici, on dimensionne la limite et on choisit sa clé.
http { limit_req_zone $binary_remote_addr zone=api_public:10m rate=5r/s; limit_req_zone $binary_remote_addr zone=api_admin:10m rate=1r/s;
server { listen 80; server_name api.lab.test;
location /public { limit_req zone=api_public burst=10 nodelay; limit_req_status 429; proxy_pass http://127.0.0.1:18098; }
location /admin { limit_req zone=api_admin burst=3 nodelay; limit_req_status 429; proxy_pass http://127.0.0.1:18098; } }}Deux points se lisent dans cet exemple. Chaque route a sa propre zone : le compteur de /admin ne partage rien avec celui de /public, donc marteler l'une ne ferme pas l'autre. Les valeurs diffèrent aussi : une route d'administration reçoit moins de trafic légitime et mérite une limite plus stricte.
La rafale (burst) est la file que Nginx accepte au-dessus du débit. Sans elle, Nginx refuse toute requête qui arrive avant que l'intervalle de rate ne soit écoulé : à 5 r/s, une deuxième requête dans les 200 ms est refusée, ce qui est déraisonnable pour une page qui charge plusieurs ressources d'un coup. Avec burst=10, jusqu'à dix requêtes en excès sont admises. Sans nodelay, elles sont retardées pour respecter le débit ; avec nodelay, elles passent immédiatement et occupent des places de la file, qui se libèrent au rythme du débit.
Le code de refus compte autant que la valeur. Par défaut, limit_req répond 503, qui se lit comme « service indisponible » : un client bien élevé croit à une panne et réessaie plus fort. limit_req_status 429; rend 429 (Too Many Requests), le code prévu pour demander au client de ralentir. Une directive voisine règle la gravité inscrite au journal, limit_req_log_level.
Reste la taille de la zone. La variable $binary_remote_addr est l'adresse du client sous forme compacte, 4 octets en IPv4 et 16 en IPv6, ce qui garde la clé petite. Selon la documentation de Nginx, l'état d'une clé occupe 64 octets sur plateforme 32 bits et 128 octets sur 64 bits : un mégaoctet retient environ seize mille états de 64 octets, ou environ huit mille états de 128 octets, le cas d'une machine actuelle. Avec 10m, la zone retient donc de l'ordre de quatre-vingt mille adresses sur 64 bits. Si elle se remplit, Nginx supprime les états les plus anciens ; s'il n'a toujours pas de place, il refuse la requête : une zone sous-dimensionnée refuse du trafic légitime.
Comment limiter les connexions simultanées avec limit_conn ?
Section intitulée « Comment limiter les connexions simultanées avec limit_conn ? »limit_conn plafonne le nombre de connexions ouvertes en même temps pour une clé, là où limit_req plafonne un débit. Les deux ne mesurent pas la même chose : un client qui télécharge des fichiers lourds en parallèle envoie peu de requêtes par seconde, mais occupe de nombreuses connexions pendant longtemps.
http { limit_conn_zone $binary_remote_addr zone=connexions:10m;
server { location /telechargements/ { limit_conn connexions 4; limit_conn_status 429; limit_rate 2m; } }}Ici, une adresse ne peut pas dépasser quatre connexions simultanées vers /telechargements/, et limit_rate 2m plafonne le débit de chaque connexion à deux mégaoctets par seconde. Le plafond de bande passante d'un client est donc le produit des deux : quatre fois deux mégaoctets, soit huit par seconde.
La portée du compteur est celle de la zone : une zone est partagée par tous les location qui la nomment, et sépare les clés. Seules comptent les connexions dont l'en-tête de requête a été entièrement lu et qui sont en cours de traitement ; en HTTP/2 et HTTP/3, chaque requête simultanée compte comme une connexion. Comme pour limit_req, le code de refus par défaut est 503 et limit_conn_status 429; le change.
Quelle clé choisir pour regrouper les appelants ?
Section intitulée « Quelle clé choisir pour regrouper les appelants ? »La clé est le choix qui décide si la limite protège ou nuit : regrouper par adresse IP pénalise tous les utilisateurs d'un NAT, et regrouper par un en-tête que l'appelant choisit lui-même ne limite personne. Un NAT (Network Address Translation) fait partager une seule adresse publique à de nombreux utilisateurs, par exemple tous les postes d'une entreprise. Une limite par adresse y refuse tout le monde à cause de l'abus d'un seul.
Le réflexe inverse est pire. Si la clé vient d'un en-tête que l'appelant écrit, par exemple X-Forwarded-For, il lui suffit de changer sa valeur à chaque requête pour n'être jamais compté deux fois. Le schéma suivant résume l'arbitrage : suivez d'abord la question de la confiance accordée à l'appelant direct, puis celle du partage d'adresse.
Le premier point se règle avec le module realip. set_real_ip_from liste les adresses dont Nginx croit l'en-tête transmis ; tout autre appelant est traité comme direct. Déclarer set_real_ip_from 0.0.0.0/0; revient à croire n'importe qui : l'en-tête devient forgeable, et toute limite par adresse est contournée.
set_real_ip_from 127.0.0.1;real_ip_header X-Forwarded-For;Avec ces deux lignes, seul un proxy amont qui se connecte depuis 127.0.0.1 voit son X-Forwarded-For cru ; pour tout autre appelant, $remote_addr reste l'adresse de connexion, que l'appelant ne peut pas falsifier. La leçon Protéger et observer Nginx signale le même piège pour sa propre limite (derrière un relais, $binary_remote_addr désigne le relais) et traite le contrôle d'accès à l'administration ; le réglage realip qui le résout se décide ici.
Le second point, le NAT, se règle avec un identifiant propre à chaque client, par exemple une clé d'API. Un en-tête de clé d'API n'est toutefois fiable que si elle est vérifiée : sinon l'appelant invente une clé neuve à chaque requête. La technique est de ne retenir comme clé que les valeurs connues, et de retomber sur l'adresse pour toutes les autres.
map $http_x_cle_api $cle_limite { default $binary_remote_addr; partenaire-1 partenaire-1; partenaire-2 partenaire-2;}
limit_req_zone $cle_limite zone=api_public:10m rate=5r/s;Une clé inconnue n'obtient donc aucun avantage : elle est comptée par adresse, comme un visiteur anonyme. Une clé connue est comptée seule, et ne pénalise pas les autres utilisateurs qui partagent la même adresse. La limite se vérifie des deux côtés : un appelant qui forge son adresse n'échappe pas à la limite, et une autre clé n'hérite pas de la pénalité.
Comment borner la taille du corps et les délais d'un client ?
Section intitulée « Comment borner la taille du corps et les délais d'un client ? »client_max_body_size plafonne la taille du corps d'une requête et renvoie 413 (requête trop volumineuse) au-delà ; la valeur par défaut est de 1 Mo. Elle se déclare au niveau http, server ou location, donc plus strictement sur une route qui ne reçoit que de petits formulaires que sur une route de dépôt de fichiers. Fixer client_max_body_size 0; supprime la limite : c'est un choix à justifier, pas un confort.
server { client_max_body_size 1m; client_body_timeout 10s; client_header_timeout 10s;
location /depot/ { client_max_body_size 50m; proxy_pass http://127.0.0.1:18098; }}Les délais complètent la taille, mais ils ne mesurent pas la même chose. client_header_timeout court sur la réception de l'en-tête entier : si le client ne l'a pas terminé à temps, la requête est coupée avec 408 (délai d'attente dépassé), même s'il envoie un octet de temps en temps. client_body_timeout ne court que entre deux lectures successives du corps : il coupe un client qui se tait, pas un client qui envoie lentement mais sans pause. Les deux valent 60 secondes par défaut.
Cette différence dicte le dimensionnement. Un client qui distille son en-tête occupe indéfiniment une connexion si rien ne la borne : c'est l'attaque dite « lente », qu'aucune limite de débit n'attrape puisque le débit est ridicule, et c'est client_header_timeout qui la coupe. Pour le corps, un téléversement de 50 Mo depuis un mobile mal couvert dépasse dix secondes sans être abusif : un client_body_timeout de 10 secondes le laisse passer tant que chaque morceau arrive dans ce délai. Le revers est qu'un corps distillé à un rythme régulier n'est pas coupé par ce délai : limit_conn borne alors le nombre de connexions que ce client peut occuper. Choisissez les deux valeurs à partir du comportement légitime, comme les autres.
Que se passe-t-il quand la limite est atteinte ?
Section intitulée « Que se passe-t-il quand la limite est atteinte ? »À la saturation, les utilisateurs voient soit un refus, soit un retard, et le choix de burst avec ou sans nodelay décide lequel. Trois situations se rencontrent, et la valeur d'une limite se juge sur ce que chacune fait vivre à un utilisateur normal.
- Sous le débit : tout passe, sans retard.
- Dans la rafale : avec
nodelay, les requêtes passent tout de suite ; sans, elles sont retardées et la latence augmente. - Au-delà de la rafale : le refus,
429si vous avez configurélimit_req_status.
Une limite sert aussi la disponibilité : en refusant tôt un client abusif, elle protège le backend, qui garde de la capacité pour les autres. Mais une limite trop basse transforme un pic légitime, un lancement ou une page qui charge vingt ressources, en erreur visible. Rejouez la mesure du trafic normal après tout changement de valeur.
Il reste à prouver qu'un 429 est réel. Le test fiable est une rafale reproductible envoyée par un client, qui compte les codes obtenus : un dépassement doit produire des 429, et un trafic normal aucun. Pour une API, une réponse 429 peut s'accompagner d'un en-tête Retry-After, que Nginx n'ajoute pas lui-même et que vous posez avec add_header Retry-After 1 always; si vos clients le lisent ; sans always, add_header ignore les réponses d'erreur comme le 429.
for i in $(seq 1 60); do curl -s -o /dev/null -w '%{http_code}\n' "http://${IP_EDGE}/public"done | sort | uniq -cLa commande envoie soixante requêtes d'affilée vers l'adresse de la machine Nginx (IP_EDGE, à renseigner) et affiche, pour chaque code de statut, le nombre de réponses. Une limite active se reconnaît à la présence de 429 ; un code 503 à sa place signale que limit_req_status n'est pas posé. Répétez la boucle en ajoutant -H "X-Forwarded-For: 203.0.113.$i" à curl, de façon que l'en-tête change à chaque tour : si les 429 disparaissent, Nginx croit une adresse que l'appelant choisit.
Mettre en pratique : limiter un abus et garder les clients légitimes
Section intitulée « Mettre en pratique : limiter un abus et garder les clients légitimes »Le lab publie une API derrière Nginx avec des limites déjà posées, et posées de travers : un débit trop bas, une zone unique pour toutes les routes, et un set_real_ip_from qui croit n'importe quel appelant. Une politique, écrite dans un fichier de la machine, dit le débit et la rafale par route, la taille du corps et le code de refus. Vous l'appliquez avec une clé qui ne se laisse pas forger.
La validation envoie de vraies rafales : quinze requêtes légitimes d'affilée doivent passer, un abus doit recevoir un 429, un X-Forwarded-For qui change à chaque requête n'échappe pas à la limite, une autre clé d'API n'est pas pénalisée, et marteler /admin ne ferme pas /public. Elle porte donc sur limit_req, le code de refus et la clé de regroupement. Elle ne mesure ni limit_conn, ni client_max_body_size, ni les délais : ces trois sujets sont enseignés ci-dessus d'après la documentation de Nginx, et rien dans ce lab ne prouve que vos valeurs conviennent.
À retenir
Section intitulée « À retenir »- Les limites se règlent d'après le trafic légitime mesuré : une limite trop basse est une panne qu'on s'inflige.
limit_req_zonedéclare zone, clé et débit,limit_reql'applique ; une zone par route évite qu'une pénalité se propage.burstadmet une rafale au-dessus du débit : avecnodelayelle passe tout de suite, sans lui elle est retardée.limit_req_status 429rend un refus lisible : le503par défaut se lit comme une panne et invite à réessayer plus fort.limit_connplafonne les connexions simultanées, pas le débit ;client_max_body_sizerenvoie413(1 Mo par défaut,0supprime la limite).client_header_timeoutborne la réception de l'en-tête entier ;client_body_timeoutne borne que l'attente entre deux lectures du corps, jamais sa durée totale.- Regrouper par adresse pénalise tous les utilisateurs d'un NAT ; regrouper par un en-tête choisi par l'appelant ne limite personne.
set_real_ip_fromne doit lister que le proxy amont de confiance :0.0.0.0/0rendX-Forwarded-Forforgeable.- Une limite se prouve par une rafale reproductible qui compte les codes, des deux côtés : abus refusé, client légitime préservé.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Nginx : publier WebSocket, SSE et gRPC sans coupure
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications