Usar un arsenal de pequeñas herramientas para bloquear bots
(lambdacreate.com)- Gitea y el blog de un servidor personal quedaron abrumados por tráfico de scraping, con alertas continuas de disco, CPU y memoria, y el operador salió a defenderlos combinando análisis de logs, Nginx y Fail2Ban
- Según Zabbix, el tráfico subió muy por encima de lo normal; el promedio mensual de Nginx fue de 8 solicitudes por segundo, y en el peor tramo llegó a más de 20 solicitudes por segundo
- La causa no fue un pico único de tráfico desde Reddit o Hacker News, sino algo más cercano a scraping distribuido, con varios bloques de IP rastreando URLs de
www.lambdacreate.comykrei.lambdacreate.com - Nginx devolvió 403 a user agents maliciosos conocidos y aplicó límites de solicitudes por IP; los clientes que generaban demasiados 403 fueron bloqueados con Fail2Ban durante 24 horas
- Al momento de escribir, la lista de bloqueos había crecido hasta un total de 735 bans, y en particular las solicitudes que intentaban generar tarballs para todos los commits de los repositorios públicos de Gitea aumentaban la carga del servidor
Tráfico de scraping que presionó a un servidor personal
- Tráfico de bots no deseado llegó de golpe a un espacio personal en internet, afectando incluso servicios a los que deberían acceder lectores reales
- Servicios como Archive.org, que indexan sitios con fines de preservación, entran en la lista de permitidos, pero Amazon, Facebook, OpenAI y varios bots aleatorios se distinguen como actores que consumen contenido para sus propios fines
- Se considera que la recolección masiva de datos de internet por parte de grandes empresas y la demanda de datos para entrenar modelos de IA incrementaron aún más la presión del scraping
- Este tráfico se trata no como consumidores reales de Lambdacreate, sino como un obstáculo que reduce la accesibilidad para lectores humanos
Zabbix detectó primero las señales anómalas
- El primero en alertar del problema fue Zabbix, con una advertencia de que el disco para contenedores se había llenado
- En un entorno basado en LXD, se amplió un sparse file de ZFS y el sitio se bajó por un momento y luego se volvió a levantar, pero la causa raíz seguía ahí
- Después, la instancia de Gitea empezó a consumir todo el disco a diario, generando 20 a 30 GB de datos por día
- Al principio se interpretó como un problema de que Gitea no habilita por defecto la limpieza de archivos de repositorios, y se configuró una tarea de limpieza agresiva
- Pronto siguieron alertas de CPU y memoria, se volvió difícil hacer
git pullygit pushen Gitea, y el cliente weechat tampoco podía mantener la conexión
Un volumen de solicitudes unas 10 veces mayor que lo normal
- Gracias a contar con monitoreo out-of-band para comparar métricas históricas con el estado actual, se pudo confirmar el patrón anómalo
- En el panel de Zabbix, las métricas clave eran el número de solicitudes de Nginx y el gráfico de throughput de red
- El promedio mensual de solicitudes a Nginx era de unas 8 solicitudes por segundo
- En el peor momento llegaron más de 20 solicitudes por segundo; aunque para un servicio grande sería poco, para un servidor personal era alrededor de 10 veces lo habitual, por lo que el impacto fue fuerte
- Más que el simple volumen de solicitudes, el aumento simultáneo del uso de disco y CPU relacionado con Gitea incrementó la carga operativa del servidor
Rastrear logs con lnav y goaccess
- Para mantener el servidor vivo el tiempo suficiente como para revisar los logs, se apagaron brevemente los contenedores y Nginx y se inició el análisis
- Las herramientas usadas fueron lnav y goaccess
lnavmuestra archivos de log en una TUI coloreada y ofrece una capa de abstracción sobre formatos de log comunes, permitiendo consultar logs con queries SQL- En
access.log, la revisión se centró en estas preguntas- Cuántas IP de visitantes había en total
- Si había patrones en las direcciones IP
- Si el tráfico venía de algún referrer específico
- Qué user agents se estaban usando
- Qué IP se asociaba con qué user agent
- El análisis mostró que no era un “hug of death” proveniente de un único referrer, sino que varios bloques de IP estaban raspando URLs de todo el sitio
403 basados en user agent y límites de solicitudes
- La primera respuesta fue listar en Nginx los user agents problemáticos y devolverles 403
- La configuración de ejemplo usa
map $http_user_agent $badagentpara marcar agents comoAdsBot-Google,AmazonbotyAmazonbot/0.1 - En la configuración base de Nginx se incluyen las reglas de user agent y también se establece rate limiting por IP
- La configuración del virtual host incluye estos comportamientos
- Aplicar límites de solicitudes con
limit_req zone=krei burst=20 nodelay; - Si
$badagentes verdadero, bloquear el acceso al contenido conreturn 403;
- Aplicar límites de solicitudes con
- Este enfoque ayuda a reducir el procesamiento del backend, pero como el servidor todavía tiene que recibir la solicitud HTTP y procesar el 403, sigue quedando carga cuando hay muchas solicitudes simultáneas
Automatizar bloqueos de firewall con Fail2Ban
- Una vez acumulados los logs 403, se pueden revisar con
lnavlas IP únicas que recibieron 403 goaccessse usa para analizar logs antiguos y actuales en conjunto y comprobar cuántas solicitudes entraron al servidor y cuáles fueron los endpoints más atacados- Para proteger realmente el servidor, se agregó Fail2Ban
- La regla de Fail2Ban es una forma simple de detectar, en el access log de Nginx, IP que generan demasiadas respuestas 403
- El tiempo de bloqueo se configuró en 86400 segundos, es decir, 24 horas
- Al momento de escribir, el resultado de
fail2ban-client status nginx-forbiddenera el siguiente- Fallos actuales: 13
- Fallos totales: 57135
- Bloqueos actuales: 38
- Bloqueos totales: 735
El objetivo real no era el blog, sino la generación de tarballs en Gitea
- Finalmente, los lectores pudieron volver a acceder al blog y a otros servicios de Lambdacreate
- Cuando hay que bloquear tráfico de robots, se vuelve difícil incluso escribir una entrada de blog
- El tráfico problemático no estaba raspando el blog, sino apuntando a la generación de tarballs de todos los commits de cada repositorio público de la instancia de Gitea
- A largo plazo, se planea considerar ampliar la lista de bloqueos o crear excepciones para servicios legítimos como Archive.org
- La postura es que no se quiere que el contenido desaparezca de los motores de búsqueda, pero tampoco dejarlo como combustible para el deterioro de internet causado por la IA
1 comentarios
Opiniones en Hacker News
Parece que muchos crawlers menos escrupulosos imitan a los crawlers grandes. Da la impresión de que mucha gente asume que el
User-Agentes auténtico.Mi método favorito es poner información señuelo en
robots.txt, hacer que esa URL entregue una bomba gzip y luego bloquear automáticamente las solicitudes posteriores.Fue fácil de configurar en Caddy y atrapa bien a los peores crawlers.
No estoy defendiendo el comportamiento de los bots, pero si algunos bots pueden tumbar un sitio solo con solicitudes a ciegas, un atacante malicioso podría divertirse mucho más destruyéndolo.
Quizá sea porque soy de otra generación que quienes escriben este tipo de posts de blog, pero no entiendo muy bien esta obsesión con un uso tan bajo de recursos.
Me recuerda a cuando los abuelos hacen un escándalo porque no apagaste una luz LED, o a manejar 15 millas para ahorrar 5 centavos por galón.
20 solicitudes por segundo no son absolutamente nada.
Incluso si todo se genera dinámicamente, para empezar no sé por qué lo harían así, y habría sido mucho mejor dedicar tiempo a arreglar el caché.
Entiendo que, con el ambiente actual, los posts del tipo “fuera bots” son populares, pero esto tampoco es muy novedoso.
Hay muchas formas productivas de manejarlo desperdiciando mucho menos tiempo.
robots.txt. Tengo entendido que la mayoría de las IA ignoran por completo lo relacionado conrobots.txt, así que en la práctica me parece que solo caen los bots que sí intentan respetarlo.No me opongo como otros aquí; me interesa saber cómo implementarlo sin perjudicar a los actores legítimos.
Están convencidos de que podría implicar una responsabilidad legal peligrosa y que no vale la pena intentarlo. Realmente me pregunto si alguien usa esto en sitios web públicos reales.
Es molesto que los bots ya no respeten en absoluto los archivos
robots.txt. La gente que crea estas cosas son villanos totales. Si eres uno de ellos, ojalá te vayas al diablo por tu cuenta.robots.txten vez de simplemente ignorarlo.El problema de espacio en disco me parece un bug de Gitea. Cuando alguien descarga un zip, debería poder streamearlo al cliente, pero en realidad crea el zip en un espacio temporal, se lo entrega al cliente y luego no lo borra.
Lo resolví marcando ese directorio como de solo lectura. Obviamente, las descargas zip ya no funcionan. Si alguien realmente las necesita, puede hacer checkout del repositorio y crearlo por su cuenta.
Si de verdad me hubiera importado, habría corregido el bug, buscado cómo desactivar bien la función o la habría habilitado solo para usuarios con sesión iniciada.
Además, redirijo ciertos
User-Agentdel lado del servidor a https://git.immibis.com/gptblock.html.Ahora ya no es por el desperdicio de recursos, sino simplemente porque no me caen bien. Lo que hacen de todos modos no tiene valor, y lo hago porque puedo.
Si de verdad necesitan los datos de un repositorio Git, que clonen el repositorio Git en vez de scrapearlo de forma tonta. Eso siempre estuvo permitido.
8 solicitudes por segundo no es tanto, siempre que cada solicitud no provoque procesamiento pesado, y de hecho, salvo por el bug de espacio en disco, no cargaba demasiado a un VPS pequeño.
No lo bloqueé por ser un DoS, sino por ser estúpido.
Entiendo que el autor “ya no le dé importancia”, pero vi Google, ripe.net y semrush entre las IP bloqueadas.
Si quiere que otras personas lo vean y hablen de ello, definitivamente no bloquearía a Google, y probablemente tampoco a los demás.
Aunque el contenido sea scrapeado por el bot de IA de alguien, no entiendo por qué operarías un sitio público sin esperar que el sitio se use.
Apagar el letrero luminoso de un motel mientras esperas que la gente llegue no es una buena forma de invitar.
robots.txt, y al final logré que alguien del área legal le pusiera atención.Permitir que una empresa de “SEO” pisotee torpemente el sitio y desplace a visitantes reales no aporta ningún valor para mí ni para usuarios potenciales.
Algunos competidores de Semrush eran igual de malos.
El caos actual de la IA también es muy deficiente. Al menos en un caso conocido, no solo hicieron falta medidas técnicas, sino también notas legales a relaciones con inversionistas y al departamento de relaciones públicas para que se restableciera cierto orden.
Google también opera scrapers de IA, así que eso pudo haber sido lo que viste.
Especialmente cuando pasan cosas como esta.
Google is using AI to censor independent websites like mine
https://news.ycombinator.com/item?id=44124820
Suena como si ya hubiéramos llegado al punto en que Google se volvió una carga mayor.
Por culpa de estos bots, los logs crecían demasiado rápido, así que desactivé el logging del servidor. Son realmente persistentes, llenan todos los formularios e incluso llaman APIs a las que solo se puede acceder mediante clics en el sitio.
Anthropic, OpenAI y Facebook siguen scrapeando hasta ahora.
Para confirmar: ¿quieres decir que son parte de la UI y que solo una persona debería presionarlas, y que no hay otra forma de acceder a esa API?
Ahora que existen agentes de IA, si imitan patrones de comportamiento humano, prácticamente casi no hay forma de distinguir entre usuarios reales y bots.
Es bueno que los bots rastreadores de IA completen honestamente el encabezado
User-Agent. Pero sorprende que fueran la causa de tanto tráficoEl 99% de todos los sitios web no cambia con la frecuencia suficiente como para necesitar ese nivel de tráfico, y mucho menos un blog de desarrollo
robots.txtAunque también vi reportes de que, después de ser bloqueados de alguna manera, empezaron a rastrear desde IP residenciales con un
User-Agentde navegadorPero también es posible que desde el principio alguien haya falsificado su rastreador haciéndolo pasar por OpenAI/Amazon/Facebook, etc.
Soy quien creó tirreno [1]
Nuestra plataforma está diseñada principalmente para usuarios con sesión iniciada en tiempo real, pero también funciona bien para detectar y bloquear bots
Anonimiza el último octeto de la dirección IP reemplazándolo por un asterisco y agrupa subredes prácticamente iguales bajo una misma cuenta
Luego, con el motor de reglas integrado, se pueden crear listas de bloqueo automáticamente según condiciones como demasiados errores 500/404, intentos de inicio de sesión por fuerza bruta o tráfico desde IP de centros de datos
Por último, se puede integrar la API de lista de bloqueo de tirreno en la lógica de la aplicación para redirigir el tráfico no deseado a una página de error
Como extra, también se ofrece un dashboard [2] para monitorear la actividad y ajustar finamente las listas para no bloquear usuarios legítimos
[1] https://github.com/tirrenotechnologies/tirreno
[2] https://play.tirreno.com/login (admin/tirreno)
Aunque encuentren algo que no haya sido bloqueado de antemano o logren pasar haciendo clic en 87 casillas de semáforos, quedan agrupados con vecinos de dirección totalmente ajenos
Parece una forma de tranquilizar la conciencia diciendo que no se está creando un sistema de vigilancia de usuarios procesando datos personales sin consentimiento
Espero que al menos cuenten con un proceso de feedback suficiente para que sus clientes puedan ver que están perdiendo clientes reales que sí gastan dinero
Mis sitios reciben entre 10 mil y 20 mil solicitudes al día. La mayoría son scrapers de IA
Algo que noté es que muchos bots buscan páginas PHP específicas. Si no usas PHP, puedes bloquear automáticamente las IP que soliciten páginas PHP. Si usas PHP, basta con bloquear las IP que pidan páginas que en realidad no existen
Algunos de nosotros estamos dispuestos a permitir el entrenamiento de IA, pero queremos evitar la sobrecarga. Por ejemplo, me alegra que se rastreen páginas sobre el evangelio y teología bíblica
Para contenido grande que no quieres que sea rastreado, puede ayudar ponerlo en un directorio específico. Luego, si detectas un bot, bloqueas el acceso de esa IP a ese directorio
En mi caso, también tengo una estrategia básica para manejar muchas solicitudes: solo texto, presentación HTML/CSS, otros elementos alojados externamente y Perma-Cache de BunnyCDN (USD 10/mes + 1 centavo por GB)
Las solicitudes de BunnyCDN van a una VM de Digital Ocean de USD 5 al mes. Al principio ni siquiera noté los scrapers de IA, porque no afectaban el rendimiento y, durante un mes, mi saldo apenas cambió de USD 30 a USD 29.99
Me preguntaba si existiría algo como “page knocking”: abrir varias páginas en un orden específico para obtener acceso
Por ejemplo, se podría hacer que todo devuelva 404 si no empiezas por una URL privada específica
GET, convertir el resto del sitio en disparates sintácticamente válidosComo mi servidor pequeño simplemente estaba funcionando en silencio, hace poco no había revisado el estado de
fail2bansudo fail2ban-client status | sed -n '/Jail list:/{s/^.*://; s/,//g; p}' | xargs -n1 sudo fail2ban-client status | awk '/jail:/{i=$5}; /Total failed:/{jail[i]=$5}; END{for(i in jail) printf("%s: %s\n", i, jail[i])}' | column -tsshd-ddos: 0postfix: 583dovecot: 9690postfix-sasl: 4227nginx-botsearch: 1421nginx-http-auth: 0postfix-botnet: 5425sshd: 202157Vaya, 220 mil IP bloqueadas
DotBot/1.2que, al día de hoy, envió más de 220 mil solicitudes en las últimas dos semanasSolicita nombres de archivo y carpetas al azar en el servidor web
Tengo curiosidad por saber hasta qué profundidad llega y si tiene algún límite, así que por ahora lo estoy observando sin bloquearlo