Rate limiting: skuteczna ochrona przed atakami DDoS

Czym jest rate limiting i dlaczego ma znaczenie?

Krótko: ograniczaj tempo żądań, zanim przeciążą Twoją infrastrukturę.

Rate limiting to fundament nowoczesnego bezpieczeństwa i niezawodności aplikacji. Polega na kontrolowaniu liczby żądań, jakie użytkownik, adres IP czy klucz API może wykonać w określonym czasie. Dzięki temu chronisz serwery przed przeciążeniem, utrzymujesz sprawiedliwe wykorzystanie zasobów i zniechęcasz atakujących do prób nadużyć oraz ataków DDoS na poziomie aplikacji.

W praktyce oznacza to nadawanie „budżetu żądań” i jego odświeżanie w czasie. Gdy limit zostanie przekroczony, serwer odpowiada błędem 429 Too Many Requests, czasem wraz z nagłówkiem Retry-After, by zasugerować klientowi, kiedy spróbować ponownie. W dobrze zaprojektowanej architekturze to jeden z filarów – obok WAF, CDN i filtracji na poziomie L3/L4 – który zapewnia ciągłość działania.

Jak to działa od kuchni: modele limitowania

Wybór algorytmu wpływa na doświadczenie użytkownika i skuteczność ochrony.

  • Token Bucket (wiaderko żetonów): daje elastyczność na „wybuchy” ruchu, ale utrzymuje średnią w ryzach. Dobry do API konsumenckich.
  • Leaky Bucket: wygładza ruch do stałego strumienia, redukuje skoki. Świetny do usług wrażliwych na chwilowe przeciążenia.
  • Fixed Window: proste okna czasowe (np. 100 żądań/minutę), ale podatne na „przebicia” przy granicach okien.
  • Sliding Window: sprawiedliwsze okna przesuwne; bardziej precyzyjne, lecz minimalnie bardziej kosztowne.
  • Limity równoległości (concurrency): ograniczają jednoczesne połączenia/operacje – ważne dla endpointów ciężkich (np. generowanie raportów).

W praktyce często łączy się kilka podejść, np. Sliding Window + Token Bucket, aby zapewnić i elastyczność, i kontrolę długoterminową.

Typy ataków DDoS a rola rate limiting

Nie każdy DDoS „pokonasz” tylko ograniczając tempo – potrzebna jest obrona warstwowa.

  • Warstwa sieciowa (L3) i transportowa (L4): masowe zalewanie ruchem (UDP, SYN flood). Tu potrzebne są mechanizmy operatorskie, Anycast, scrubbing, ACL-e i ochrona na brzegu (CDN, dostawca chmury).
  • Warstwa aplikacyjna (L7): ataki imitujące normalnych użytkowników (np. zalewanie loginów, wyszukiwania). Tutaj rate limiting jest wyjątkowo skuteczny, zwłaszcza w połączeniu z WAF i regułami wykrywającymi anomalie.

Kluczowe jest, by nie przeceniać jednej techniki. Rate limiting najlepiej działa na L7 i nadużycia API, ale musi współgrać z ochroną sieciową oraz filtracją ruchu zanim dotrze do aplikacji.

Strategia warstwowa: WAF, CDN i rate limiting

Zasada: zatrzymuj zły ruch jak najbliżej źródła i jak najtaniej.

  • CDN z Anycast i scrubbingiem: przejmuje volumetryczne ataki i rozprasza je globalnie.
  • WAF: rozpoznaje wzorce ataków, blokuje znane exploity oraz niestandardowe sygnatury.
  • Rate limiting na brzegu (edge) i w aplikacji: dba o sprawiedliwe zasoby dla realnych użytkowników i neutralizuje L7 DDoS.

Ustal jasną ścieżkę: ruch trafia na CDN/WAF, potem do warstwowej limitacji (per IP, per konto, per klucz API), a na końcu do logiki aplikacji wyposażonej w dodatkowe „bezpieczniki”.

Projektowanie polityk: jak dobrać limity i zakresy

