Rate limiting – begrens misbruk uten å blokkere kundene
En global grense per IP er sjelden nok. Begrens handling, identitet, ressurskostnad og samtidighet på hvert sitt nivå.
Vymo · · 9 min lesing
Rate limiting begrenser hvor ofte eller hvor mye en klient kan bruke en tjeneste i et tidsrom. Det kan dempe skjemaspam, passordforsøk, scraping, dyre API-kall og kostnadssjokk. Feil utformet kan det også stenge en hel arbeidsplass, mobiloperatør eller skole ute fordi mange legitime brukere deler én IP-adresse.
En god løsning svarer på fire spørsmål:
- Hvilken handling begrenses? Lesing, søk, innlogging, eksport, utsending eller noe annet.
- Hvem eller hva deler kvoten? Konto, kunde, API-nøkkel, økt, IP, ressurs eller en kombinasjon.
- Hva måles? Antall forespørsler, kostnadsenheter, datamengde eller samtidige jobber.
- Hva skjer ved grensen? Avslag, forsinkelse, kø, utfordring eller redusert funksjon.
Rate limiting er flere kontroller, ikke én regel
En regel som sier «100 forespørsler per minutt per IP» kan være nyttig ved kanten, men den forstår ikke virksomhetens brukere eller kostnader.
| Lag | Ser typisk | Egnet til | Begrensning |
|---|---|---|---|
| CDN / WAF | IP, geografi, sti, bot-signal og enkelte headere | Store volum, kjente mønstre og tidlig avvisning | Mangler ofte sikker bruker- og forretningskontekst |
| Gateway / Worker | Rute, verifisert token, sesjon og enkelte identiteter | Endepunkt- og kundegrenser før backend | Distribuerte tellere kan være lokale eller omtrentlige |
| Applikasjon | Konto, virksomhet, rolle, operasjon og kostnad | Forretningsregler og misbruk på tvers av IP-er | Forespørselen har allerede nådd applikasjonen |
| Jobbkø / database | Samtidighet, kjøretid og faktisk ressursbruk | Tunge rapporter, eksport, e-post og bakgrunnsjobber | Stopper ikke nødvendigvis volumet ved inngangen |
Bruk kanten til å dempe volum og applikasjonen til å håndheve regler som krever autentisert identitet. En angriper med tusen IP-adresser skal ikke få tusen ganger større kvote mot den samme kontoen eller ressursen.
Finn handlingene som trenger egne grenser
Start med operasjoner som endrer tilstand, avslører data, sender noe eller bruker uforholdsmessig mye ressurser:
- innlogging, engangskode og passordgjenoppretting
- registrering, invitasjon og opprettelse av konto
- kontaktskjema, tilbudsforespørsel og e-postutsending
- søk med kostbare filtre eller jokertegn
- eksport, rapportgenerering og filopplasting
- API-kall til betalte tredjepartstjenester
- kjøp, reservasjon, kupong og andre begrensede ressurser
- GraphQL-spørringer, batching og store sideparametere
- funksjoner som genererer bilde, video eller annen kostbar behandling
Ikke tell bare HTTP-forespørsler. Én eksport av én million rader kan koste mer enn tusen cachede produktsider. Begrens også maksimal filstørrelse, antall elementer, sidebredde, spørringsdybde, kjøretid, samtidighet og samlet kostnad.
OWASP API Security Top 10 behandler manglende ressursgrenser som mer enn en trafikkutfordring: CPU, minne, lagring, båndbredde og leverandørkostnader må alle ha grenser.
Velg nøkkelen etter misbruket
En rate-limit-nøkkel bestemmer hvilke forespørsler som deler teller.
| Nøkkel | Fordel | Risiko | Typisk bruk |
|---|---|---|---|
| IP-adresse | Tilgjengelig før innlogging | NAT, mobilnett og personvernproxy samler mange brukere; angripere bytter IP | Romslig volumgrense ved kanten |
| Konto eller bruker-ID | Følger identiteten på tvers av nettverk | Kan misbrukes til å låse offerets konto ute | Sensitive kontohandlinger sammen med andre signaler |
| Virksomhet / tenant | Stopper én kunde fra å bruke all kapasitet | Én tung bruker kan påvirke kolleger | API- og kostnadskvote per kunde |
| API-nøkkel | Stabil for maskinklienter | Delt eller lekket nøkkel gir feil fordeling | Integrasjoner og offentlig API |
| Sesjon / enhetssignal | Bedre enn IP for delt nettverk | Kan slettes, roteres eller forfalskes | Nettleserflyt som tilleggssignal |
| Ressurs-ID | Beskytter ett tilbud, telefonnummer eller dokument | Må kombineres med avsender for vanlig bruk | Reservasjon, melding og dyre objekter |
| Global nøkkel | Beskytter samlet kapasitet | Kan gjøre angriperens trafikk til tjenestenekt for alle | Nødbrems og kø, ikke primær brukergrense |
Kombiner dimensjoner. En passordreset kan for eksempel ha:
- romslig grense per kilde mot endepunktet
- strammere grense per konto over tid
- grense på hvor mange meldinger som faktisk sendes til samme mottaker
- global leverandør- og kostnadsgrense
Gi ikke angriperen et enkelt verktøy for å låse offeret ute. Etter grensen kan dere forsinke, kreve ekstra verifisering eller stoppe utsending samtidig som en trygg gjenopprettingsvei bevares.
Stol bare på proxyheadere fra en betrodd vei
X-Forwarded-For, Forwarded og leverandørspesifikke IP-headere kan forfalskes dersom klienten kan nå applikasjonen direkte. Bestem hvilken proxy som får skrive headeren, fjern innkommende kopier ved kanten, og la backend bare stole på verdien når trafikken faktisk kommer gjennom den kontrollerte proxyen.
I en Cloudflare Worker er CF-Connecting-IP en plattformverdi. Den samme headeren skal ikke ukritisk stoles på i en opprinnelsesserver som også er offentlig tilgjengelig uten Cloudflare foran.
IP-adresser og brukeridentiteter kan være personopplysninger. Ikke legg rå e-post, telefon, API-nøkkel eller sesjonstoken i tellernøkkelen eller loggen. Bruk en intern stabil ID eller en egnet, ensrettet avledning, og styr tilgang og oppbevaring.
Velg algoritme og burst med hensikt
| Modell | Hvordan den virker | Styrke | Svakhet |
|---|---|---|---|
| Fast vindu | Teller i f.eks. hvert hele minutt | Enkel og billig | Tillater stort burst rundt vindusgrensen |
| Glidende logg | Lagrer tid for hver hendelse i siste periode | Presis | Mer lagring og arbeid per nøkkel |
| Glidende teller | Tilnærmer glidende vindu med flere tellere | Jevnere enn fast vindu | Fortsatt omtrentlige grenser |
| Token bucket | Fyller tokens med fast rate opp til en kapasitet | Tillater kontrollert burst og stabil langtidstakt | Krever riktig valg av fyllrate og bøttestørrelse |
| Leaky bucket / kø | Slipper arbeid ut i kontrollert takt | Jevn backend-belastning | Legger til køtid og trenger køgrense |
| Samtidighetsgrense | Teller aktive operasjoner | Beskytter tungt arbeid | Begrenser ikke mange raske sekvensielle kall |
For interaktive brukerhandlinger er en liten burst ofte nødvendig. En side kan laste flere ressurser samtidig, og en bruker kan dobbeltklikke eller prøve igjen etter nettverksfeil. Maskin-API-er kan tåle jevnere flyt dersom klienten får tydelig kvoteinformasjon.
Kombiner gjerne token bucket for kort burst med en lengre dagskvote og en samtidighetsgrense for tunge jobber.
Mål før dere blokkerer
Finn legitim normalbruk og kjente topper før grensen settes:
- Skill menneskelig nettlesertrafikk, interne integrasjoner, søkemotorer og ukjente automatiske klienter.
- Mål per endepunkt og aktuell nøkkel, ikke bare total forespørselsrate.
- Se på fordeling og høye persentiler, ikke bare gjennomsnitt.
- Finn hvor kapasitet, leverandørkvote eller kostnad faktisk blir et problem.
- Sammenlign en vanlig periode med en kjent kampanje, feil eller angrepsperiode.
- Kjør regelen i loggmodus eller med romslig grense før avslag aktiveres.
Terskelen skal ligge over kjent legitim burst og under nivået der misbruk eller ressursmangel blir skadelig. Dersom disse overlapper, må arkitektur, kø, cache eller produktflyt forbedres; en tilfeldig terskel kan ikke løse kapasitet alene.
Svar riktig når grensen nås
RFC 6585
definerer 429 Too Many Requests. Responsen bør forklare hva som skjedde og kan oppgi Retry-After:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Cache-Control: no-store
Retry-After: 60
{"error":"For mange forsøk. Vent litt og prøv igjen."}
Retry-After kan være antall sekunder eller en HTTP-dato. Verdien bør gjenspeile når en ny forespørsel sannsynligvis kan lykkes. For en omtrentlig eller distribuert grense er den et råd, ikke et løfte.
Bruk normalt:
- 429 når denne klienten, identiteten eller kvoten har gjort for mye
- 503 Service Unavailable når selve tjenesten midlertidig ikke kan levere, gjerne med
Retry-After - 413 Content Too Large når innsendt innhold overskrider maksimal størrelse
Ikke avslør om en bestemt e-postkonto finnes gjennom ulik tekst, status eller responstid. Innloggings- og gjenopprettingsendepunkter trenger en egen vurdering av kontolåsing og brukeropplisting; se guiden mot brute force og credential stuffing .
RateLimit-headere er fortsatt et utkast
Per 22. august 2026 er RateLimit og RateLimit-Policy beskrevet i IETF-utkastet for rate-limit-felter
, ikke i en ferdig RFC. Utkastets syntaks har endret seg gjennom versjonene.
Hvis dere tar feltene i bruk, oppgi hvilken utkastversjon klient og server følger, og vær forberedt på endringer. Eldre X-RateLimit-Limit, X-RateLimit-Remaining og lignende er leverandørkonvensjoner med varierende semantikk, ikke ett universelt format.
Retry-After og 429 kan brukes uavhengig av dette utkastet.
Klienter må dempe seg riktig
En klient som får 429 bør:
- følge
Retry-Afternår den finnes - bruke eksponentiell backoff med jitter når den ikke finnes eller flere feil følger
- ha øvre grense på venting og totalt antall forsøk
- ikke synkronisere alle jobber til samme sekund
- bare automatisk gjenta operasjoner som er idempotente eller beskyttet med idempotensnøkkel
- stoppe og varsle når feilen krever menneskelig eller kontraktsmessig handling
Automatisk gjentakelse av betaling, bestilling, e-postutsending eller engangskode kan skape duplikater og mer misbruk. Serveren bør støtte idempotens der klienter trygt må kunne prøve en opprettende operasjon igjen etter nettverksfeil.
Distribuerte tellere har en konsistenspris
I flere regioner eller datasentre kan en streng global teller kreve koordinering på hver forespørsel. Det øker latency og gjør telleren til en ny kritisk avhengighet.
Avklar:
- om telleren er global, regional, per datasenter eller per prosess
- om oppdatering er atomisk eller etter hvert konsistent
- hvor stort overskridelsesrom samtidige forespørsler kan få
- hvordan nøkkelen fordeles mellom noder
- hva som skjer når lageret er tregt eller utilgjengelig
- om sikkerhetskritiske handlinger skal feile åpent eller lukket
En permissiv kantteller kan være riktig for skjemaspam, men feil for økonomisk kvote eller begrenset lager. Bruk transaksjonell og autoritativ kontroll for penger, antall solgte billetter, lisensforbruk og andre grenser som ikke tåler overskridelse.
Overvåk virkningen, ikke bare antall 429
Mål per regel og endepunkt:
- tillatte, forsinkede, utfordrede og avviste forespørsler
- unike nøkler og andel legitime brukere som rammes
- 429-rate før og etter produkt- eller trafikkendringer
- backend-latency, kø, feil og leverandørkostnad
- hvilke regler som utløses samtidig
- om misbruk flytter til en annen identitet eller operasjon
Logg regel-ID og en pseudonymisert nøkkel, ikke rå passord, tokens eller hele forespørselskropper. Varsle på plutselige endringer og langvarig høy rate, men unngå ett varsel per avvist forespørsel.
Test grensene som et distribuert system
En brukbar testplan dekker:
- siste tillatte og første avviste forespørsel
- reset,
Retry-Afterog klokke-/vindusgrenser - tillatt kort burst og langvarig takt
- samtidige forespørsler fra flere prosesser
- samme konto fra flere IP-er og mange brukere bak samme IP
- IPv4, IPv6 og skiftende mobilnett
- forfalskede proxyheadere mot en direkte tilgjengelig origin
- feil i tellerlager og valgt fail-open/fail-closed-adferd
- 429 i CDN og mellomlagring, slik at én klients avslag ikke deles med alle
- klientens backoff, jitter og idempotens
Belastningstesting skal skje i kontrollert miljø eller med eksplisitt tillatelse og kapasitet. Ikke bruk produksjonskunder som terskeleksperiment.
Hva Vymo gjør på bestillingsskjemaene
Vymos bestillings-API bruker flere uavhengige kontroller:
- bare forespørsler fra forventet Vymo-origin behandles
- Cloudflare Turnstile valideres på server med riktig hostname og handlingsnavn
- forespørselskropp og hvert relevant felt har maksimal størrelse
- en romslig grense på 30 kall per minutt gjelder per kilde og skjemaendepunkt før ekstern behandling
- etter gyldig Turnstile, e-post og Brønnøysund-kontroll gjelder 3 bestillinger per minutt for samme kombinasjon av endepunkt, organisasjonsnummer og e-post
- nøklene hashes før de sendes til rate-limit-bindingen
- avslag gir 429 og
Retry-After: 60, og e-post sendes ikke
Grensene bruker Cloudflare Workers Rate Limiting API. Cloudflare dokumenterer at telleren er permissiv, etter hvert konsistent og lokal til datasenteret som kjører Workeren. Den kan derfor dempe automatisert misbruk, men er ikke en presis global teller eller garanti mot DDoS.
Den grove kildegrensen er bevisst romsligere fordi mange legitime brukere kan dele IP. Den strammere grensen aktiveres først etter at menneskeutfordring og virksomhetsdata er validert, slik at en angriper ikke bare kan oppgi et offentlig organisasjonsnummer for å bruke opp bedriftens kvote.
Dette vernet kommer i tillegg til, ikke i stedet for, Cloudflares nettverksbeskyttelse og sikker behandling av selve bestillingen.
Har bedriften funnet riktig navn?
Sjekk om .no-domenet er ledig. Et .no-domene koster 199,- per år, også ved fornyelse.