Cloudflare WAF y protección DDoS a fondo: reglas, rate limiting y bots

Cómo protege Cloudflare tu web: DDoS sin límite en todos los planes, WAF con reglas gestionadas y personalizadas, rate limiting, Bot Fight Mode y Under Attack. Qué incluye cada plan y un limitador por cliente con el binding de Workers probado en local.

Portada: Cloudflare WAF y protección DDoS a fondo

Cuando pones un dominio detrás de Cloudflare con la nube naranja activada, cada petición pasa por su red antes de llegar a tu servidor. Ese paso intermedio es lo que permite cachear, pero también filtrar: absorber ataques de denegación de servicio, bloquear intentos de inyección SQL, frenar a quien hace mil peticiones por minuto o desafiar a los bots.

En este artículo repasamos las capas de seguridad que hay delante de tu aplicación: la protección DDoS, el WAF con sus reglas gestionadas y personalizadas, el rate limiting (en el WAF y como binding de Workers), y las herramientas contra bots. Con lo que incluye cada plan, que es donde más confusión hay, y un limitador por cliente hecho con el binding de Workers.

🧪
Lo único ejecutable de este artículo, el limitador con el binding ratelimits, se ha probado de verdad el 3 de octubre de 2026 con Wrangler 4.147.0 y Node.js 24.21.0 en local. Las reglas del WAF, la protección DDoS, Bot Fight Mode y Under Attack no los he probado: necesitan una zona activa en Cloudflare. Las expresiones de ejemplo usan campos y funciones que he comprobado en la referencia oficial del lenguaje de reglas, pero no se han ejecutado. Planes y límites revisados en la documentación oficial ese mismo día.

Cómo funciona: capas delante de tu origen

Todo esto solo aplica al tráfico proxied (nube naranja). Si un registro DNS está en modo «solo DNS», las peticiones van directas a tu servidor y Cloudflare no ve nada. De fuera hacia dentro, una petición se encuentra con:

  1. Protección DDoS de red (capas 3/4) y HTTP (capa 7), automática.
  2. El WAF: reglas personalizadas, reglas de rate limiting y reglas gestionadas, evaluadas por fases.
  3. La protección contra bots, si la tienes activada.
  4. La caché y tu Worker, si los hay, y por último tu origen.
Esquema de seguridad de Cloudflare: el tráfico pasa por la mitigación DDoS automática, después por el WAF con reglas personalizadas, rate limiting y reglas gestionadas, por la protección de bots y finalmente llega a la caché, al Worker y al origen
Cada capa puede bloquear, desafiar o dejar pasar. Lo que llega al origen ya ha pasado todos los filtros. Diagrama: devutilites.

Protección DDoS

Es la parte que no tienes que configurar. Cloudflare detecta y mitiga ataques DDoS de forma autónoma, y la protección es estándar y sin medición (unmetered) en todos los planes, incluido el gratuito: no pagas más por el tamaño del ataque. Cubre ataques de red (capas 3 y 4, como inundaciones SYN o UDP) y de aplicación (inundaciones HTTP).

Las reglas de mitigación se exponen como rulesets gestionados de DDoS. Puedes ajustar su sensibilidad o su acción si te dan falsos positivos; en todos los planes no Enterprise se permite una modificación (override). La protección adaptativa, que aprende el perfil normal de tu tráfico, está limitada a las reglas basadas en tasas de error salvo en Enterprise con el complemento avanzado.

Y si te están atacando de verdad, existe el modo Under Attack: muestra una página intermedia a todos los visitantes y solo deja pasar a los validados. La propia documentación lo describe como un último recurso, porque interrumpe temporalmente el acceso normal y afecta a tus analíticas. Puedes activarlo para toda la zona o solo para algunas rutas con una regla de configuración.

El WAF

El WAF revisa cada petición contra conjuntos de reglas (rulesets) escritos en el lenguaje de reglas de Cloudflare, el mismo que usan las reglas de caché o de redirección. Tiene tres tipos de reglas:

Reglas gestionadas

Las escribe y actualiza el equipo de seguridad de Cloudflare. Protegen contra vulnerabilidades conocidas y de día cero sin que hagas nada.