Zacznij od danych, nie od intuicji – najpierw obserwuj normalny ruch.

  • Segmentacja: różne limity dla publicznych endpointów, operacji kosztownych (np. raporty, wyszukiwanie), akcji krytycznych (logowanie, reset hasła) i zasobów internal.
  • Wymiary limitów:
    • per IP (dobry baseline, pamiętaj o NAT i CGNAT),
    • per użytkownik/konto/klucz API (najbardziej sprawiedliwe),
    • per ścieżka/endpoint (różne koszty operacji),
    • per region/ASN (gdy wzorce wskazują nadużycia).
  • Burst vs. sustain: dopuszczaj krótkie piki (np. 10 żądań w 2 sekundy), ale trzymaj średnią (np. 300/min).
  • „Allowlist” i „denylist”: z rozsądkiem. Nie dawaj nieograniczonego zaufania szerokim zakresom IP.
  • Obsługa przekroczeń: błąd 429, nagłówki Retry-After, komunikaty pomagające użytkownikom i developerom zrozumieć problem.
  • Wrażliwe akcje: rozważ progressive challenges (np. CAPTCHA dopiero po kilku przekroczeniach), by nie karać uczciwych.
  • Idempotencja i retry: promuj nagłówki/macierze idempotency i backoff (np. wykładniczy) po stronie klienta.

Rate limiting w praktyce: od edge do aplikacji

Wybierz miejsce wdrożenia zgodnie z celem i kosztami.

  • Na brzegu (CDN/WAF): tanio zatrzymasz masowe nadużycia zanim obciążą origin.
  • Na load balancerze/reverse proxy: spójne limity dla całego klastra.
  • W aplikacji: najwięcej kontekstu (użytkownik, plan taryfowy, rola), ale i największy koszt.

Rate limiting w NGINX

Prosty, szybki i skuteczny na warstwie reverse proxy.

Przykład (limit na IP z lekkim burstem):

limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s
limit_req_zone $http_authorization zone=perkey:10m rate=60r/m

server {
location /api/ {
limit_req zone=perip burst=10 nodelay;
limit_req zone=perkey burst=20;
add_header X-RateLimit-Policy “5r/s per IP; 60r/m per key”;
}
}

Powyżej łączymy dwa wymiary: IP oraz klucz. Warto dodać logowanie 429 i korelację z identyfikatorem żądania.

Rate limiting w chmurze: Cloudflare, AWS, GCP

Skorzystaj z natywnych usług, by ograniczyć opóźnienia wdrożenia.

  • Cloudflare: Ruleset-y L7, bot management, dynamiczne limity per ścieżka, integracja z Turnstile (wyzwania bez CAPTCHA obrazkowych).
  • AWS: WAF rate-based rules, API Gateway usage plans i throttling, CloudFront Function/Workers do niestandardowej logiki, Shield Advanced do volumetrii.
  • GCP: Cloud Armor z politykami L7, Apigee do limitów per produkt/klucz, Cloud CDN na brzegu.

Rate limiting na poziomie aplikacji

Najbardziej elastyczne – wykorzystaj Redis i okna przesuwne.

Prosty schemat:

  • Klucz: rate:{wymiar}:{identyfikator}, np. rate:user:123.
  • Wartość: znaczniki czasu ostatnich żądań lub licznik + TTL.
  • Algorytm Sliding Window: przy każdym żądaniu usuwasz stare wpisy, liczysz bieżące, decydujesz o akceptacji, ustawiasz TTL równy długości okna.

W Javie, Node czy Pythonie świetnie działa Redis + skrypt Lua dla atomowości. Pamiętaj o poziomych limitach na wąskie gardła (np. kolejki z maksymalną liczbą jednoczesnych zadań).

Monitorowanie i alertowanie

Bez obserwowalności każdy limit to strzał w ciemno.

  • Metryki: liczba 429, odsetek 429 per endpoint, p95/p99 opóźnienia, błędy 5xx podczas ataków, saturacja CPU/RAM/IO, cache hit ratio.
  • Logi: kto został ograniczony i dlaczego (IP, klucz, user-agent, ASN), korelacja z ruchem marketingowym lub wydaniami.
  • Dashboards i alerty: progi dynamiczne (anomalia do mediany/odchylenia), osobne alarmy na sudden spikes i długotrwałe nadużycia.
  • SLO/SLA: zdefiniuj akceptowalne czasy odpowiedzi i dostępność; limity nie mogą ich nadmiernie naruszać.

