1 pontos por GN⁺ 2 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Sem usar CDN, o texto organiza formas de bloquear a maioria dos bots com implementação ou configuração ruim combinando protocolo HTTP/faixas de IP/sinais do cliente/características TCP/impressão digital TLS/compressão de conteúdo
  • Todos os métodos devem ser ajustados de forma seletiva e, sem antes analisar 1 a 3 anos de logs de acesso, você pode acabar bloqueando junto usuários de VPN/motores de busca/CDN/escolas/bibliotecas/usuários de determinados idiomas
  • Bloquear clientes HTTP/1.1 e faixas AS/CIDR de datacenters pode remover muitos bots, mas também pode excluir motores de busca, incluindo o GoogleBot, e usuários legítimos de datacenters
  • A inspeção de cabeçalhos no Nginx e os filtros de tamanho de janela TCP/MSS/TTL no nftables reduzem crawlers e scanners simples, mas podem gerar falsos positivos em ambientes normais como LTE/VPN/Windows
  • Como alternativa de longo prazo, o texto propõe detecção de impressão digital TLS JA4 e respostas exclusivas em Brotli, mas alerta que isso não garante bloqueio completo e não deve ser usado em serviços com receita

Escopo do bloqueio e premissas de aplicação

  • Primeiro é preciso decidir se o objetivo é bloquear alguns bots, a maioria dos bots ou todos os bots
    • O foco das abordagens tratadas aqui não é todo tipo de ferramenta de automação sofisticada, e sim bloquear de forma relativamente simples a maioria dos bots com implementação ou configuração ruim
    • Para cada método, também é indicado o risco de bloquear usuários legítimos e motores de busca
  • Depois de ser compartilhado no Hacker News em 26 de julho de 2026, o autor decidiu mover a maior parte dos recursos de bloqueio do blog para um site de demonstração separado, transformando-o em um tipo de quebra-cabeça em que o leitor lê o método e depois tenta acessar por conta própria
  • Todas as configurações podem ser alteradas opcionalmente ou omitidas, e é necessário investigar e testar bastante antes de aplicar em produção
  • Como usuários legítimos/sistemas internos da organização/serviços externos dos quais se depende podem ser bloqueados, a responsabilidade pela aplicação é inteiramente do operador
  • Não usar em ambientes operacionais que gerem receita

Método 1: diferenciar pelo protocolo HTTP

  • O risco de bloquear usuários legítimos é baixo, e o risco de bloquear alguns motores de busca é médio
  • A ideia é explorar a diferença de que navegadores comuns usam HTTP/2.0, enquanto muitos bots usam HTTP/1.1
    • Considera-se que o GoogleBot usa HTTP/1.1 e, por esse método, será bloqueado
    • Os crawlers do Bing e do Facebook usam HTTP/2.0
    • Serviços que buscam títulos de links ou prévias curtas via HTTP/1.1 também podem ser bloqueados
    • O Opera Mini também fica excluído
  • No Nginx, configure para redirecionar para outra página ou retornar 200, 403 ou 444 se $server_protocol não for HTTP/2.0
if ($server_protocol != HTTP/2.0) {  
    return 403 'Upgrade your client';  
}  
  • Retornar 444 permite encerrar a conexão sem resposta separada
  • Cada organização deve avaliar por conta própria se o benefício obtido compensa a perda causada por bloquear tráfego vindo da busca do Google