RulesetFreeProBusinessEnterprise
Free Managed RulesetSíSíSíSí
Cloudflare Managed RulesetNoSíSíSí
Cloudflare OWASP Core RulesetNoSíSíSí

El Free Managed Ruleset cubre las vulnerabilidades más explotadas y de mayor impacto. Si tienes el Managed Ruleset completo, no lo necesitas, porque está incluido. El OWASP Core Ruleset usa puntuaciones: cada regla que coincide suma, y se actúa al pasar un umbral.

Reglas personalizadas

Tus propias reglas: una expresión y una acción. Las acciones más usadas son Block, Managed Challenge (Cloudflare elige el tipo de desafío según la petición), Non-Interactive Challenge, Interactive Challenge y Skip (saltarse otras protecciones para ciertas peticiones). Se evalúan en orden y las acciones terminales, como Block, detienen la evaluación.

Algunos ejemplos de expresiones (sin probar, como decía arriba):

# Proteger el panel de administración salvo desde tu país
(starts_with(http.request.uri.path, "/wp-admin") and ip.src.country ne "ES")

# Bloquear métodos que tu API no usa
(starts_with(http.request.uri.path, "/api/") and http.request.method in {"PUT" "DELETE"})

# Desafiar a quien no sea un bot verificado (Google, Bing…) en el buscador interno
(http.request.uri.path eq "/buscar" and not cf.client.bot)
Reglas personalizadasFreeProBusinessEnterprise
Número de reglas5201001000
Expresiones regulares (matches)NoNoSíSí
AccionesTodas menos LogTodas menos LogTodas menos LogTodas

Reglas de rate limiting

Cuentan peticiones que cumplen una expresión y, al pasar del umbral, aplican una acción durante un tiempo de mitigación. En el plan Free son muy básicas:

Rate limiting (WAF)FreeProBusinessEnterprise
Número de reglas125100
Campos en la expresiónPath y Verified Bot+ Host, URI, Query+ Method, IP, User AgentTodos los de la petición
Se cuenta porIPIPIP o IP con NATIP, cabeceras, cookies, país, JA3/JA4… (con Advanced Rate Limiting)
Periodo de conteo10 sHasta 1 minHasta 10 minHasta 65 535 s
Tiempo de mitigación10 sHasta 1 hHasta 1 díaHasta 1 día

Con una regla de 10 segundos por IP en Free puedes proteger un login contra fuerza bruta sencilla, pero no implementar «100 peticiones por hora por cliente de la API». Para eso está el binding de Workers.

Rate limiting desde tu Worker

El binding ratelimits usa la misma infraestructura que las reglas del WAF, pero el límite lo aplicas tú en el código, con la clave que quieras: el id del usuario, su API key, la ruta, o una combinación. Necesita Wrangler 4.36.0 o posterior.

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "ratelimit-lab",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "ratelimits": [
    {
      "name": "LIMITE_GRATIS",
      "namespace_id": "1001",               // entero único en tu cuenta
      "simple": { "limit": 5, "period": 10 } // period: solo 10 o 60 segundos
    },
    {
      "name": "LIMITE_PRO",
      "namespace_id": "1002",
      "simple": { "limit": 100, "period": 60 }
    }
  ]
}

period solo admite 10 o 60 segundos, y namespace_id es un entero que tú eliges, único en tu cuenta. El Worker aplica un límite distinto según el plan del cliente y usa como clave «API key + ruta»:

// Claves de API de ejemplo; en la vida real vendrían de KV o D1
const CLIENTES: Record<string, { plan: "gratis" | "pro" }> = {
  "clave-ana": { plan: "gratis" },
  "clave-empresa": { plan: "pro" },
};

export default {
  async fetch(request, env): Promise<Response> {
    const apiKey = request.headers.get("Authorization")?.replace("Bearer ", "") ?? "";
    const cliente = CLIENTES[apiKey];
    if (!cliente) return Response.json({ error: "no autorizado" }, { status: 401 });

    const { pathname } = new URL(request.url);
    // Clave = quién + qué ruta. Mejor que la IP, que pueden compartir muchos usuarios.
    const limitador = cliente.plan === "pro" ? env.LIMITE_PRO : env.LIMITE_GRATIS;
    const { success } = await limitador.limit({ key: `${apiKey}:${pathname}` });

    if (!success) {
      return Response.json(
        { error: "demasiadas peticiones" },
        { status: 429, headers: { "Retry-After": "10" } },
      );
    }
    return Response.json({ ok: true, plan: cliente.plan, ruta: pathname });
  },
} satisfies ExportedHandler<Env>;