Testowanie i walidacja ochrony

Traktuj to jak funkcję biznesową – regularnie ćwicz i mierz.

  • Testy obciążeniowe: k6, Locust, Gatling – weryfikuj progi, bursty, „cold starty”.
  • Symulacje nadużyć: wiele IP, wiele kluczy, różne ścieżki ataku (np. wolne żądania, randomized user-agent).
  • Canary i shadow mode: najpierw loguj potencjalne 429 bez egzekwowania, potem stopniowo zaostrzaj.
  • Game days: ćwicz runbook zespołu – kto podnosi limity, kto kontaktuje się z CDN, kto komunikuje się z klientami.

Użyteczność i komunikacja z użytkownikami

Ochrona nie może być kosztem dobrego doświadczenia.

  • Jasne komunikaty: „Przekroczono limit. Spróbuj ponownie za 30 s.” i link do dokumentacji.
  • Developer-friendly: nagłówki X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After, opis polityki w docs.
  • Sprawiedliwość: różne plany taryfowe z transparentnymi limitami; możliwość podniesienia progu dla zaufanych partnerów.
  • Prywatność: ogranicz zbieranie danych o użytkowniku – loguj tyle, ile potrzeba do bezpieczeństwa i zgodności.

Najczęstsze błędy przy wdrażaniu

Unikaj pułapek, które osłabiają ochronę lub psują UX.

  • Jeden globalny limit dla całego API – uderza w kluczowe funkcje.
  • Takie same limity dla tanich i drogich operacji.
  • Blokowanie szerokich zakresów IP/ASN bez analizy – ryzyko fałszywych trafień.
  • Ignorowanie IPv6 i nagłówków PROXY/Forwarded – zła identyfikacja klienta.
  • Brak idempotencji i backoffu – klienci „dokręcają” pętlę retry i pogarszają sytuację.
  • Brak limitów na GraphQL lub wyszukiwanie – pojedyncze zapytania potrafią być ekstremalnie kosztowne.
  • Brak cache’owania często odczytywanych zasobów – niepotrzebnie „przepalasz” budżet limitów.

Plan reakcji na incydenty DDoS

Z góry uzgodniony runbook skraca czas niedostępności.

  • Identyfikacja: wykryj warstwę ataku (L3/L4/L7), wolumetrię, geografie, ASN.
  • Eskalacja do dostawcy: włącz tryby awaryjne CDN/WAF, poproś o dodatkowe filtrowanie.
  • Zaostrzenie limitów: tymczasowo obniż progi na newralgicznych endpointach, włącz wyzwania.
  • Feature flags: wyłącz na chwilę najcięższe funkcje (np. generowanie raportów).
  • Komunikacja: status page, ETA, informacje dla kluczowych klientów.
  • Post mortem: co zadziałało, co usprawnić, jakie progi i reguły zmienić.

Podsumowanie

Skuteczna ochrona to połączenie rozsądnych limitów, mądrej infrastruktury i dobrej obserwowalności.

Rate limiting to prosta idea o ogromnej mocy – szczególnie wobec ataków na warstwę aplikacji i codziennych nadużyć. Najlepiej działa jako element strategii warstwowej: CDN i scrubbing na brzegu, WAF do filtrowania wzorców, a następnie granularne limity per IP, użytkownik i endpoint. Zaprojektuj polityki na podstawie realnych danych, testuj je regularnie i komunikuj jasno użytkownikom. Dzięki temu utrzymasz wydajność, obniżysz koszty i zapewnisz stabilne działanie nawet pod presją niespodziewanych skoków ruchu.

Kacper Jedynak

Zostaw swój numer - oddzwonię

Cześć! Zadzwoń +48 572 651 439 lub napisz lub zostaw numer telefonu, a oddzwonię w ciągu 1h i porozmawiamy o ofercie.

Picture of Łukasz Janeczko

Łukasz Janeczko

Programista - DropDigital.pl