Een scraper-vloedgolf op het Free-plan van Cloudflare: wat het stopte en wat we uitgeschakeld lieten
Ops
Op een ochtend stopte een van onze productpaginasites met laden. Cloudflare toonde bezoekers een 524, de origin nam twee tot zes minuten per pagina, en niets liet het ons weten gedurende ongeveer tien uur. De oorzaak was een scraper die via residential proxies ging met ongeveer 225 verzoeken per seconde.
De vorm van de vloedgolf
- Duizenden adressen, één tot drie verzoeken per stuk. Thuisbreedbandverbindingen in de VS, Spanje, Frankrijk, Brazilië, het VK en elders, het soort verkeer dat een residential proxy-netwerk verhuurt.
- Chrome user agents op een Mac, met versienummers van 103 tot 151.
- Bijna nooit een cookie of een Referer. Van de 2.697 verzoeken die we op de server bemonsterden, hadden er 4 een cookie en 4 een Referer.
- Twee soorten clients. Ongeveer de helft stuurde geen
Sec-Fetch-*headers en geen client hints: een script met een gekopieerde user agent string. De andere helft stuurde volledige browser headers: een headless browser.
Elke pagina werd voor elk verzoek gerenderd, dus elke worker zette honderden renders in de wachtrij en bereikte zijn CPU-limiet.
Waarom limieten per adres niet hielpen
Een rate limit telt verzoeken per adres. Met één tot drie verzoeken van elk van de duizenden adressen komt geen enkel adres in de buurt van een limiet. Landen blokkeren had onze bezoekers geblokkeerd. Wat de scraper niet goedkoop kon nabootsen was gedrag als een browser die de site eerder had bezocht.
Aan de Cloudflare-edge: drie gratis regels
Het Free-plan staat vijf WAF custom rules per zone toe. We gebruikten er drie, allemaal met een managed challenge in plaats van een block, zodat iemand die per ongeluk wordt geraakt er doorheen klikt:
- Nep-browser: een GET waarvan de user agent
Chrome/bevat en die geenSec-Fetch-Modeheader heeft. Elke Chrome sinds 2019 stuurt deze. - Scraper clouds: een paginaverzoek van de netwerken van Alibaba, Tencent en Huawei Cloud, waar veel van wat we uitdaagden vandaan kwam.
- Noodgeval, standaard uit: een GET zonder cookie en zonder Referer. Iemand die de site heeft bezocht, of die via een link binnenkomt, komt er ongemoeid doorheen; een scraper die geen cookies bewaart krijgt bij elk verzoek een challenge. We zetten dit alleen aan tijdens een vloedgolf, omdat het ook iemand uitdaagt die het adres in een verse browser typt.
Alle drie laten Cloudflares geverifieerde bots door, user agents die zichzelf als robots aanduiden, onze eigen adressen, de API- en webhook-paden en bestanden die geen pagina's zijn. Twee dagen later ging de vloedgolf nog steeds door: in één uur daagde de fake-browserregel meer dan 10.000 verzoeken uit. De 10.000 events die Cloudflare per query teruggeeft, kwamen van 9.627 adressen, waarvan geen enkel meer dan 4 had.
Op de origin: een poort in de app
Het headless-gedeelte heeft volledige browserheaders, dus de edgeregels vangen het niet op als de noodregel uit staat. In de app zelf zetten we een kleine middleware vóór de paginarenderaar:
- een Chrome user agent zonder
Sec-Fetch-Modeen zonder client hints krijgt een 403 voordat er werk wordt verricht; - een vreemde, zonder onze cookies en zonder Referer, krijgt alleen inhoud als de worker capaciteit over heeft, aan een paar pagina's per seconde. Daarboven stelt een 400-byte 503-pagina een cookie in en herlaadt na twee seconden. Een persoon krijgt de pagina bij de tweede poging; een scraper die geen cookies bijhoudt, krijgt hem nooit.
In de eerste minuut weigerde de poort ongeveer 6.700 fake browsers en wees ongeveer 6.700 vreemden af, terwijl het vreemden ongeveer 9 pagina's per seconde bediende. Langzame verzoeken daalden naar nul, de CPU van de workers daalde van hun limiet naar 12 tot 15 procent, en hun geheugen van 4 tot 5 GB elk naar 0,65 GB.
Wat we uitgeschakeld lieten
- Bot Fight Mode. Het daagt geautomatiseerd verkeer uit en kan op het Free-plan niet worden overgeslagen met een custom rule, en het ving de webhooks van onze betalingsprovider af.
- Under Attack mode voor de hele zone. Het stuurt elke bezoeker, API-client en webhook door de interstitial. De noodregel doet hetzelfde werk alleen voor paginaverzoeken van vreemden.
- De rate-limitingregel van het Free-plan. Die telt per adres, wat deze vloedgolf nooit activeert.
- Blokkeren van AI-crawlers. We willen gevonden worden door AI-zoekassistenten, en die crawlers waren niet het probleem.
De conclusie
Een vloedgolf via residential proxies is makkelijk te herkennen aan wat er ontbreekt: browser fetch headers, cookies en Referers. Daag dat uit aan de edge, houd vreemden binnen wat je workers kunnen renderen, en zorg dat iets buiten de server merkt wanneer een pagina niet meer opent. Night Watch bundelt alle drie: de bewaking, de regels met een automatische schakelaar voor de noodregel, en de poort voor Python web apps.