La documentación desaconseja usar la IP como clave: una oficina, una universidad o una red móvil comparten IP entre muchos usuarios legítimos.

Prueba en local

El simulador de Wrangler aplica el límite de verdad:

$ for i in $(seq 1 7); do curl -s -o /dev/null -w "%{http_code} " -H "Authorization: Bearer clave-ana" localhost:8806/api/datos; done
200 200 200 200 200 429 429 
# otra ruta, mismo cliente: contador independiente
$ curl -s -H "Authorization: Bearer clave-ana" localhost:8806/api/otra
{"ok":true,"plan":"gratis","ruta":"/api/otra"}
# plan pro, misma ruta
$ for i in $(seq 1 7); do curl -s -o /dev/null -w "%{http_code} " -H "Authorization: Bearer clave-empresa" localhost:8806/api/datos; done
200 200 200 200 200 200 200 
$ curl -si -H "Authorization: Bearer clave-ana" localhost:8806/api/datos | grep -iE "^HTTP|retry-after|^\{"
HTTP/1.1 429 Too Many Requests
Retry-After: 10
{"error":"demasiadas peticiones"}
$ sleep 11; curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer clave-ana" localhost:8806/api/datos
200

Cinco peticiones pasan y la sexta recibe 429. Otra ruta del mismo cliente tiene su propio contador, el cliente pro no llega a su límite y, pasados los 10 segundos, el cliente gratuito vuelve a entrar.

⚠️
El binding no sirve para contabilidad exacta. Los contadores son locales a cada ubicación de Cloudflare: un cliente que entra por Madrid y por París tiene dos contadores. Además se actualizan en segundo plano, así que es permisivo y eventualmente consistente: con muchas peticiones simultáneas pueden colarse algunas de más. Para cuotas de facturación usa un Durable Object o una base de datos.

Bots

  • Bot Fight Mode es gratuito: identifica tráfico que coincide con bots conocidos y les plantea desafíos que consumen CPU para encarecer sus peticiones. No se puede ajustar ni excluir con reglas personalizadas y puede desafiar tráfico de tu API o de tu app móvil, así que actívalo con cuidado si tu dominio sirve APIs.
  • Super Bot Fight Mode (Pro y Business) y Bot Management (Enterprise) dan más control y una puntuación de bot por petición.
  • Para formularios concretos, la herramienta adecuada es Turnstile.

Errores comunes (y cómo evitarlos)

  • Dejar registros en «solo DNS». Ni el WAF ni la protección DDoS ven ese tráfico. Revisa la nube naranja.
  • Exponer la IP de tu origen. Si alguien conoce la IP de tu servidor, puede atacarlo directamente saltándose Cloudflare. Que el origen acepte solo tráfico de Cloudflare, o mejor, usa Cloudflare Tunnel y no abras puertos.
  • Bloquear sin probar. Empieza con Managed Challenge en vez de Block y revisa Security Events antes de endurecer.
  • Activar Bot Fight Mode con una API pública. Tus clientes legítimos que no son navegadores recibirán desafíos que no pueden resolver.
  • Usar la IP como clave de rate limiting. Castigas a todos los que comparten esa IP.
  • Fiarse del binding como cuota exacta. Es por ubicación y permisivo.
  • Dejar Under Attack activado. Es para emergencias; molesta a todos tus visitantes.

Cuándo usar cada cosa

Siempre: la protección DDoS (no hay que hacer nada) y el Free Managed Ruleset en cualquier sitio proxied. Reglas personalizadas para cerrar rutas sensibles, países o métodos. Rate limiting del WAF para limitar por IP sin código, y el binding de Workers cuando el límite depende de quién es el usuario o su plan. Turnstile para formularios. Under Attack solo durante un ataque.

Si necesitas expresiones regulares, más reglas o rate limiting por algo que no sea la IP sin escribir código, ahí empiezan los planes de pago.

Sigue leyendo