Uma enxurrada de scrapers no plano gratuito da Cloudflare: o que a parou e o que deixamos desativado
Operações
Uma manhã, um dos nossos sites de listagens parou de abrir. A Cloudflare exibia aos visitantes um erro 524, a origem levava de dois a seis minutos por página e nada nos avisou por cerca de dez horas. A causa era um scraper passando por proxies residenciais a cerca de 225 requisições por segundo.
O formato da enxurrada
- Milhares de endereços, uma a três requisições cada. Conexões de banda larga residencial nos EUA, Espanha, França, Brasil, Reino Unido e outros lugares, o tipo de tráfego que uma rede de proxies residenciais aluga.
- User agents do Chrome em Mac, com números de versão de 103 a 151.
- Quase nunca um cookie ou um Referer. Das 2.697 requisições que amostramos no servidor, 4 traziam um cookie e 4 um Referer.
- Dois tipos de cliente. Cerca de metade não enviava cabeçalhos
Sec-Fetch-*nem client hints: um script com uma string de user agent copiada. A outra metade enviava cabeçalhos completos de navegador: um navegador headless.
Cada página era renderizada para cada requisição, então cada worker enfileirava centenas de renderizações e atingia seu limite de CPU.
Por que limites por endereço não ajudavam
Um rate limit conta requisições por endereço. Com uma a três requisições de cada um dos milhares de endereços, nenhum endereço isolado chega perto de um limite. Bloquear países teria bloqueado nossos visitantes. O que o scraper não podia fingir barato era se comportar como um navegador que já tinha visitado o site.
Na borda da Cloudflare: três regras gratuitas
O plano gratuito permite cinco regras personalizadas de WAF por zona. Usamos três, todas com um desafio gerenciado em vez de um bloqueio, para que uma pessoa pega por engano clique para passar:
- Navegador falso: um GET cujo user agent contenha
Chrome/e que não tenha cabeçalhoSec-Fetch-Mode. Todo Chrome desde 2019 o envia. - Nuvens de scraper: uma requisição de página das redes da Alibaba, Tencent e Huawei Cloud, de onde vinha grande parte do que desafiávamos.
- Emergência, desativado por padrão: um GET sem nenhum cookie e sem Referer. Uma pessoa que já esteve no site, ou que chega por um link, passa sem ser tocada; um scraper que não guarda cookies encontra um desafio em cada requisição. Só ativamos durante uma enxurrada, porque também desafia quem digita o endereço em um navegador novo.
Todos os três permitem a passagem dos bots verificados da Cloudflare, dos user agents que se identificam como robôs, dos nossos próprios endereços, dos caminhos da API e dos webhooks, e dos arquivos que não são páginas. Dois dias depois, a inundação continuava: em uma hora, a regra de navegador falso desafiou mais de 10.000 requisições. Os 10.000 eventos que a Cloudflare retorna por consulta vieram de 9.627 endereços, nenhum com mais de 4.
Na origem: um portão no aplicativo
A metade headless tem cabeçalhos de navegador completos, então as regras de borda sozinhas não a capturam enquanto a regra de emergência está desativada. No próprio aplicativo, colocamos um pequeno middleware na frente do renderizador de páginas:
- um user agent do Chrome sem
Sec-Fetch-Modenem client hints recebe um 403 antes de qualquer trabalho ser feito; - um estranho, sem nenhum dos nossos cookies e sem Referer, é atendido apenas enquanto o worker tem capacidade ociosa, a algumas páginas por segundo. Acima disso, uma página 503 de 400 bytes define um cookie e recarrega após dois segundos. Uma pessoa recebe a página na segunda tentativa; um scraper que não mantém cookies nunca recebe.
No primeiro minuto, o portão recusou cerca de 6.700 navegadores falsos e afastou cerca de 6.700 estranhos, enquanto servia aos estranhos cerca de 9 páginas por segundo. As requisições lentas caíram para zero, a CPU dos workers caiu do limite para 12 a 15 por cento, e a memória de 4 a 5 GB cada para 0,65 GB.
O que deixamos desativado
- Bot Fight Mode. Ele desafia o tráfego automatizado e não pode ser ignorado com uma regra personalizada no plano Free, e ele capturou os webhooks do nosso provedor de pagamentos.
- Modo Under Attack para toda a zona. Ele coloca todos os visitantes, clientes de API e webhooks através da página intersticial. A regra de emergência faz o mesmo trabalho apenas para requisições de páginas de estranhos.
- A regra de limitação de taxa do plano Free. Ela conta por endereço, o que esta inundação nunca dispara.
- Bloquear crawlers de IA. Queremos ser encontrados por assistentes de busca de IA, e esses crawlers não eram o problema.
A conclusão
Uma inundação por meio de proxies residenciais é fácil de identificar pelo que falta: cabeçalhos de requisição do navegador, cookies e Referers. Enfrente isso na borda, mantenha os estranhos dentro do que seus workers conseguem renderizar e garanta que algo fora do servidor perceba quando uma página parar de abrir. O Night Watch reúne os três: o watchdog, as regras com uma troca automática para a de emergência e o guarda para apps web em Python. As três regras e o guarda também são gratuitos e de código aberto no GitHub: cloudflare-free-shield e bot-gate.