Método 2: bloquear faixas de IP de datacenters

  • O risco de bloquear usuários domésticos/LTE legítimos é baixo, mas é médio para usuários de VPN e alto para motores de busca que operam em datacenters
  • Nos logs de acesso dos últimos 1 a 2 anos, identifique requisições suspeitas combinando os seguintes sinais
    • Protocolo HTTP
    • User-Agent
    • Accept-Language
    • Sec-Fetch-Mode
    • Accept
  • Consulte os IPs suspeitos em BGP Tools ou Hurricane Electric BGP Toolkit para verificar o AS ao qual pertencem e os Prefixes anunciados
  • A lista de blackholes de rede fornecida pode incluir faixas de CDN e motores de busca, então deve ser aplicada de forma seletiva
  • Antes de listas separadas, já se usa uma configuração que coloca em blackhole as faixas 3/8, 10/8, 11/8, 25/8, 26/8, 38/8, 41/8, 60/8, 61/8, 200/8, 224/3
  • Depois de copiar a página de Prefixes do AS, usa-se uma função de shell para extrair apenas os CIDRs, ordenar, remover duplicatas e consolidar
    • Usa-se sum_cidr.pl, e o módulo Perl Net::CIDR::Lite é necessário
    • Após revisão, o resultado gerado é movido para arquivos /usr/local/etc/*.netset
  • Na inicialização do servidor, cada CIDR é adicionado como rota blackhole
for CflIP in $(grep -E ^[1-9] /usr/local/etc/_cloudflare.netset); do  
    /sbin/ip route add blackhole "${CflIP}" 2>/dev/null  
done  
  • No exemplo, toda a faixa da Cloudflare é bloqueada para não aceitar requisições via Workers etc.
  • O método de roteamento é escolhido porque o roteamento blackhole do Linux usa menos CPU do que regras ipset do firewall
  • Também é possível bloquear as faixas da empresa de hospedagem à qual o servidor atual pertence
    • DNS/configuração/serviços internos não devem usar o mesmo espaço de endereços
    • Rotas de gateway diretamente conectadas têm prioridade sobre rotas blackhole

Método 3: bloquear país/proxy/Tor/IP malicioso

Método 4: inspecionar sinais do cliente HTTP

  • Parte-se da premissa de que User-Agent e cabeçalhos podem ser falsificados, mas bots simples que priorizam velocidade muitas vezes não os falsificam corretamente
  • Para requisições de Curl e Wget, retorna-se texto simples; para requisições que contenham Bot, GPT, LLM, Spider, retorna-se 410 Gone
if ($http_user_agent ~* Curl)   { return 200 '\nGNU Terry Pratchett\n\n'; }  
if ($http_user_agent ~* Wget)   { return 200 '\nGNU Terry Pratchett\n\n'; }  
if ($http_user_agent ~* Bot)    { return 410 '1000101'; }  
if ($http_user_agent ~* GPT)    { return 410 '1000101'; }  
if ($http_user_agent ~* LLM)    { return 410 '1000101'; }  
if ($http_user_agent ~* Spider) { return 410 '1000101'; }  
  • Parte das strings observadas em User-Agent é verificada com uma única regex longa para bloquear crawlers/scanners/ferramentas de coleta
    • Inclui substrings como Go-http, Java, libwww, okhttp, urllib, python, nmap, zgrab, semrush, shodan, rss, scrap, crawler, headless, github, facebook, google, bing
  • Antes de aplicar, é preciso agregar 2 a 3 anos de User-Agents e verificar se clientes legítimos reais batem na regex
sort access-user-agents.txt | uniq -c | sort  
  • Se a requisição correspondente for HTTP/1.1, ela é tratada como tendo alta probabilidade de ser bot, com exceção considerada para o GoogleBot
  • Se for uma requisição HTTP/2.0, a filiação do IP é verificada adicionalmente com ferramentas BGP

Sec-Fetch-Mode

  • Adicione Sec-Fetch-Mode ao log de acesso e bloqueie se o valor não for um entre cors, no-cors, navigate
if ($http_sec_fetch_mode !~ (cors|no-cors|navigate)) {  
    return 410 '1000101';  
}  

Verificação de Referer

  • Para impedir requisições que incorporam conteúdo ou fazem varredura a partir de outros sites, bloqueie quando Referer contiver determinadas strings
    • São verificados termos ligados a páginas de administração/motores de busca/redes sociais/criptomoedas/conteúdo adulto/scanners/WordPress etc.
  • Um tipo específico de bot que alega ter https://www.google.com/ como Referer também é bloqueado separadamente
    • É um padrão observado em requisições que fingem ser Android antigo

Restrição de métodos HTTP

  • Permita apenas GET e POST, necessários para requisições normais de navegador, e bloqueie os demais métodos
if ($request_method !~ (^GET$|^POST)) {  
    return 410 '1000101';  
}  
  • Dependendo da aplicação real, os caminhos que precisam de POST podem ser restringidos com mais detalhe ou totalmente excluídos se não forem usados

Verificação de proxy e aparência de navegador

  • Se houver cabeçalho X-Forwarded-For, considera-se que a requisição veio de proxy e ela é bloqueada
    • Ambientes legítimos de proxy compartilhado, como escolas ou bibliotecas, também podem acabar bloqueados
  • Se o User-Agent não contiver nenhum entre Linux, BSD, Macintosh, Windows, Mozilla, WhatsApp, considera-se que a requisição não se parece com navegador
  • Também se usa uma regra que bloqueia quando Accept-Language não contém en ou es
    • Há grande chance de bloquear alguns navegadores e usuários legítimos que não usam inglês ou espanhol
  • Também é apresentada uma regra opcional que bloqueia separadamente configurações de idioma contendo br ou sy

Bloqueio de varredura em caminhos sensíveis

  • Se forem requisitados os arquivos ou caminhos abaixo, isso é tratado como varredura automática e bloqueado
    • .git
    • .yml
    • .db
    • .sql
    • .conf

Método 5: bloquear scanners TCP com nftables

  • As características dos pacotes TCP SYN são inspecionadas na chain PREROUTING da tabela raw do nftables
  • O endereço de servidor de exemplo 172.238.221.88 é especificado como destino para reduzir falsos positivos que podem ocorrer em situações de perda de pacotes
  • Entre os pacotes SYN que chegam às portas 80/443, são bloqueados os que atendem às seguintes condições
    • Tamanho da janela TCP menor que 12.288 bytes
    • MSS fora da faixa de 1.220 a 1.460
  • O critério usado é que clientes reais usam janelas maiores, e MSS fora dessa faixa tem baixa probabilidade de vir de cliente legítimo
  • Restringir o MSS exatamente a 1460 torna a regra mais rígida, mas pode bloquear a maioria dos usuários de LTE e VPN

Restrição opcional baseada em TTL

  • Se o TTL do TCP SYN for maior que 128, a maioria dos dispositivos LTE pode ser bloqueada
  • Se o TTL for maior que 64, a maioria dos sistemas Windows também será bloqueada
  • Os valores base de TTL são explicados assim
    • Linux/Mac/BSD: 64
    • Windows: 128
    • LTE: valores maiores que esses

Exclusão do rastreamento de conexão

  • Define-se notrack para as portas 80/443 para não colocar o tráfego web na tabela conntrack
  • Nesse caso, é preciso configurar diretamente regras sem estado para direção de envio e recebimento também na tabela filter
  • No exemplo, permite-se tráfego entre portas de origem do cliente 1000-65535 e as portas 80/443 do servidor

Método 6: conteúdo adulto e cabeçalhos para robôs

  • Para restringir acesso a conteúdo adulto, usa-se o cabeçalho RTA: Restricted To Adults
  • Considera-se que métodos de verificação de idade além do RTA servem para rastreamento de usuários e monetização
  • Os seguintes cabeçalhos são sempre adicionados às respostas do Nginx
add_header Rating 'RTA-5042-1996-1400-1577-RTA' always;  
add_header adult 'porn, sex, politics, religion, philosophy' always;  
add_header X-Robots-Tag "none,noindex,nofollow,nosnippet,noai" always;  
  • Bots comuns podem ignorar esses cabeçalhos, mas isso pode afetar motores de busca ou bots projetados para evitar conteúdo adulto

Método 7: detecção de impressão digital TLS

  • Os métodos 1 a 6 acima são todos heurísticas grosseiras, e no longo prazo a análise de impressão digital TLS pode ser uma escolha melhor
  • O JA4 pode ser usado sob a condição de que o bot não altere sua impressão digital TLS para ficar idêntica à de um navegador normal
  • Primeiro, recomenda-se verificar o método de implantação em Deploying JA4 e depois aplicar o FoxIO JA4

Método 8: servir apenas conteúdo comprimido com Brotli

  • O conteúdo do site é previamente comprimido com Brotli, e o servidor web é configurado para retornar apenas arquivos comprimidos
  • A ideia é aproveitar o fato de que muitos bots não conseguem interpretar HTML comprimido com Brotli
  • Após a aplicação, confirmou-se que vários bots deixaram de seguir links da página, indicando que não conseguiam de fato fazer parse do HTML
  • No Nginx, configura-se para sempre servir arquivos Brotli estáticos
brotli_static always;  
  • Os arquivos HTML são pré-comprimidos assim
cat ./i.html | brotli --best -fncv > ./i.html.br  

Método 9: induzir scanners a se autoidentificarem

  • Um método separado para reduzir atacantes iniciantes e scanners que repetidamente exploram caminhos de vulnerabilidade é tratado em Help Attackers Self Report

1 comentários

 
GN⁺ 2 시간 전
Opiniões no Hacker News
  • Como alguém que opera vários sites públicos e também raspa outros sites para usar em ferramentas, fico me perguntando por que as pessoas se preocupam tanto com bots.
    Até um WordPress com cache consegue lidar com cerca de 1.000 requisições por segundo no VPS mais barato, e um site estático bem feito provavelmente aguentaria 10 vezes isso. Fico curioso se estão servindo blogs com algo como Lambda, ou se é obsessão, defesa contra vulnerabilidades, ou um hábito da época em que crawlers realmente afetavam serviços em produção.

    • No meu caso, o problema é uma instância do Forgejo. Um blog é só um conjunto limitado de arquivos estáticos, então tudo bem, mas o Forgejo é um serviço dinâmico em que bots conseguem descobrir páginas praticamente sem limite, e algumas páginas até executam Git em segundo plano ao serem geradas, então um servidor pequeno sobrecarrega facilmente.
      Os repositórios são open source, então os mantenho públicos de propósito. Hoje me defendo com uma verificação simples de cookies, que só deixa passar alguns poucos bots, mas é um compromisso que sacrifica a exposição em mecanismos de busca.
    • Meu site pessoal em hospedagem compartilhada foi suspenso recentemente porque o uso de CPU ficou excessivo devido ao rastreamento constante por bots de IA. O problema não é tanto o rastreamento em si, mas o fato de haver bots demais e eles operarem de forma muito ineficiente.
    • É um experimento feito pela diversão de procurar características comuns, como JavaScript, que sejam difíceis para operadores de bots evitarem ou contornarem. Este blog usa conteúdo estático pré-comprimido em um disco RAM, então provavelmente conseguiria lidar com centenas de milhares de requisições por segundo.
      A ideia é mostrar métodos aplicáveis a fóruns, imageboards, servidores de chat etc., e todas as opções podem ser ajustadas ou desligadas. Antes de aplicar de verdade, é preciso validar em um servidor de teste; e tudo bem também só rir disso e seguir em frente.
    • Em casa, não dá para ter uma conexão de 40 Gbit e servidores compatíveis. Mesmo que alguns VPSs do Google Cloud rodem nmap e diversos testes de vulnerabilidade web, fazendo um ataque distribuído de negação de serviço, o desempenho de hardware modesto cai facilmente.
      Não é o fim do mundo levar alguns segundos a mais para verificar um servidor IMAP local porque a DMZ ficou travada, mas isso também não significa que eu tenha que gostar ou continuar permitindo.
    • O maior problema é que lidar com bots toma tempo que poderia ser gasto em coisas mais úteis.
      No fim de semana, encerrei interfaces web viewvc (CVS/Subversion) e hgweb (Mercurial) que eu operava havia 10 a 20 anos. De IPs de proxies residenciais vinham 2,7 milhões de requisições por dia, em média 30 por segundo, sobrecarregando programas uWSGI/CGI antigos e outros sites no mesmo servidor, e o tráfego também estava se aproximando do limite do VPS, de 1 TB por mês.
      Como as combinações dinâmicas de URLs de VCS podem chegar a milhões, o efeito do cache também era incerto; e não valia a pena gastar tempo ajustando ainda mais o servidor. No fim, escolhi dar mais um passo rumo a uma internet centralizada.
  • Bloquear tudo exceto agentes de usuário “aprovados” ajuda o monopólio dos navegadores existente e acelera a distopia. É exatamente esse tipo de problema que RMS vem alertando há décadas.
    Se há um problema, o bloqueio deveria se basear no volume de tráfego e na frequência das requisições. Eu também não consigo acessar o site, mas não pretendo mudar meu comportamento por causa disso; como no DRM, adversários determinados acabarão passando.

    • Essa crítica é aceitável. Já estive com RMS algumas vezes; ele é uma pessoa interessante e muito inteligente, e se eu o tivesse encontrado por causa desse problema, provavelmente teria ouvido uma bronca interminável.
      Dito isso, independentemente da alegação de que qualquer navegador pode ser usado, é preciso ter especial cuidado com navegadores gerados de improviso ou que não foram suficientemente testados contra sites maliciosos. Aplicativos leitores também podem ser vulneráveis a servidores maliciosos se não tiverem passado por uma revisão ampla de código de terceiros feita por especialistas em testes de intrusão.
    • Também dá para julgar pelo comportamento. O go-away verifica se imagens e CSS são carregados e se redirecionamentos por meta refresh são seguidos; o Anubis confirma se é possível executar JavaScript por alguns segundos.
    • A própria string de agente de usuário é, em geral, prejudicial. Se for um navegador novo, é melhor simplesmente copiar o agente de usuário do Chrome.
  • Gosto da ideia de adicionar um subdomínio cpanel falso apontando para 169.254.169.254, fazendo atacantes iniciantes escanearem as portas do próprio provedor de hospedagem e, assim, serem detectados ou bloqueados.

    • Quando testei pela primeira vez, achei que nada aconteceria. Em poucos dias, alguém da Amazon EC2 na Alemanha tentou fazer uma transferência de zona em parte do meu domínio, aparentemente para encontrar registros que deveria evitar; depois disso, excluiu completamente meu domínio, e os scans também pararam logo em seguida.
      Embora os IPs de origem estivessem espalhados pelo mundo, o ruído real de varredura vinha de uma única pessoa.
    • Não vejo motivo para a AWS rodar fail2ban no Instance Metadata Service (IMDS). Será que eles não confiam na própria implementação, ou querem levar processo de um grande cliente?
  • Bloqueio baseado em IP exige cuidado. Faixas de IP às vezes são realocadas, então você pode acabar bloqueando a pessoa errada; já vi várias vezes faixas que tinham sido bloqueadas por serem de uma região ou data center passarem para um ISP residencial
    Bloquear HTTP/1.1 também traz um grande risco de impedir usuários reais que usam navegadores antigos. Além disso, há navegadores que não enviam a URL completa em requisições cross-origin; se o tráfego vier da Busca do Google, o referer pode apontar apenas para a página raiz do Google. Portanto, se você concluir que isso é uma mentira de bot e bloquear, pode acabar perdendo também o tráfego vindo da Busca do Google

    • Infelizmente, também há muita gente cuja rede é revendida sem que ela saiba como VPN residencial
      Por outro lado, acho razoável bloquear HTTP/1.1. Faz mais de 10 anos que praticamente todos os navegadores suportam protocolos além dele, e, se o navegador é antigo a esse ponto, a maior parte da Web dominante já deve quebrar nele; então mais um site pessoal não funcionar seria a regra, não a exceção
    • Em sites de hobby e experimentos, bloqueio completamente todos os ASNs do Google. Ultimamente não tenho recebido tráfego útil, e acho que a qualidade da busca também se deteriorou
      Mesmo que eu perca navegadores antigos e ferramentas de API, pretendo manter o bloqueio de HTTP/1.1. Entendo se for código proprietário de um sistema financeiro legado, mas a Internet pública precisa se atualizar por conta própria
      Como bloqueio o Google há muito tempo, toda requisição que diz vir do Google é falsa. Tento circular o blog por vários domínios aleatórios para quebrar relações e snapshots, e controlar por quais caminhos as pessoas descobrem meus textos
    • Alguns anos atrás, bloqueei o tráfego vindo da AWS e escrevi um post sobre isso. Normalmente tenho só algumas dezenas de visitantes reais por semana, mas esse texto foi visto por cerca de 15.000 pessoas reais durante uns 3 meses e depois foi rapidamente esquecido
      De quebra, recebi um teste de intrusão gratuito e concluí que minhas defesas e meu pipeline de processamento eram robustos. Por pressão de sobrevivência, 90% do tráfego de bots migrou para VPNs, e os endpoints de VPN estão brilhando como árvores de Natal
      Eu poderia fornecer um feed de IPs de acesso descartável, mas os usuários teriam de ser devidamente verificados e ter o uso aprovado. Esse processo em si é divertido
    • O autor deixou claro que não se importa em bloquear vários tipos de usuários reais, então não vou seguir esse conselho
  • Se não conseguir ler, dá para ver a versão arquivada em https://archive.ph/d3236

    • É uma implementação infeliz para usuários comuns do Safari no iOS: https://i.ibb.co/vCDH79d0/IMG-0303.png
      Não quero desativar o iCloud Private Relay só para ler algo quando nem sou um bot. Pelas outras respostas do autor, é uma boa implementação como site de teste, mas espero que outros administradores web não adotem todos esses métodos do mesmo jeito, se puderem evitar
    • Achei interessante que eu não consegui acessar, mas o crawler do archive.ph passou sem problemas
  • Pelo corpo da resposta mostrar só 410 e a string Sec-Fetch-Mode:, parece que fui classificado como bot. Não há nada para ler nem ver, então simplesmente vou embora; a Web moderna é horrível

    • Navegadores reais enviam esse header, mas alguns apps de leitura e a maioria dos bots que não usa Chrome Headless não enviam
      O status de suporte pode ser conferido em https://caniuse.com/?search=sec-fetch-mode, e alguns headers em https://nochan.net/.env
    • Eu nem cheguei a esse ponto: recebi PR_END_OF_FILE_ERROR, indicando que nem o handshake TLS foi concluído
  • Imagino que mais de 99% do tráfego web seja de bots ou agentes, então estou pensando em remover a exibição de contagem de visitantes. O número não tem significado e faz o site parecer muito mais movimentado do que realmente é, mas hesito em reagir porque temo impedir pessoas reais de ler os textos ou baixar os livros

    • Tecno-thrillers, ficção científica e romances de mistério? Quero dar uma olhada depois
  • Se o bloqueio for necessário, em geral uma lista de permissão é mais eficaz que uma lista de bloqueio; se não der para aplicar uma lista de permissão, esse método também pode não ser uma boa solução
    Ferramentas como Cloudflare e Anubis podem causar sérios problemas de acessibilidade, então prefiro limitação de frequência de requisições. É limpa e não prejudica a acessibilidade; para problemas temporários, bloqueios curtos de IP também funcionam bem
    Pessoalmente, uso fail2ban para analisar logs HTTP e bloquear por N horas IPs que solicitam URLs proibidas em robots.txt, caminhos como wp-login.php, ou que ultrapassam com frequência excessiva o limite de requisições. No momento estou testando o Anubis na UI web do Git

    • Em comunicação entre empresas, implementei a lista de permissão com VPN entre redes. Fora da VPN, não é possível acessar o servidor, e os funcionários podem se conectar pela VPN da empresa
  • Só com fail2ban já dá para bloquear bastante coisa, mas nos primeiros meses é preciso ajustar em detalhes ao ambiente
    Primeiro eu detectava com o filtro failregex = ^ - \S+ \[\] ".*?" 40[034] e depois adicionava a listas mais específicas; hoje uso cerca de 80 expressões regulares para bloquear todo o tráfego, e há muito tempo nenhuma requisição chega ao filtro genérico 40[034]
    Mas, atrás de um load balancer ou proxy, é preciso algum método para obter o IP real, o que torna tanto o fail2ban quanto a abordagem do texto original mais trabalhosos

    • A maioria dos load balancers de camada 7 oferece a função de adicionar um header com o IP real. Basta configurar o servidor web para registrar esse header; é muito parecido com a forma como uma CDN repassa o IP real
  • A julgar por estes comentários e pelas minhas tentativas de acesso, parece que não estão bloqueando só bots, mas todo o tráfego legítimo também

    • Só pelos comentários dá para entender errado. Até agora, cerca de 2.600 pessoas e alguns bots conseguiram ver o texto
      Aos domingos, dá para ver a maior variedade de navegadores e apps incomuns que as pessoas usam para navegar na Web; em dias úteis, há mais navegadores convencionais, o que vira um bom teste