NGINX-hastighed Limiting stopper automatiserede forespørgsler, dæmper spidsbelastninger og beskytter login-, API- og formular-endepunkter mod bots og angreb. Jeg viser dig, hvordan du definerer grænser og bruger dem til Beskyttelse mod bots anvender og ud fra dette udarbejder et robust sikkerhedskoncept til meget besøgte hjemmesider.
Centrale punkter
Væsentligt Dette er de centrale budskaber:
- Prisgrænser bremser ondsindede angreb og beskytter backend-ressourcer.
- Burst/ingen forsinkelse opfanger legitime spidsbelastninger uden at blokere brugerne.
- zoner adskiller mennesker og bots med forskellige begrænsninger.
- Logning leverer data til iterativt at skærpe grænserne.
- Integration med WAF, DDoS-beskyttelse og overvågning øges effektiviteten.
Hvorfor rate limiting stopper angreb i tide
Angribere satser på høje Anmodningsfrekvenser, for at misbruge login-formularer, overbelaste API’er eller automatisk scrape indhold. Derfor begrænser jeg antallet af forespørgsler pr. nøgle – som regel pr. IP-adresse – og beslutter, om jeg skal begrænse dem, forsinke dem eller svare med en 429-fejl. På den måde holder jeg bottrafik væk fra CPU, database og applikationslogik og lader legitime brugere komme igennem. Særligt følsomme stier som /login, /auth, /xmlrpc.php eller ressourcekrævende søgninger drager stor fordel heraf. Kilden til denne fremgangsmåde er Nginx-dokumentation om ngx_http_limit_req_module.
Sådan fungerer NGINX-modulet i praksis
Modulet fungerer efter princippet om Utæt spand-Princip: For hver nøgle gemmer NGINX tællerstande i en zone og sammenligner dem med den tilladte hastighed. Typiske nøgler er $binary_remote_addr for IP-adresser, tokens for API-nøgler eller afledte værdier via map. Hvis en klient vedvarende overskrider hastigheden og burst-bufferen, afviser NGINX anmodningen, inden den når backenden. Det sparer regnetid og reducerer ventetider for ægte besøgende. Reaktionen indstiller jeg til 429 Too Many Requests eller eventuelt en anden Statuskode um.
Konfiguration: Forklaret trin for trin
Jeg starter med en zone i http-sektionen, indstiller en moderat hastighed og aktiverer den målrettet på følsomme stier. Ved kortvarige spidsbelastninger definerer jeg en burst, eventuelt med nodelay, for at undgå pludselige afvisninger. Derefter tester jeg i staging-miljøet og analyserer logfilerne, før jeg tager det i brug i produktionsmiljøet. På den måde undgår jeg unødvendige spærringer for ægte brugere. Et kortfattet eksempel illustrerer dette Syntaks håndgribelig:
# http {}
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
server {
location /api/ {
limit_req zone=req_limit_per_ip burst=20 nodelay;
limit_req_status 429;
}
location /login {
limit_req zone=req_limit_per_ip burst=5;
limit_req_status 429;
}
}
Bot-beskyttelse med zoner og user-agent-logik
IP-baserede begrænsninger er sjældent tilstrækkelige mod distribuerede botnet, derfor opdeler jeg trafikken i zoner: Mennesker får mere generøse værdier, mens generiske crawlere får strengere. Med »map« vurderer jeg user-agenter, genkender godkendte bots som Googlebot og tildeler dem deres egne, nøje overvågede grænser. For ukendte scrapere sætter jeg strenge grænser på ressourcekrævende ruter. Hvis der dukker mønstre op, skærper jeg restriktionerne dynamisk, indtil Vurder igen er inden for det normale.
Finjustering: hastighed, burst, nodelay og statuskoder
Rate styrer gennemstrømningen pr. sekund, Burst tillader kortvarige buffere, og nodelay afgør, om jeg foretrækker buffering eller øjeblikkelig gennemladning. Jeg starter moderat, f.eks. 10r/s med burst 20 på API'er, og finjusterer efter loganalyse. For login-ruter indstiller jeg f.eks. 1r/s med en lille burst for at bremse brute-force-angreb. Ved overskridelser returnerer jeg 429, fordi klienter dermed klare sig og at »Retry«-logikken fungerer korrekt. I særlige tilfælde bruger jeg alternative koder, hvis kunderne ønsker det.
Oversigt i tabellen: Direktiver og anvendelse
Det følgende Bord opsummerer de vigtigste retningslinjer og viser, hvornår de er relevante.
| direktiv | Effekt | Eksempel | Typisk brug |
|---|---|---|---|
| limit_req_zone | Angiv nøgle, zone og Vurder fast | limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s; | Grundlag pr. IP, token eller user-agent |
| limit_req | Aktiverer grænsen i Placering/Server | limit_req zone=perip burst=20 nodelay; | Finjustering pr. sti eller vHost |
| limit_req_status | Tilføjer HTTP-kode Overskridelse | limit_req_status 429; | Korrekt klientadfærd og gentagelser |
| kort | Videresender anmodninger til zoner på | map $http_user_agent $is_bot {…} | Skelnen mellem bot og menneske baseret på User-Agent |
Praksis: Målrettet beskyttelse af login-endepunktet
Jeg begrænser /login meget strengt, fordi bots bruger adgangskoder med høj Frekvens Prøve sig frem. 1 anmodning pr. sekund med burst 3 forhindrer massiv gætning uden at ramme rigtige brugere for hårdt. Derudover registrerer jeg gentagne fejlforsøg i loggen for midlertidigt at blokere IP-adresser. Kombineret med 2FA og eventuelt Captcha mindskes belastningen på databasen og sessionhåndteringen mærkbart. På den måde holder jeg antallet af fejlforsøg nede og sikrer, at Adgang klar og stabil.
Praksis: At stille API’er til rådighed på en retfærdig og kontrolleret måde
API’er kræver klare Odds, så enkelte klienter ikke optager hele båndbredden. For generelle ruter indstiller jeg 10r/s og burst 20, mens jeg anvender strengere værdier for dyre slutpunkter. Hvis der er tokens eller API-nøgler til rådighed, begrænser jeg pr. token i stedet for pr. IP. Det skaber retfærdighed mellem kunderne og forhindrer misbrug. En mere dybdegående introduktion findes i min vejledning til API-ratebegrænsning, som sætter begrebet ind i en bredere sammenhæng.
Overvågning, logning og iterativ finjustering
Jeg logger 429-svarene sammen med Nøgle (f.eks. IP eller token) og sti for at genkende mønstre. Pludselige stigninger på få stier tyder på scraping eller brute-force-angreb; en jævnt fordelt belastning tyder på botnet. Med disse data indfører jeg kun begrænsninger, hvor det er nødvendigt, og minimerer falske positiver. Dashboards med hastigheder, fejlprocent og latenstid viser mig effekten af hver ændring. På den måde forbliver Ydelse høj, mens beskyttelsen øges.
Integration i et helhedsorienteret beskyttelseskoncept
Jeg anser rate limiting for at være et stærkt første skridt lag, men jeg kombinerer det med WAF-regler, IP-reputation og TLS-hærdning. Mod angreb med stor datamængde hjælper en forudgående DDoS-beskyttelse, der filtrerer trafikken på netværksniveau, inden NGINX skal træde i aktion. Jeg måler løbende nøgletal, indstiller alarmer ved usædvanlige spidsbelastninger og reagerer med regelopdateringer. På den måde skabes der et robust beskyttelsesnetværk ud af flere byggesten. Disse giver et praktisk overblik DDoS-strategier.
Konkrete konfigurationsmønstre for bots kontra mennesker
Jeg inddeler besøgende i kategorier ved hjælp af map og omdirigerer dem til deres egne zoner. Kendte crawlere får moderate begrænsninger, mens generiske agenter får strengere. For stier som /search eller /report er jeg strengere, da de belaster CPU’en meget. Ved gentagne overtrædelser øger jeg ikke grænserne, men spærrer adgangen midlertidigt eller flytter kontrollen over til et bot-genkendelsesmodul. På den måde forbliver Misbrugsfrekvens lav, uden at forstyrre søgemaskinerne.
Eksempel: To zoner og brugeragent-tilknytning
Følgende uddrag viser opdelingen efter Brugeragent og tildeling af passende grænser. Jeg kombinerer dette med differentierede statuskoder og logningsfelter for at kunne måle effekten præcist. Bots med generiske agenter havner i den strenge zone. Mennesker eller verificerede crawlere benytter den mere lempelige zone. Denne tilgang giver forudsigelige Gennemstrømning pr. klasse:
map $http_user_agent $is_bot {
default 0;
"~*googlebot" 0;
"~*bingbot" 0;
"~*crawler|scraper|bot" 1;
}
limit_req_zone $binary_remote_addr zone=human:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=bot:10m rate=1r/s;
server {
location / {
if ($is_bot) {
limit_req zone=bot burst=5;
}
if ($is_bot = 0) {
limit_req zone=human burst=20 nodelay;
}
limit_req_status 429;
}
}
Fejlhåndtering: Korrekt kommunikation ved fejlkode 429
Hos Limits leverer jeg en klar Svar med en angivelse af, hvornår det er hensigtsmæssigt at prøve igen. For API’er skal den gyldige »Retry-After«-header være til stede, så klienter kan anvende »Backoff«. Menneskelige brugere får en kort forklaring uden tekniske detaljer. Det reducerer antallet af supportanmodninger og sikrer en forståelig adfærd. En overskuelig UX gør grænser acceptable og forhindrer frustration.
Webhost, netværk og kerne: styrke grundlaget
Høj mængde legitim trafik og sikkerhedsforanstaltninger kræver pålidelige Ressourcer og fornuftige standardindstillinger på netværksniveau. Jeg sørger for, at NGINX-versionerne er opdaterede, at der er tilstrækkelig RAM til zoner, og at der er beskyttelsesfunktioner mod transportangreb. Mod SYN-floods hjælper det at aktivere TCP SYN-cookies i kernen, så forbindelser ikke hænger fast. Alt i alt aflaster dette NGINX for unødvendig belastning. På den måde fokuserer jeg begrænsningerne på HTTP-lagene og holder Gennemstrømning stabil.
Kort sagt: Sådan bruger jeg NGINX-ratebegrænsning effektivt
Jeg begrænser antallet af forespørgsler pr. nøgle, afskærmer kritiske stier og holder bots på afstand med strenge zoner. Burst og nodelay hjælper med at tillade legitime spidsbelastninger uden at fremme misbrug. Via 429-logfiler kalibrerer jeg løbende værdierne og skærper grænserne kun der, hvor der er behov for det. I kombination med WAF, DDoS-forsvar, overvågning og kernel-hærdning skabes et robust beskyttelseskoncept. Den, der konsekvent implementerer dette, reducerer bot-trafikken markant og bevarer Ydelse selv under belastning.
Elementer, der ofte mangler i praksis
I mange opsætninger mangler der nogle afgørende komponenter, som mærkbart øger effekten af rate limiting:
- Den egentlige klient-IP bag proxyservere: Uden korrekt håndtering af den reelle IP-adresse begrænser NGINX ofte load balancerens IP-adresse – begrænsningerne gælder da for alle de brugere, der er samlet bagved.
- Tørtest (Dry-Run): Grænser aktiveres „blindt“. Det er bedre først at registrere, hvor ofte en grænse ville være blevet udløst.
- Finkornede nøgler: I stedet for kun at begrænse adgangen pr. IP-adresse, er det en god idé at indføre begrænsninger pr. API-token, session eller bruger for at sikre større retfærdighed.
- Samspil med limit_conn: Parallelle forbindelser og anmodningsfrekvenser dækker forskellige mønstre for misbrug.
- Målrettede undtagelser: Sundhedstjek, webhooks eller interne tjenester kræver ofte mere fleksible begrænsninger eller slet ingen.
Reverse proxy: sikker analyse af den reelle klient-IP-adresse
Hvis NGINX kører bag en load balancer, indstiller jeg Real-IP-direktiverne, så $binary_remote_addr afspejler den reelle klient. Jeg stoler kun på netværk, som jeg selv ejer, og aktiverer rekursiv evaluering:
http {
# Pålidelige proxy-IP-intervaller (eksempel)
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
# Tilføj eventuelt offentlige LB-/CDN-intervaller
real_ip_header X-Forwarded-For;
real_ip_recursive on;
limit_req_zone $binary_remote_addr zone=perip:20m rate=10r/s;
}
Uden denne indstilling vil en begrænsning ellers ramme mange brugere på én gang, selvom de ikke har gjort noget forkert. Efter opsætningen tjekker jeg i adgangslogfilerne, om den forventede klient-IP-adresse vises.
Nøglestrategi: IP, bruger, token og sti
Det valgte nøglekoncept er afgørende for retfærdighed og effekt. Her er nogle gennemprøvede modeller:
- Pro IP ($binary_remote_addr): Hurtig at sætte i drift, velegnet til /login og anonyme slutpunkter.
- Per API-token: Retfærdighed mellem kunderne; beskytter mod NAT-bundling. Jeg udtrækker tokens ved hjælp af map.
- Pr. sti-klasse: Begræns dyre slutpunkter separat, f.eks. /search i højere grad end /status.
map $http_authorization $api_token {
default "";
"~*^Bearer\s+(.+)$" $1;
}
limit_req_zone $api_token zone=per_token:30m rate=5r/s;
server {
location /api/ {
# Gælder kun, hvis der findes et token
limit_req zone=per_token burst=10;
limit_req_status 429;
}
}
Vigtigt: Høj nøglekardinalitet bruger hukommelse i zonen. Sørg for at afsætte bufferplads, og hold øje med udnyttelsen.
Lagring og dimensionering af zonerne
Zonen gemmer metadata for hver aktiv nøgle. Forbruget ligger på nogle få dusin byte pr. post plus overhead. Herudfra konkluderer jeg:
- Hvis der er mange samtidige IP-adresser/tokens, vælger jeg større zoner, f.eks. 50–100 MB.
- Jeg starter med en ret generøs indstilling og læser NGINX-logfilerne: „shared memory zone is full“ indikerer, at der skal foretages en finjustering.
- Ubrugte nøgler udløber efter kortvarig inaktivitet; spidsbelastninger er vigtigere end dagsgennemsnittet.
Præcis anvendelse af burst og nodelay
Uden at nodelay NGINX placerer overskridelser i burst-bufferen og forsinket Anmodninger. Med nodelay Tilladte burst-anmodninger slippes straks igennem, mens overskydende afvises. Min fremgangsmåde:
- Interaktive ruter (HTML): helst uden nodelay for at skabe korte ventetider i stedet for en direkte 429-fejl.
- API'er: ofte med »nodelay«, så klienterne tydeligt modtager en 429-fejl og anvender backoff.
- Dyre slutpunkter: en lille burst for at udjævne spidsbelastninger i backend.
Tørkørsel, logniveau og evaluering
Inden jeg aktiverer begrænsningerne, aktiverer jeg Dry-Run og justerer log-niveauet. På den måde kan jeg se effekten uden risiko:
server {
location /api/ {
limit_req zone=perip burst=20;
limit_req_dry_run on; # kun logge, ikke blokere
limit_req_log_level notice; # mindre alvorligt end 'error'
}
}
Derefter analyserer jeg adgangsdata fra de seneste 3–7 dage, identificerer hotspots, justerer rate/burst og deaktiverer først derefter dry-run.
429-fejlhåndtering: HTML, JSON og Retry-After
For at sikre en god brugeroplevelse skelner jeg mellem browsere og API-klienter og indstiller Retry-After. Sådan kommunikerer jeg grænser tydeligt:
map $http_accept $wants_json {
default 0;
"~*application/json|/json" 1;
}
server {
error_page 429 = @rate_limited;
location @rate_limited {
add_header Retry-After 2 always;
if ($wants_json) {
add_header Content-Type application/json;
return 429 '{"error":"too_many_requests","retry_after":2}';
}
return 429 "Prøv igen senere.";
}
}
API'er kan reagere programmatisk, og brugerne får en forståelig meddelelse.
Kombinering af limit_req og limit_conn
limit_req angiver gennemstrømning pr. tidsvindue, limit_conn begrænser antallet af samtidige forbindelser. Mod downloads, chatty-klienter eller HTTP/2-oversvømmelser kombinerer jeg begge dele:
limit_conn_zone $binary_remote_addr zone=perip_conn:10m;
server {
location /api/ {
limit_req zone=perip burst=20 nodelay;
limit_conn zone=perip_conn 20; # maks. 20 samtidige forbindelser pr. IP
}
}
På den måde undgår jeg, at nogle få klienter ganske vist overholder hastigheden, men alligevel optager ressourcer med for mange samtidige forbindelser.
Undtagelser, sundhedstjek og interne ruter
Ikke alle paths behøver begrænsninger. Health-checks (/healthz), interne webhooks eller betalings-callbacks får deres egne locations uden limit_req – eller med lavere værdier:
server {
# ingen begrænsninger for sundhedstjek
location = /healthz { return 200 "ok"; }
# bløde begrænsninger for betalings-callbacks
location /webhooks/pay/ {
limit_req zone=perip burst=5;
}
# streng beskyttelse ved login
location = /login {
limit_req zone=perip rate=1r/s burst=3;
}
}
Granulære undtagelser reducerer antallet af falske positiver og sikrer stabile integrationer.
Mere robust zonestyring uden »if-magi«
Når det gælder opdelingen mellem „bot og menneske“, foretrækker jeg interne omdirigeringer via navngivne placeringer. Det gør konfigurationen overskuelig og forudsigelig:
map $http_user_agent $is_bot {
default 0;
"~*googlebot|bingbot" 0;
"~*crawler|scraper|bot" 1;
}
limit_req_zone $binary_remote_addr zone=human:20m rate=10r/s;
limit_req_zone $binary_remote_addr zone=bot:10m rate=1r/s;
server {
error_page 418 = @bot;
location / {
if ($is_bot) { return 418; } # intern omdirigering
limit_req zone=human burst=20 nodelay;
limit_req_status 429;
try_files $uri $uri/ /index.html;
}
location @bot {
limit_req zone=bot burst=5;
limit_req_status 429;
}
}
Således ender bots deterministisk i den strenge zone, mens mennesker ender i den afslappede – uden at begge grænser virker samtidigt.
Test, måling, påtagning: en pragmatisk fremgangsmåde
- Iscenesættelse: Vælg en konservativ hastighed/burst, aktiver dry-run, og kør syntetisk belastning mod hot-path.
- Røgprøver: Brug curl eller Lasttools til at generere korte bursts og kontrollér 429/Delay-adfærden.
- Produktiv-Pilot: Anvend det først på enkelte lokationer, og følg logfilerne nøje.
- Iterativ skarphedsjustering: Indfør kun begrænsninger der, hvor der ses mønstre; minimer falske alarmer.
# Eksempel: hurtig burst-test med curl
for i in {1..50}; do curl -s -o /dev/null -w "%{http_code}\n" https://example.com/login & done; wait
Minut- i stedet for sekundhastigheder og detaljerede stier
NGINX tillader hastigheder i sekunder eller minutter (r/s, r/m). Ved misbrug af login indstiller jeg ofte 60r/m i stedet for 1r/s for at tillade korte, legitime dobbeltklik, men begrænse kontinuerlige indtastninger. Dyre stier får strammere begrænsninger end billige. Eksempel:
limit_req_zone $binary_remote_addr zone=perip_min:20m rate=60r/m;
server {
location /search/ {
limit_req zone=perip_min burst=10; # strengere
}
location /status {
# ingen begrænsning – billig og bruges internt
return 200;
}
}
Faldgruber og hvordan jeg undgår dem
- Forkert nøgle: Når der bruges proxyservere uden en rigtig IP-adresse, begrænser jeg ved en fejltagelse alle brugere på én gang.
- For små zoner: „zone is full“ medfører uforudsigelig adfærd – sørg for generøs dimensionering.
- En grænse for alt: Forskellige veje kræver forskellige værdier; en løsning, der passer til alle, skaber frustration.
- Ingen overvågning: Uden en 429-analyse forbliver fejlkonfigurationer ubemærket.
- Over-whitelist: For brede undtagelser åbner dør og port – lav en hvidliste, der er målrettet, midlertidig og gennemsigtig.
Særlige forhold ved HTTP/2, SSE og caching
HTTP/2 samler anmodninger i få forbindelser; limit_conn er er stadig relevant, da streams bruger ressourcer. Server-sent events eller lange downloads udløser sjældent rate-limits (få anmodninger), men tager tid – her begrænser jeg antallet af samtidige forbindelser med `limit_conn` eller implementerer båndbreddestrategier. Hvor det er muligt, aflaster jeg med Caching (f.eks. statiske ressourcer, hyppige GET-anmodninger), så begrænsningerne udløses sjældnere, og brugerne får hurtigere svar.
Operativ tjekliste
- Real-IP er korrekt, nøgler er defineret (IP/token/bruger)
- Zoner er generøst dimensioneret, målinger/logfiler er tilgængelige
- hastighed/burst tilpasset pr. sti-klasse, nodelay bevidst indstillet
- Testet med dry-run, 429-kommunikation (Retry-After) implementeret
- Undtagelser for Health/Webhooks, kombination med limit_conn
- Iterativ genfokusering og alarmering ved afvigelser


