1 puntos por GN⁺ 1 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Sin usar un CDN, se resume cómo bloquear a la mayoría de los bots con implementaciones o configuraciones deficientes combinando protocolo HTTP/rangos IP/señales del cliente/características TCP/huella TLS/compresión de contenido
  • Todos los métodos deben ajustarse de forma selectiva, y si no se analizan primero los logs de acceso de 1 a 3 años, se puede terminar bloqueando también a usuarios de VPN/motores de búsqueda/CDN/escuelas/bibliotecas/personas que usan ciertos idiomas
  • Bloquear clientes HTTP/1.1 y rangos AS/CIDR de centros de datos puede eliminar muchos bots, pero también puede excluir a motores de búsqueda como GoogleBot y a usuarios legítimos de centros de datos
  • La inspección de encabezados en Nginx y los filtros de tamaño de ventana TCP/MSS/TTL en nftables reducen crawlers y escáneres simples, pero pueden generar falsos positivos en entornos legítimos como LTE/VPN/Windows
  • Como alternativa a largo plazo, se proponen la detección de huellas TLS JA4 y respuestas exclusivas con Brotli, pero se advierte que no garantizan un bloqueo completo y que no deben usarse en servicios que generan ingresos

Alcance del bloqueo y supuestos de aplicación

  • Primero hay que decidir si el objetivo es bloquear algunos bots, la mayoría de los bots o todos los bots
    • El enfoque aquí no es detener a todas las herramientas de automatización sofisticadas, sino bloquear de forma relativamente simple a la mayoría de los bots con implementaciones o configuraciones deficientes
    • Para cada método también se indica el riesgo de bloquear usuarios legítimos y motores de búsqueda
  • Después de compartirse en Hacker News el 26 de julio de 2026, se decidió mover la mayoría de las funciones de bloqueo del blog a un sitio de demostración aparte y convertirlo en una especie de rompecabezas donde el lector lee el método e intenta acceder por su cuenta
  • Todas las configuraciones pueden modificarse u omitirse de forma selectiva, y antes de aplicarlas de verdad hace falta suficiente investigación y pruebas
  • Como podrían bloquearse usuarios legítimos/sistemas internos de la organización/servicios externos de los que se depende, la responsabilidad de aplicarlo recae por completo en el operador
  • No usar en entornos de producción que generan ingresos

Método 1: distinguir por protocolo HTTP

  • El riesgo de bloquear usuarios legítimos es bajo, y el riesgo de bloquear algunos motores de búsqueda es intermedio
  • Se aprovecha la diferencia de que los navegadores comunes usan HTTP/2.0, mientras que muchos bots usan HTTP/1.1
    • Se considera que GoogleBot usa HTTP/1.1, por lo que queda bloqueado con este método
    • Los crawlers de Bing y Facebook usan HTTP/2.0
    • También pueden bloquearse servicios que obtienen títulos de enlaces o vistas previas cortas por HTTP/1.1
    • Opera Mini también queda excluido
  • En Nginx se configura para redirigir a otra página o devolver 200, 403 o 444 si $server_protocol no es HTTP/2.0
if ($server_protocol != HTTP/2.0) {  
    return 403 'Upgrade your client';  
}  
  • Si se devuelve 444, la conexión puede cerrarse sin respuesta adicional
  • Cada organización debe evaluar por sí misma si el beneficio obtenido supera la pérdida causada por bloquear el tráfico proveniente de Google Search

