Наводнение от скрейпери при безплатния план на Cloudflare: какво го спря и какво оставихме изключено
Операции
Една сутрин един от нашите сайтове с обяви спря да се отваря. Cloudflare показваше на посетителите грешка 524, сървърът отнемаше от две до шест минути за страница, а ние не получихме никаква информация в продължение на около десет часа. Причината беше скрейпер, минаващ през резидентни прокси с около 225 заявки в секунда.
Формата на наводнението
- Хиляди адреси, по една до три заявки от всеки. Домашни широколентови връзки в САЩ, Испания, Франция, Бразилия, Великобритания и други държави – вид трафик, който мрежите за резидентни прокси отдават под наем.
- Потребителски агенти на Chrome за Mac, с номера на версии от 103 до 151.
- Почти никога бисквитка или Referer. От 2697 заявки, които взехме за проба на сървъра, 4 съдържаха бисквитка и 4 – Referer.
- Два вида клиенти. Около половината не изпращаха заглавки
Sec-Fetch-*и клиентски подсказки: скрипт с копиран низ за потребителски агент. Другата половина изпращаше пълни заглавки на браузър: headless браузър.
Всяка страница се рендираше за всяка заявка, затова всеки worker зареждаше стотици рендери и достигаше лимита си за CPU.
Защо лимитите по адрес не помогнаха
Ограничението на честотата брои заявките по адрес. При една до три заявки от всеки от хилядите адреси нито един адрес не се доближава до лимита. Блокирането на държави би блокирало нашите посетители. Онова, което скрейпърът не можеше евтино да имитира, беше да се държи като браузър, който вече е бил на сайта.
На ръба на Cloudflare: три безплатни правила
Безплатният план позволява пет персонализирани WAF правила на зона. Използвахме три, всички с управлявано предизвикателство вместо блокиране, така че човек, хванат погрешка, да премине с клик:
- Фалшив браузър: GET заявка, чийто потребителски агент съдържа
Chrome/и която няма заглавкаSec-Fetch-Mode. Всеки Chrome след 2019 г. я изпраща. - Облачни скрейпери: заявка за страница от мрежите на Alibaba, Tencent и Huawei Cloud, откъдето идваше голяма част от предизвиканите от нас заявки.
- Аварийно, изключено по подразбиране: GET заявка без никаква бисквитка и без Referer. Човек, който е бил на сайта, или който идва чрез връзка, минава непроменен; скрейпър, който не пази бисквитки, среща предизвикателство при всяка заявка. Включваме го само по време на наводнение, защото то предизвиква и някой, който въвежда адреса в нов браузър.
И трите пропускат проверените ботове на Cloudflare, потребителските агенти, които се представят като роботи, нашите собствени адреси, пътищата за API и webhook, както и файловете, които не са страници. Два дни по-късно наводнението продължаваше: за един час правилото за фалшиви браузъри предизвика повече от 10 000 заявки. 10 000-те събития, които Cloudflare връща на заявка, идваха от 9 627 адреса, като нито един от тях нямаше повече от 4.
На източника: врата в приложението
Безглавата половина има пълни заглавки на браузъра, така че правилата на ръба не я хващат, докато аварийното правило е изключено. В самото приложение поставихме малък middleware пред рендериращия модул на страницата:
- потребителски агент на Chrome без
Sec-Fetch-Modeи без client hints получава 403, преди да се извърши каквато и да е работа; - непознат, без никоя от нашите бисквитки и без Referer, получава достъп само когато worker-ът има свободен капацитет, при няколко страници в секунда. Над този лимит 400-байтова страница с грешка 503 задава бисквитка и презарежда след две секунди. Човекът получава страницата при втория опит; скрапер, който не пази бисквитки, никога не я получава.
В първата си минута вратата отказа около 6 700 фалшиви браузъра и отблъсна около 6 700 непознати, като обслужваше непознатите с около 9 страници в секунда. Бавните заявки паднаха до нула, CPU-то на worker-ите спадна от лимита им до 12 до 15 процента, а паметта им – от 4 до 5 GB всеки на 0.65 GB.
Какво оставихме изключено
- Bot Fight Mode. Той предизвиква автоматизирания трафик и не може да бъде заобиколен с персонализирано правило в безплатния план, а хвана webhook-ите на нашия доставчик на плащания.
- Under Attack mode за цялата зона. Той прекарва всеки посетител, API клиент и webhook през междинната страница. Аварийното правило върши същата работа само за заявките за страници от непознати.
- Правилото за ограничаване на честотата в безплатния план. То брои на адрес, което това наводнение никога не задейства.
- Блокирането на AI паяци. Искаме да ни откриват AI търсачките, а тези паяци не бяха проблемът.
Изводът
Наводнение през резидентни прокси е лесно за разпознаване по липсващите елементи: заглавки на браузъра за fetch, бисквитки и Referer-и. Предизвикайте го на ръба, ограничете непознатите в рамките на това, което worker-ите ви могат да рендерират, и се уверете, че нещо извън сървъра забелязва, когато една страница спре да се отваря. Night Watch пакетира и трите: наблюдението, правилата с автоматичен превключвател за аварийното и вратата за Python уеб приложения.