RateLimit – Ochrana proti floodu¶
Princip: Omezit počet requestů ze stejné IP adresy v daném časovém okně.
Používá se k ochraně login endpointů, registrace, API antes brute-force útoků. RateLimiter si pamatuje timestampy posledních requestů z každé IP adresy v JSON souborech a při překročení limitu request zamítne.
Proč se používá¶
- Brute-force ochrana – Útočník nemůže zkoušet 1000 hesel za sekundu
- DDoS mitigation – Sníží dopadu nevyškoleného DDoS scripperu
- API rate limiting – Zamezí zneužití API endpointů
- Login flood – Ochrana přihlašovacích formulářů
Jak to funguje (vnitřně)¶
Sliding Window Approach¶
Každá IP adresa má svůj JSON soubor v var/rate-limits/:
var/rate-limits/
├── a3f9c2d1e8b47f02.json ← IP 192.168.1.100 (SHA-256 hash)
├── f7d2b1c9e3a4f6d8.json ← IP 10.0.0.50
└── ...
Obsah souboru:
Pole requests obsahuje timestampy poslední aktivit (Unix timestamps). Přesné pořadí se neuchovává – jen hodnoty.
Jak se filtrují staré requesty¶
Při každém check():
- Načte pole timestampů
- Vyfiltruje ty, které jsou mimo časové okno (sliding window)
- Pokud zbývá málo requestů → přidá aktuální čas
- Pokud je víc → zamítne (vrátí false)
Příklad s check($ip, 5, 60) (5 requestů / 60 sekund):
čas 100: [100] → accept
čas 105: [100, 105] → accept
čas 110: [100, 105, 110] → accept
čas 115: [100, 105, 110, 115] → accept
čas 120: [100, 105, 110, 115, 120] → accept
čas 125: [100, 105, 110, 115, 120] → REJECT (6 requestů)
čas 162: [105, 110, 115, 120] → accept (100 expiroval, < 60s od teď)
Race Conditions a Locking¶
RateLimiter používá file locking (flock) na úrovni OS:
$fp = fopen($file, 'c+');
flock($fp, LOCK_EX); // Exclusive lock – ostatní čekají
// ... read/write/modify ...
flock($fp, LOCK_UN); // Release
fclose($fp);
To zabraňuje race conditions v high-concurrency prostředí (když více requestů z různých IP procesů souběžně zásahuje do var/rate-limits/).
Fail-open behavior: Pokud se nepodaří otevřít soubor nebo získat zámek, request je povolen (raději flood než false-positive block).
Výkon a Dopad na Přihlášení¶
Správný Výkon (Optimální Nastavení)¶
Pokud voláš RateLimiter jen na login endpointu, je to zanedbatelný overhead.
Zpomalení Přihlášení?¶
Ano, ale jen pokud voláš check() globálně na každý request (včetně statických souborů, AJAX, API):
Problém:
- Login formulář = 10-15 requestů (HTML + CSS + JS + AJAX)
- Všechny čekají na zámek stejného souboru
- Fronta na zámku = viditelné zpomalení
Řešení¶
Volej RateLimiter jen tam, kde to má smysl:
// ✅ DOBŘE – jen na login
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $path === '/login') {
if (!RateLimiter::check($ip, 10, 300)) {
http_response_code(429);
exit;
}
}
Nebo filtruj statické soubory:
// ✅ DOBŘE – vynech statické assety
if (!in_array(pathinfo($path, PATHINFO_EXTENSION), ['js', 'css', 'png', 'jpg'])) {
RateLimiter::check($ip);
}
Případ Použití¶
| Scénář | Limit | Okno |
|---|---|---|
| Login form | 10 pokusů | 5 minut |
| API endpoint | 100 requestů | 1 minuta |
| Public form (kontakt) | 5 | 1 hodina |
| Password reset | 3 | 1 hodina |
Ochrana Soukromí¶
- IP adresy jsou hashované (SHA-256, 16 znaků)
- Žádné plaintext IP se neukládá
- Soubory mají TTL 1 hodinu (automaticky se mažou staré)
- GDPR compliant
Přenositelnost & Nezávislost¶
RateLimiter je zcela přenositelný – žádné závislosti:
✅ Žádné externí balíčky (Composer)
✅ Žádné systémové příkazy (shell)
✅ Žádné databáze (MySQL, PostgreSQL)
✅ Žádné cache servery (Redis, Memcached)
✅ Jen PHP built-in funkce:
fopen(),flock(),fwrite()– File I/Ojson_encode()– JSON (PHP 5.2+)hash('sha256')– SHA-256 hashingmkdir()– Directory creationtime()– Unix timestamps
Filesystem: Jedinou závislostí je filesystem. Každý server/hosting má filesystém.
PHP verze: 7.1+ (standardní)
Kopírování na Jiný Projekt¶
Pak jen zavolej v boostrappingu:
Nastavení Storage Path¶
NUTNÉ: Musíš zavolat setPath() během bootstrap aplikace!
// app/bootstrap.php
RateLimiter::setPath(DIR . '/var/rate-limits');
// Nebo vlastní cesta:
RateLimiter::setPath('/tmp/rate-limits');
Bez setPath() vyhodí RuntimeException (fail-fast design).
Výchozí Cesta¶
Neexistuje – musíš ji nastavit sám. Tím se zajistí explicitní inicializace a žádné "tiché selhání".
Lazy Cleanup¶
RateLimiter automaticky maže starší soubory (~1% šance na každý allowed request):
Zabraňuje neomezené akumulaci souborů na disku.
Další Čtení¶
- API Reference – kompletní funkce
- Příklady Použití – praktické scénáře