Jak jsme zařízli botnet ze Singapuru: Když CPU vyletí na 55násobek kvůli scraperům
Stalo se to zčistajasna. Server, který se běžně „nudí“ s vytížením kolem 1–2 %, najednou začal topit. Monitoring hlásil kritické hodnoty, load average v červených číslech a procesor (CPU) vyletěl na padesátipětinásobek běžného stavu. Diagnóza? Masivní útok botnetu ze Singapuru, který se pokoušel "proškrábat" (scrape) skrz web pomocí totálně zprasených URL.
V tomto článku se podíváme na to, jak jsme v reálném čase identifikovali tyhle "garbage" requesty, jak jsme je okamžitě „vykostili“ v konfiguraci Apache a proč byl finálním řešením přechod pod křídla Cloudflare.
První kontakt: Co se to sakra děje?
Když vám CPU vyletí na 100 % a drží se tam, máte v podstatě dvě možnosti: buď se o vás napsalo na titulce New York Times, nebo vás právě někdo „mydlí“ botnetem. Pohled do logů (/var/log/apache2/access.log) potvrdil druhou variantu.
Stovky unikátních IP adres ze Singapuru začaly v obrovské frekvenci bombardovat náš server. Nebyl to ale klasický DDoS na zahlcení linky. Šlo o útok na aplikační vrstvu, kde boti generovali požadavky plné escapovaných HTML entit a uvozovek. Tyhle zprasené requesty nutili Apache a následně PHP procesy k neustálému parsování nesmyslů, což CPU totálně zahltilo.
Krok 1: Identifikace "Scraper Garbage"
Při analýze THE_REQUEST (to, co klient skutečně poslal serveru) jsme si všimli, že boti rotují IP adresy, ale jejich požadavky obsahují specifický balast: escapované uvozovky ("), zpětná lomítka a další HTML entity přímo v URL.
Místo abychom blokovali tisíce IP adres, rozhodli jsme se blokovat vzor chování.
Krok 2: Chirurgický řez v konfiguraci Apache
Místo složitého nastavování firewallu jsme sáhli po modulu mod_rewrite. Potřebovali jsme tyhle požadavky „zaříznout“ dříve, než stačí probudit PHP proces a začít žrát drahocenné CPU cykly.
Do konfigurace jsme přidali tohle pravidlo, které cílí na zprasená URL (malformed URLs):
Apache
## Block malformed bot URLs with escaped HTML quotes (scraper garbage)
RewriteCond %{THE_REQUEST} %5[Cc]%26quot|%5[Cc]"|\\"|%5[Cc]& [NC]
RewriteRule .* - [R=410,L]
Proč zrovna kód 410? Použili jsme 410 Gone namísto klasické 403. Tím dáváme botovi (a vyhledávačům) jasně najevo, že tento zdroj je nenávratně pryč. Pro server je vygenerování této odpovědi triviální záležitost, která nevyžaduje téměř žádný výpočetní výkon.
Krok 3: Cloudflare jako neprůstřelný štít
Exkluze v Apache byla skvělá „první pomoc“, která okamžitě srazila load serveru. Dlouhodobě ale nechcete, aby útočník vůbec na vaše dveře klepal. Každý request, i ten zamítnutý, totiž spotřebovává určitou režii Apache a síťovou konektivitu.
Proto jsme web nasměrovali přes Cloudflare. To nám umožnilo přesunout logiku blokování z našeho serveru na jejich globální síť.
Jak jsme to nastavili v Cloudflare:
WAF Custom Rule: Vytvořili jsme pravidlo, které kontroluje
URI. Pokud obsahuje stejné patterny (escapované uvozovky, lomítka), Cloudflare požadavek zablokuje ještě v Singapuru.JS Challenge pro Singapur: Jelikož útok šel cíleně z tohoto regionu, nastavili jsme pro něj interaktivní výzvu. Boti na JS výzvě ztroskotají, zatímco reálný člověk by po vteřině prošel.
Shrnutí: Co si z toho odnést?
Boj s boty není o tom mít nejsilnější server na světě. Je to o schopnosti rychle identifikovat vzorec chování.
Sledujte THE_REQUEST: Někdy se útočník prozradí tím, jak nekvalitně má napsaný scraper (escapované entity v URL).
410 Gone je váš přítel: Pokud víte, že jde o totální nesmysl, nebojte se ho poslat k šípku definitivně.
Vrstvěte obranu: Apache vás zachrání v první minutě, Cloudflare vám zajistí klidné spaní po zbytek měsíce.
Dnes server běží opět na svých 2 % a útočník může bušit do zdí Cloudflare, jak chce. My máme klid na kávu.
Automaticky jsme všem našim klientům nastavili cloudlfare.