Limite la ruta cara, no al crawler
Encuentre las URL que cuestan trabajo real a su sitio y limite allí a los crawlers con stick tables de HAProxy y un 429, sin dañar el posicionamiento ni a los visitantes.

Bloquear bots es fácil y normalmente un error. Los buscadores le traen visitantes, las previsualizaciones de enlaces le traen clics, e incluso los crawlers de IA agresivos suelen ser un tráfico que prefiere frenar antes que cerrar. El mejor enfoque es encontrar dónde le cuestan dinero los crawlers realmente, que es un puñado de rutas sin caché y pesadas en base de datos, y controlar la tasa allí, en el balanceador. Así lo hacemos nosotros.
Averigüe qué es caro antes de escribir una regla
El coste vive en las rutas que fallan la caché y llegan a PHP y a la base de datos: sitemaps generados al vuelo, la búsqueda, la navegación por facetas donde cada combinación de filtros es una consulta nueva, y cualquier cosa con una query string que la caché no conoce.
Su log de acceso ya le dice cuáles son. Si el log registra el tiempo de la petición ($request_time de nginx, por ejemplo, como último campo), sume el tiempo gastado por ruta:
awk '{split($7, p, "?"); t[p[1]] += $NF; n[p[1]]++}
END {for (u in t) printf "%10.1f s %8d req %s\n", t[u], n[u], u}' access.log \
| sort -rn | head -20
Después mire quién lo está gastando, por user agent, en esas rutas:
awk -F'"' '$2 ~ /sitemap|search|filter=/ {print $6}' access.log \
| sort | uniq -c | sort -rn | head -20
Dos listas, el trabajo de una tarde, y sabe exactamente dónde una regla dará resultado.
Limite la tasa con stick tables de HAProxy
HAProxy puede contar tasas de peticiones por cliente y por user agent en memoria, a velocidad de línea, y actuar sobre ellas. Una configuración mínima que protege solo las rutas caras:
backend st_src
stick-table type ipv6 size 200k expire 10m store http_req_rate(10s)
backend st_ua
stick-table type string len 128 size 20k expire 10m store http_req_rate(10s)
frontend fe_web
# bind lines and certificates as usual
acl expensive path_beg /sitemap /search
acl expensive url_sub -i filter=
http-request track-sc0 src table st_src if expensive
http-request track-sc1 req.fhdr(user-agent) table st_ua if expensive
http-request deny deny_status 429 hdr Retry-After 60 if expensive { sc_http_req_rate(0) gt 20 }
http-request deny deny_status 429 hdr Retry-After 60 if expensive { sc_http_req_rate(1) gt 60 }
Aquí importan tres decisiones de diseño. Solo se rastrean las rutas caras, así que nada más del sitio se ve afectado. La respuesta es un 429 con una cabecera Retry-After, que los crawlers bien educados entienden como «frene y vuelva más tarde», no como un error por el que castigarle. Y la segunda tabla cuenta por user agent, lo que atrapa a un crawler repartido en muchas direcciones que se colaría por debajo de un límite por dirección. Los umbrales de arriba son valores de ejemplo: fije los suyos a partir de lo que la ruta puede servir realmente sin caché.
Identifique a los crawlers con cuidado
Compare los user agents de forma laxa
Los crawlers cambian el formato de sus cadenas de user agent, añadiendo tokens de versión, URL o nuevos nombres de producto. Una regla que compara la cadena completa de forma exacta deja de funcionar el día que cambia. La comparación por subcadena sobre la parte estable (hdr_sub(user-agent) -i <name>) sigue funcionando.
No bloquee al buscador por accidente
Verifique un crawler antes de tratarlo de forma especial. Los grandes buscadores publican cómo: una consulta DNS inversa sobre la dirección del cliente debería devolver un nombre de host en su dominio, y una consulta directa sobre ese nombre debería devolver la misma dirección.
host <client-address> # should return a name in the engine's published domain
host <name-returned-above> # should return the same client address
Los crawlers genuinos quedan entonces limitados en las rutas caras como todos los demás, y siguen rastreando el resto del sitio libremente. Los impostores no reciben favores.
Rechace las formas que nunca son legítimas
Algunos patrones de petición no tienen ningún uso legítimo: URL recodificadas una y otra vez hasta medir miles de caracteres, combinaciones imposibles de parámetros, la misma codificación porcentual aplicada tres veces. Una sola regla en el edge las rechaza antes de que cuesten nada:
http-request deny deny_status 400 if { url_sub -i %2525 }
Ajuste el patrón a lo que muestren sus logs. La cuestión es que el balanceador es el lugar más barato de toda la pila para decir que no.
Proteja PHP de lo que se cuele
Ninguna regla en el edge es perfecta, así que la capa de aplicación necesita sus propios límites. En cada pool de PHP-FPM, un tiempo límite de terminación evita que una petición patológica retenga un worker durante minutos, y un techo de memoria evita que crezca sin límite:
request_terminate_timeout = 60s
php_admin_value[memory_limit] = 256M
pm.max_requests = 500
Fíjelos junto con las reglas del edge, para que las dos capas estén de acuerdo en qué aspecto tiene una petición razonable. Mientras tanto Varnish sigue sirviendo páginas en caché, así que lectores y compradores nunca notan nada de esto.
Cómo lo operamos nosotros
En las propiedades de noticias y comercio electrónico que operamos, las rutas de sitemap, búsqueda y listados filtrados reciben guardias de tasa desde el primer día, dimensionadas a lo que cada sitio puede servir sin caché. Las reglas nuevas se escriben a partir de los logs de acceso, se despliegan en cada edge de la propiedad, y se registran con cifras de antes y después para el cliente. Cuando aparece un crawler nuevo, una regla dirigida suele poder estar en su sitio en todos los edges a los pocos minutos de identificar el patrón.
Compruebe su propio edge
- ¿Qué cinco rutas costaron más tiempo de PHP y de base de datos la semana pasada?
- ¿Quién las solicitó, por user agent?
- ¿Se aplican sus límites solo donde está el coste, o a todo el sitio?
- ¿Responde con 429 y Retry-After, o con un bloqueo?
- ¿Cuándo confirmó alguien por última vez que las reglas siguen correspondiéndose con el tráfico real?
Si los crawlers se están comiendo su capacidad, podemos leer sus logs con usted y escribir las reglas.
Related
- /what-we-do/operations/edge-traffic-control/
- /what-we-do/data-web/high-availability-web-tiers/
- /what-we-do/data-web/performance-audits/
Publicado el 12 de octubre de 2026.
Todas las notas de campo