Un asalt de scrapere pe planul gratuit Cloudflare: ce l-a oprit și ce am lăsat dezactivat
Operațiuni
Într-o dimineață, un site de listări de-al nostru a încetat să se încarce. Cloudflare afișa vizitatorilor o eroare 524, originul dura între două și șase minute per pagină, iar nimic nu ne-a alertat timp de aproximativ zece ore. Cauza era un scraper care trecea prin proxy-uri rezidențiale la aproximativ 225 de cereri pe secundă.
Forma asaltului
- Mii de adrese, una până la trei cereri fiecare. Conexiuni de bandă largă rezidențiale din SUA, Spania, Franța, Brazilia, Regatul Unit și alte țări, genul de trafic pe care îl închiriază o rețea de proxy-uri rezidențiale.
- User agents Chrome pe Mac, cu numere de versiune de la 103 la 151.
- Aproape niciodată un cookie sau un Referer. Din 2.697 de cereri eșantionate pe server, 4 aveau un cookie și 4 un Referer.
- Două tipuri de client. Aproximativ jumătate nu trimiteau antete
Sec-Fetch-*și nici client hints: un script cu un user agent string copiat. Cealaltă jumătate trimitea antete complete de browser: un browser headless.
Fiecare pagină era redată pentru fiecare cerere, astfel încât fiecare worker punea în coadă sute de redări și atingea limita de CPU.
De ce limitele per adresă nu au putut ajuta
Un rate limit numără cererile per adresă. Cu una până la trei cereri de la fiecare dintre mii de adrese, nicio adresă individuală nu se apropie niciodată de o limită. Blocarea țărilor ar fi blocat vizitatorii noștri. Ce nu putea falsifica ieftin scraperul era să se comporte ca un browser care a mai fost pe site.
La marginea Cloudflare: trei reguli gratuite
Planul gratuit permite cinci reguli WAF personalizate per zonă. Am folosit trei, toate cu o provocare gestionată (managed challenge) în loc de blocare, astfel încât o persoană prinsă din greșeală să poată trece mai departe:
- Browser fals: o cerere GET al cărei user agent conține
Chrome/și care nu are antetulSec-Fetch-Mode. Orice Chrome din 2019 încoace îl trimite. - Cloud-uri de scrapere: o cerere de pagină din rețelele Alibaba, Tencent și Huawei Cloud, de unde venea mare parte din ce am provocat.
- Urgență, dezactivată implicit: o cerere GET fără niciun cookie și fără Referer. O persoană care a fost pe site sau care ajunge printr-un link trece neatinse; un scraper care nu ține cookie-uri întâlnește o provocare la fiecare cerere. O activăm doar în timpul unui asalt, pentru că provoacă și pe cineva care tastează adresa într-un browser proaspăt.
Toate trei lasă să treacă boții verificați de Cloudflare, user agents care se declară roboți, propriile noastre adrese, căile API și webhook și fișierele care nu sunt pagini. Două zile mai târziu, inundația continua: într-o oră, regula de browser fals a solicitat verificări pentru mai mult de 10.000 de cereri. Cele 10.000 de evenimente returnate de Cloudflare per interogare proveneau de la 9.627 de adrese, niciuna cu mai mult de 4.
La origine: o barieră în aplicație
Partea headless are antete complete de browser, astfel încât regulile de la margine (edge) nu o prind singure cât timp regula de urgență este oprită. În aplicația propriu-zisă, am pus un mic middleware în fața randorului de pagini:
- un user agent Chrome fără
Sec-Fetch-Modeși fără client hints primește un 403 înainte de orice prelucrare; - un vizitator străin, fără niciuna dintre cookie-urile noastre și fără Referer, este servit doar cât timp worker-ul are capacitate liberă, la câteva pagini pe secundă. Peste această limită, o pagină 503 de 400 de bytes setează un cookie și reîncarcă după două secunde. O persoană primește pagina la a doua încercare; un scraper care nu păstrează cookie-uri nu o primește niciodată.
În primul minut, bariera a respins aproximativ 6.700 de browsere false și a îndepărtat aproximativ 6.700 de vizitatori străini, în timp ce servea străinilor aproximativ 9 pagini pe secundă. Cererile lente au scăzut la zero, CPU-ul workerilor a scăzut de la limita lor la 12-15 procente, iar memoria de la 4-5 GB fiecare la 0,65 GB.
Ce am lăsat oprit
- Bot Fight Mode. Solicită verificări pentru traficul automatizat și nu poate fi sărită cu o regulă personalizată pe planul Free, iar ea a prins webhook-urile furnizorului nostru de plăți.
- Modul Under Attack pentru întreaga zonă. Trece fiecare vizitator, client API și webhook prin pagina intermediară. Regula de urgență face aceeași treabă doar pentru cererile de pagini ale vizitatorilor străini.
- Regula de limitare a ratei din planul Free. Numără per adresă, lucru pe care această inundație nu îl declanșează niciodată.
- Blocarea crawlerilor AI. Vrem să fim găsiți de asistenții de căutare AI, iar acești crawlere nu erau problema.
Concluzia
O inundație prin proxy-uri rezidențiale este ușor de identificat prin ceea ce îi lipsește: antete de fetch de browser, cookie-uri și Referer-uri. Solicită verificări la margine (edge), menține vizitatorii străini în limitele pe care workerii tăi le pot randa și asigură-te că ceva în afara serverului observă când o pagină nu se mai deschide. Night Watch împachetează toate cele trei: ceasul de veghe, regulile cu un comutator automat pentru cea de urgență și bariera pentru aplicațiile web Python.