Método 2: bloquear rangos IP de centros de datos

  • El riesgo de bloquear usuarios residenciales/LTE legítimos es bajo, pero para usuarios de VPN es intermedio, y para motores de búsqueda que operan desde centros de datos es alto
  • En los logs de acceso de los últimos 1 a 2 años, se combinan las siguientes señales para encontrar solicitudes sospechosas
    • protocolo HTTP
    • User-Agent
    • Accept-Language
    • Sec-Fetch-Mode
    • Accept
  • Las IP sospechosas se consultan en BGP Tools o en Hurricane Electric BGP Toolkit para verificar el AS al que pertenecen y los Prefix anunciados
  • La lista de blackholes de red incluida puede contener también rangos de CDN y motores de búsqueda, por lo que debe aplicarse con criterio
  • Antes de las listas separadas, ya se usa una configuración que hace blackhole de los rangos 3/8, 10/8, 11/8, 25/8, 26/8, 38/8, 41/8, 60/8, 61/8, 200/8, 224/3
  • Después de copiar la página de Prefix de un AS, se extraen solo los CIDR con una función de shell y se ordenan/se eliminan duplicados/se fusionan
    • Se usa sum_cidr.pl y se requiere el módulo de Perl Net::CIDR::Lite
    • El resultado generado se revisa y luego se mueve a archivos /usr/local/etc/*.netset
  • Al iniciar el servidor, cada CIDR se agrega como ruta blackhole
for CflIP in $(grep -E ^[1-9] /usr/local/etc/_cloudflare.netset); do  
    /sbin/ip route add blackhole "${CflIP}" 2>/dev/null  
done  
  • En el ejemplo, se bloquean todos los rangos de Cloudflare para no aceptar solicitudes a través de Workers, etc.
  • Se elige el enrutamiento porque el blackhole routing de Linux usa menos CPU que las reglas ipset del firewall
  • También se puede bloquear el rango del proveedor de hosting al que pertenece el servidor actual
    • DNS/configuración/servicios internos no deben usar el mismo espacio de direcciones
    • Las rutas de gateway conectadas directamente tienen prioridad sobre las rutas blackhole

Método 3: bloqueo por país/proxy/Tor/IP maliciosas

Método 4: inspección de señales del cliente HTTP

  • Se parte de la idea de que, aunque el User-Agent o los encabezados pueden falsificarse, muchos bots simples priorizan la velocidad y no los falsifican bien
  • A las solicitudes de Curl o Wget se les devuelve texto plano, y a las que incluyen Bot, GPT, LLM o Spider se les devuelve 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'; }  
  • Se inspeccionan algunas cadenas observadas en User-Agent con una sola expresión regular larga para bloquear crawlers/escáneres/herramientas de recolección
    • Incluye subcadenas como Go-http, Java, libwww, okhttp, urllib, python, nmap, zgrab, semrush, shodan, rss, scrap, crawler, headless, github, facebook, google, bing
  • Antes de aplicarlo, hay que agregar los User-Agent de 2 a 3 años para comprobar si clientes legítimos reales coinciden con la expresión regular
sort access-user-agents.txt | uniq -c | sort  
  • Si una solicitud coincidente es HTTP/1.1, se considera con alta probabilidad que sea un bot, aunque GoogleBot se toma como excepción
  • Si la solicitud es HTTP/2.0, se revisa además la pertenencia de la IP con herramientas BGP

Sec-Fetch-Mode

  • Se agrega Sec-Fetch-Mode a los logs de acceso y se bloquea si el valor no es cors, no-cors o navigate
if ($http_sec_fetch_mode !~ (cors|no-cors|navigate)) {  
    return 410 '1000101';  
}  

Inspección de Referer

  • Para impedir solicitudes que insertan contenido o escanean desde otros sitios, se bloquea si Referer contiene ciertas cadenas
    • Se inspeccionan cadenas relacionadas con páginas de administración/motores de búsqueda/redes sociales/criptomonedas/contenido para adultos/escáneres/WordPress
  • También se bloquea por separado cierto tipo de bot que afirma usar la página raíz de Google https://www.google.com/ como Referer
    • Es un patrón observado en solicitudes que se hacen pasar por Android antiguo

Restricción de métodos HTTP

  • Solo se permiten GET y POST, que son los necesarios para solicitudes normales del navegador; los demás métodos se bloquean
if ($request_method !~ (^GET$|^POST)) {  
    return 410 '1000101';  
}  
  • En la aplicación real, se puede restringir con más detalle qué rutas necesitan POST, o excluirlo por completo si no se usa

Inspección de proxies y forma de navegador

  • Si existe el encabezado X-Forwarded-For, se considera una solicitud por proxy y se bloquea
    • También podrían bloquearse entornos legítimos de proxy compartido como escuelas o bibliotecas
  • Si el User-Agent no contiene ninguna de estas cadenas: Linux, BSD, Macintosh, Windows, Mozilla, WhatsApp, se considera una solicitud que no parece venir de un navegador
  • También se usa una regla que bloquea si Accept-Language no contiene en o es
    • Hay alta probabilidad de bloquear algunos navegadores y usuarios legítimos que no usan inglés o español
  • También se presenta una regla opcional para bloquear por separado configuraciones de idioma que incluyan br o sy

Bloqueo de escaneo de rutas sensibles

  • Si se solicitan los siguientes archivos o rutas, se considera escaneo automático y se bloquea
    • .git
    • .yml
    • .db
    • .sql
    • .conf

Método 5: bloquear escáneres TCP con nftables

  • Se inspeccionan las características de los paquetes TCP SYN en la cadena PREROUTING de la tabla raw de nftables
  • Para reducir falsos positivos que pueden ocurrir en situaciones de pérdida de paquetes, se especifica la dirección de destino del servidor de ejemplo 172.238.221.88
  • Entre los paquetes SYN entrantes a los puertos 80/443, se bloquean los que cumplan estas condiciones
    • tamaño de ventana TCP menor a 12,288 bytes
    • MSS fuera del rango 1,220~1,460
  • Se usa como criterio que los clientes reales emplean tamaños de ventana más grandes y que un MSS fuera de ese rango tiene baja probabilidad de corresponder a un cliente legítimo
  • Si se restringe el MSS exactamente a 1460, se vuelve más estricto, pero podría bloquear a la mayoría de los usuarios de LTE y VPN

Restricción opcional basada en TTL

  • Si el TTL del TCP SYN es mayor que 128, se puede bloquear a la mayoría de los dispositivos LTE
  • Si el TTL es mayor que 64, también se bloquea a la mayoría de los sistemas Windows
  • Los criterios de TTL base se explican así
    • Linux/Mac/BSD: 64
    • Windows: 128
    • LTE: un valor mayor que esos

Exclusión del seguimiento de conexiones

  • Se marca 80/443 como notrack para que el tráfico web no entre a la tabla conntrack
  • En ese caso, en la tabla filter también hay que configurar manualmente reglas sin estado para las direcciones de envío y recepción
  • En el ejemplo, se permite el tráfico entre los puertos de origen del cliente 1000-65535 y los puertos 80/443 del servidor

Método 6: contenido para adultos y encabezados para robots

  • Para restringir el acceso a contenido para adultos, se usa el encabezado RTA: Restricted To Adults
  • Se considera que los métodos de verificación de edad distintos de RTA existen para rastrear usuarios y monetizar
  • En las respuestas de Nginx se agregan siempre los siguientes encabezados
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;  
  • Los bots comunes pueden ignorar estos encabezados, pero podrían afectar a motores de búsqueda o bots diseñados para evitar contenido para adultos

Método 7: detección de huellas TLS

  • Los métodos 1 a 6 anteriores son heurísticas bastante toscas, y a largo plazo el análisis de huellas TLS puede ser una mejor opción
  • JA4 puede aprovecharse bajo la condición de que el bot no cambie su huella TLS para igualarla a la de un navegador normal
  • Primero se indica revisar el método de despliegue de Deploying JA4 y luego aplicar FoxIO JA4

Método 8: entregar solo contenido comprimido con Brotli

  • Se comprime previamente el contenido del sitio con Brotli y se configura el servidor web para devolver solo los archivos comprimidos
  • Se aprovecha que muchos bots no pueden interpretar HTML comprimido con Brotli
  • Después de aplicarlo, se confirmó que varios bots dejaron de seguir enlaces de páginas, lo que indica que en realidad no podían parsear el HTML
  • En Nginx se configura para servir siempre archivos Brotli estáticos
brotli_static always;  
  • Los archivos HTML se comprimen previamente de la siguiente forma
cat ./i.html | brotli --best -fncv > ./i.html.br  

Método 9: inducir a que los escáneres se identifiquen solos

  • Otro método para reducir atacantes principiantes y escáneres que exploran repetidamente rutas de vulnerabilidades se trata en Help Attackers Self Report

1 comentarios

 
GN⁺ 1 시간 전
Comentarios de Hacker News
  • Como alguien que opera varios sitios web públicos y usa herramientas para extraer datos de otros sitios, me pregunto por qué a la gente le preocupan tanto los bots
    Incluso WordPress con caché puede manejar alrededor de 1,000 solicitudes por segundo en el VPS más barato, y un sitio estático bien hecho probablemente podría con 10 veces eso. Me pregunto si están sirviendo el blog con algo como Lambda, o si es obsesión, defensa ante vulnerabilidades, o una costumbre de cuando el scraping sí afectaba al servicio real

    • En mi caso, el problema es la instancia de Forgejo. El blog está bien porque son archivos estáticos con un número limitado de páginas, pero en Forgejo los bots pueden descubrir páginas prácticamente sin límite, y algunas páginas hasta ejecutan Git en segundo plano al generarse, así que un servidor pequeño se sobrecarga fácilmente
      El repositorio es de código abierto, así que está expuesto a propósito. Ahora mismo me defiendo con una simple verificación de cookies y solo unos pocos bots pasan, pero es una concesión a costa de la visibilidad en buscadores
    • Mi sitio personal en hosting compartido fue suspendido recientemente por uso excesivo de CPU debido al rastreo constante de bots de IA. El problema no es tanto el rastreo en sí, sino que hay demasiados bots y funcionan de forma ineficiente
    • Es un experimento que hago por diversión para buscar características comunes, como JavaScript, que a los operadores de bots les resulte difícil evitar o eludir. Este blog tiene contenido estático precomprimido en un disco RAM, así que probablemente podría manejar cientos de miles de solicitudes por segundo
      La idea es mostrar cómo aplicarlo a foros, imageboards, servidores de chat, etc., y todas las opciones se pueden ajustar o desactivar. Antes de aplicarlo en producción habría que validarlo en un servidor de pruebas, y también está bien si solo quieres reírte y seguir de largo
    • En casa no puedo tener un enlace de 40 Gbit ni servidores acordes. Basta con que unas cuantas VPS de Google Cloud ejecuten nmap y varios escáneres de vulnerabilidades web para que el rendimiento de hardware modesto caiga fácilmente por un ataque distribuido de denegación de servicio
      Que tarde unos segundos más en revisar mi servidor IMAP local porque la DMZ está saturada no es el fin del mundo, pero tampoco hay razón para que eso me guste o para seguir permitiéndolo
    • El mayor problema es que me quita tiempo que podría dedicar a cosas más útiles que lidiar con bots
      El fin de semana cerré las interfaces web de viewvc (CVS·Subversion) y hgweb (Mercurial) que había operado por 10~20 años. Llegaban 2.7 millones de solicitudes al día, unas 30 por segundo en promedio, desde IPs de proxies residenciales, lo que cargaba programas antiguos de uWSGI/CGI y otros sitios en el mismo servidor, y además el tráfico se acercaba al límite mensual de 1 TB de mi VPS
      Como las combinaciones dinámicas de URLs de VCS pueden llegar a cientos de millones, ni siquiera estaba claro que el caché ayudara, y no valía la pena seguir gastando tiempo afinando el servidor, así que al final tomé una decisión que nos acerca un paso más a un internet centralizado
  • Si bloqueas todo excepto los agentes de usuario “aprobados”, terminas ayudando al actual monopolio de navegadores y acelerando la distopía. Este es justo el tipo de problema sobre el que RMS viene advirtiendo desde hace décadas
    Si de verdad es un problema, deberías bloquear según el volumen de tráfico y la frecuencia de las solicitudes. Yo tampoco puedo acceder a tu sitio, pero no pienso actuar según eso, y como con el DRM, un oponente realmente decidido acabará pasando de todos modos

    • Puedo aceptar esa crítica. Coincidí con RMS algunas veces; es una persona interesante y muy brillante, y si nos hubiéramos encontrado por este tema seguramente me habría dado un sermón interminable
      Aun así, aparte del argumento de que deberías poder usar cualquier navegador, hay que tener especial cuidado con navegadores hechos con código generado al vuelo o no suficientemente auditados frente a sitios maliciosos. Incluso una app lectora podría ser vulnerable a un servidor malicioso si no pasó por una revisión extensa de código de terceros por parte de expertos en pruebas de penetración
    • También se puede juzgar por comportamiento. go-away comprueba si carga imágenes y CSS, y si sigue redirecciones por meta refresh; Anubis verifica si puede ejecutar JavaScript durante unos segundos
    • La cadena de agente de usuario en sí suele ser perjudicial. Si es un navegador nuevo, conviene más simplemente copiar el agente de usuario de Chrome
  • Me gusta la idea de agregar un subdominio falso de cpanel que apunte a 169.254.169.254, para que atacantes novatos terminen haciéndole un port scan a su propio proveedor de hosting y puedan ser detectados o bloqueados

    • Cuando lo probé por primera vez, pensé que no pasaría nada. A los pocos días, alguien en Amazon EC2 de Alemania intentó una transferencia de zona sobre parte de mi dominio, como si buscara registros que debía evitar, y después excluyó mi dominio por completo y el escaneo pronto se detuvo
      Las IP de origen estaban dispersas por todo el mundo, pero el ruido real del escaneo venía de una sola persona
    • No entiendo por qué AWS tendría motivos para ejecutar fail2ban en el servicio de metadatos de instancia (IMDS). Me pregunto si no confían en su implementación, o si quieren que algún gran cliente los demande
  • Hay que tener cuidado con el bloqueo basado en IP. Los rangos de IP a veces se reasignan, así que puedes terminar bloqueando a gente equivocada; también he visto varias veces rangos bloqueados por ser de una región o de un datacenter que luego pasan a un ISP residencial
    Bloquear HTTP/1.1 también implica un alto riesgo de bloquear usuarios reales que usan navegadores antiguos. Además, hay navegadores que no envían la URL completa en solicitudes de origen cruzado, así que si alguien llega desde una búsqueda de Google, el referer podría apuntar solo a la página raíz de Google; si asumes que eso es una mentira de un bot y lo bloqueas, también podrías perder tráfico proveniente de Google Search

    • También hay tristemente muchas personas cuya red se revende como VPN residencial sin que ellas lo sepan
      En cambio, sí me parece razonable bloquear HTTP/1.1. Ya pasaron más de 10 años desde que casi todos los navegadores soportan protocolos más nuevos, y si un navegador es así de viejo, gran parte de la web actual ya se le rompe, así que que un sitio personal más no funcione no sería una excepción sino algo cotidiano
    • En sitios de hobby y experimentación bloqueo por completo todos los ASN de Google. Últimamente no he recibido tráfico útil de ahí y creo que la calidad de búsqueda también se arruinó
      Aunque eso implique perder navegadores viejos y herramientas de API, pienso mantener el bloqueo de HTTP/1.1. Si fuera código propietario de un sistema financiero antiguo lo entendería, pero el internet público debe actualizarse por su propio bien
      Como bloqueé a Google desde hace mucho, cualquier solicitud que diga venir de Google es mentira. Hago rotar el blog entre varios dominios aleatorios para romper asociaciones y snapshots, y trato de controlar por dónde descubre la gente mis textos
    • Hace unos años bloqueé el tráfico que venía de AWS y escribí sobre eso. Normalmente tengo apenas unas decenas de visitantes reales por semana, pero ese texto lo vieron unos 15,000 humanos reales durante cerca de 3 meses y luego se olvidó rápido
      Gracias a eso también recibí pruebas de penetración gratis y concluí que mis defensas y mi pipeline de procesamiento son sólidos. Por presión de supervivencia, el 90% del tráfico bot se movió a VPN y los endpoints de VPN están brillando como árbol de Navidad
      Podría incluso ofrecer un feed de IP de acceso de un solo uso, pero el usuario tendría que pasar una verificación adecuada y que se apruebe su propósito. Ese proceso en sí es divertido
    • El autor deja claro que no le importa bloquear varios tipos de usuarios reales, así que no seguiría su consejo
  • Si no se puede leer, puede verse en el respaldo https://archive.ph/d3236

    • Es una implementación desafortunada para usuarios normales de iOS Safari: https://i.ibb.co/vCDH79d0/IMG-0303.png
      No soy un bot, pero tampoco quiero desactivar iCloud Private Relay para poder leer algo. Según otra respuesta del autor, como sitio de prueba es una buena implementación, pero ojalá otros administradores web no copien tal cual todos los métodos si pueden evitarlo
    • También me pareció curioso que yo no pudiera entrar, pero el crawler de archive.ph sí pasó sin problemas
  • Por cómo el cuerpo de la respuesta solo muestra 410 y la cadena Sec-Fetch-Mode:, parece que me clasificó como bot. No hay nada que leer ni ver, así que uno simplemente se va; la web moderna es terrible

    • Los navegadores reales sí envían ese header, pero algunas apps de lectura y la mayoría de los bots que no usan Chrome Headless no lo envían
      El soporte puede verse en https://caniuse.com/?search=sec-fetch-mode y algunos headers pueden revisarse en https://nochan.net/.env
    • Ni siquiera llegué tan lejos: me salió PR_END_OF_FILE_ERROR, lo que indica que no pude pasar ni el handshake de TLS
  • Estoy pensando en quitar el contador de visitas, porque calculo que más del 99% del tráfico web son bots o agentes. La cifra no significa nada y hace que el sitio parezca mucho más concurrido de lo que realmente es, pero dudo en actuar por miedo a impedir que personas reales lean los textos o descarguen libros

    • ¿Thrillers tecnológicos, ciencia ficción y misterio? Luego quiero echarles un vistazo
  • Si hace falta bloquear, por lo general una lista de permitidos funciona mejor que una lista de bloqueados, y si no puedes aplicar una lista de permitidos, quizá este método tampoco sea una buena solución
    Herramientas como Cloudflare y Anubis pueden causar problemas graves de accesibilidad, así que prefiero limitar la frecuencia de solicitudes. Es más limpio sin dañar la accesibilidad, y para problemas temporales también funcionan bien los bloqueos cortos por IP
    En lo personal, analizo los logs HTTP con fail2ban y bloqueo por N horas las IP que piden URL prohibidas en robots.txt, rutas como wp-login.php, o que sobrepasan con demasiada frecuencia el límite de solicitudes. Ahora mismo estoy probando Anubis en la interfaz web de Git

    • En comunicación entre empresas implementé la lista de permitidos con una VPN entre redes. Fuera de la VPN no se puede acceder al servidor, y los empleados pueden entrar mediante la VPN corporativa
  • Solo con fail2ban se puede frenar bastante bien, pero durante los primeros meses hay que ajustarlo con mucho detalle al entorno
    Primero detecté con el filtro failregex = ^ - \\S+ \\[\\] ".*?" 40[034] y luego fui agregando a listas más específicas; ahora llevo unas 80 expresiones regulares y desde hace mucho no aparece ninguna solicitud que llegue siquiera al filtro general 40[034]
    Eso sí, detrás de un balanceador de carga o un proxy hace falta algún método para obtener la IP real, así que tanto fail2ban como el método del texto original se vuelven engorrosos

    • La mayoría de los balanceadores de carga de capa 7 ofrecen una función para agregar headers con la IP real. Solo hay que configurar el servidor web para que registre ese header, y es muy parecido a cómo un CDN transmite la IP real
  • Por estos comentarios y por mis intentos de acceso, parece que está bloqueando todo el tráfico normal, no solo bots

    • Si solo lees los comentarios puedes llevarte una impresión equivocada. Hasta ahora unas 2,600 personas y algunos bots sí han podido ver el texto
      Los domingos es cuando más se ven navegadores y apps raras que la gente usa para recorrer la web, y entre semana predominan los navegadores comunes y mayoritarios, así que sirve como buena prueba