Cómo Proteger un Servidor Web de Ataques: WAF, fail2ban y Rate Limit

El 94% de los inicios de sesión en la red de Cloudflare son bots. Descubre cómo WAF, rate limit y fail2ban detienen los ataques antes de que tumben tu sitio.

por Cleverson Gouvêa

Cómo Proteger un Servidor Web de Ataques: WAF, fail2ban y Rate Limit

Proteger un servidor web contra ataques ya no es tarea exclusiva de grandes empresas: en 2026, quien tiene un sitio web, una tienda o un sistema funcionando en su propia VPS es objetivo cada día, de forma automática. En esta guía te mostramos las tres capas que utilizamos en Agathas Web — WAF, fail2ban y rate limit —, qué detiene cada una, cuánto cuesta y cuándo estorba más de lo que ayuda.

TL;DR

  • El 94% de los intentos de inicio de sesión que pasan por la red de Cloudflare provienen de bots, según el informe de amenazas 2026 de la empresa. Tu formulario de inicio de sesión está siendo probado ahora mismo.
  • WAF detiene peticiones maliciosas antes de llegar al servidor; rate limit limita el volumen por IP o ruta; fail2ban lee logs y banea a quien insiste. Una capa no sustituye a la otra.
  • El plan Free de Cloudflare ya ofrece WAF gestionado básico, 5 reglas personalizadas y 1 regla de rate limit — suficiente para empezar, insuficiente para un sistema crítico.
  • La trampa nº 1: fail2ban detrás de proxy/CDN sin configurar la IP real banea a la propia Cloudflare y tumba el sitio.
  • Sin alguien que lea los logs y ajuste las reglas, toda protección envejece. Ahí es donde entra el servicio de alojamiento gestionado.

Por qué proteger un servidor web contra ataques se ha convertido en rutina, no en excepción

Hasta hace unos años, la conversación sobre ataques era "¿y si un hacker elige mi empresa?". Hoy nadie elige a nadie. Los robots rastrean rangos enteros de IP, prueban contraseñas filtradas en cualquier pantalla de inicio de sesión que encuentran y lanzan avalanchas de peticiones contra quien responde.

Las cifras recientes lo dejan claro:

  • El informe DDoS del primer semestre de 2026 de Cloudflare contabilizó 29,64 billones de peticiones HTTP de DDoS mitigadas en el semestre y 23,2 millones de ataques de capa de red — cerca de 5.343 por hora.
  • En el mismo informe, Brasil superó a Estados Unidos como principal país de origen de DDoS en el semestre (14,9% contra 13,4%). Gran parte de este tráfico sale de máquinas infectadas dentro del país.
  • El 90,6% de los ataques duran menos de 10 minutos. Cuando alguien se da cuenta y abre una incidencia, el daño ya está hecho.
  • El Verizon DBIR 2025 muestra que el 88% de las intrusiones por ataque básico a aplicación web involucraron credenciales robadas, y que la fuerza bruta en esta categoría saltó de cerca del 20% al 60% de los incidentes.
  • El Imperva Bad Bot Report 2025 estima que los bots maliciosos ya representan el 37% de todo el tráfico de internet, y el tráfico automatizado total superó al humano (51%).

En la práctica, proteger un servidor web contra ataques automatizados ha dejado de ser opcional: tu VPS de entrada recibe el mismo tipo de golpe que un gran portal — solo que sin nadie supervisando. En los servidores que administro, el log de acceso de un WordPress recién publicado muestra intentos en /wp-login.php y /xmlrpc.php en cuestión de horas, antes de que el sitio aparezca en Google.

Los tres tipos de ataque que tumban servidores de pequeñas empresas

Antes de elegir una herramienta para proteger un servidor web contra ataques de este tipo, conviene separar el problema. En nuestra experiencia con sitios web, sistemas y entornos Moodle, casi todo incidente de indisponibilidad encaja en uno de estos tres grupos.

Fuerza bruta y credential stuffing

La fuerza bruta consiste en probar contraseña tras contraseña hasta acertar. Credential stuffing es la versión refinada: el robot utiliza pares de correo electrónico y contraseña filtrados de otros servicios, apostando a que el usuario repitió la contraseña. El mismo informe de amenazas 2026 de Cloudflare señala que el 46% de los inicios de sesión humanos utilizan credenciales que ya han aparecido en filtraciones.

El riesgo no es solo la intrusión. Cada intento de inicio de sesión consume CPU: el PHP se ejecuta, consulta la base de datos, calcula el hash de la contraseña. Mil intentos por minuto en un wp-login.php bastan para ralentizar una VPS pequeña para los clientes reales.

Bots de scraping y escaneo

Son los robots que no quieren tu contraseña, sino tu contenido, tus precios o una vulnerabilidad conocida. Recorren URLs como /.env, /phpmyadmin, /wp-content/plugins/<plugin-vulnerável>/ y cualquier ruta que ya haya tenido un CVE publicado. Desde 2025 se suman a ellos los crawlers de IA, que pueden descargar miles de páginas en secuencia.

DDoS de aplicación (capa 7)

A diferencia del DDoS volumétrico, que intenta saturar el enlace, el DDoS de aplicación envía peticiones HTTP que parecen legítimas — búsqueda interna, página de informe, carrito — elegidas precisamente porque son costosas para el servidor. Pocas centenas de peticiones por segundo en la ruta correcta tumban un sistema que soportaría decenas de miles de accesos a una página en caché.

Las tres capas para proteger un servidor web contra ataques

Quien intenta proteger un servidor web contra ataques suele instalar una herramienta y detenerse ahí. La forma más útil de entender WAF, rate limit y fail2ban es por la posición de cada uno en el camino de la petición:

Capa Dónde se ejecuta Qué detiene mejor Punto débil
WAF (Web Application Firewall) En el borde (Cloudflare) o en el servidor (ModSecurity + OWASP CRS) SQL injection, XSS, explotación de CVE conocido, bots maliciosos identificados Falso positivo en formulario legítimo; no entiende la lógica de tu negocio
Rate limit En el borde y/o en Nginx/Apache y en la propia aplicación Fuerza bruta, inundación de ruta costosa, scraping agresivo Límite mal calibrado bloquea a usuario real (NAT de empresa, escuela, 4G)
fail2ban En el servidor, leyendo logs Quien insiste: SSH, inicio de sesión, escaneo repetido Reactivo — actúa después del log; inútil si la IP registrada es la del proxy

El punto central: para proteger un servidor web contra ataques de verdad, necesitas las tres, porque cada una cubre el hueco de la otra. El WAF no sabe que la IP X erró la contraseña 40 veces; fail2ban sí. fail2ban no ve el tráfico que el borde ya descartó; y el rate limit no reconoce una firma de SQL injection.

WAF: el filtro en la puerta de entrada

WAF es un firewall que entiende HTTP. En lugar de mirar solo el puerto y la IP, inspecciona la URL, las cabeceras y el cuerpo de la petición y los compara con reglas de ataque conocidas.

WAF en el borde: Cloudflare

Es el camino que utilizamos por defecto para proteger un servidor web contra ataques de aplicación. La petición pasa por Cloudflare antes de llegar a tu servidor, y lo que se bloquea allí no consume ni un ciclo de CPU de tu parte. Según la documentación oficial del WAF, el plan Free incluye el Free Managed Ruleset (reglas para vulnerabilidades de alto impacto, como Log4Shell y Shellshock) y 5 reglas personalizadas. El plan Pro cuesta 20 $/mes en el pago anual (25 $/mes en el mensual) y libera el conjunto gestionado completo.

Las reglas personalizadas que más rendimiento ofrecen, en nuestra experiencia:

  1. Desafío (managed challenge) en rutas administrativas — /wp-admin, /wp-login.php, /admin — para quien no viene de España, cuando el público es solo nacional.
  2. Bloqueo total de /xmlrpc.php en WordPress que no usa app móvil ni Jetpack.
  3. Bloqueo de rutas que no existen en tu sistema y solo aparecen en escaneos: /.env, /.git/, /phpmyadmin.

WAF en el servidor: ModSecurity y OWASP CRS

Cuando el tráfico no pasa por CDN, o el cliente necesita reglas dentro del propio servidor, la alternativa de código abierto es ModSecurity con el OWASP Core Rule Set (CRS). Dos hechos que cambiaron el escenario y que muchos tutoriales antiguos ignoran:

  • Trustwave finalizó el soporte a ModSecurity el 1 de julio de 2024 y transfirió la custodia del proyecto a la OWASP.
  • F5 descontinuó el NGINX ModSecurity WAF comercial el 31 de marzo de 2024.

El CRS sigue activo: la línea 4.25.x es LTS, con correcciones de seguridad previstas hasta el tercer trimestre de 2027, según el proyecto OWASP CRS. Funciona, pero exige un ajuste fino — un CRS con un nivel de paranoia alto, instalado sin período de observación, bloquea formularios de contacto, editores de posts y subidas de archivos el primer día.

Cuando NO usar WAF en modo bloqueo

No actives el bloqueo directo en sistemas con mucha entrada de texto libre (ERP, Moodle con foro y cuestionario, editores ricos) sin antes ejecutarlo algunos días en modo solo log. En Moodle, por ejemplo, preguntas con fragmentos de código o SQL en clases de programación disparan reglas de inyección con facilidad.

Rate limit: ¿cuánto es demasiado?

El rate limit es la pieza que más ayuda a proteger un servidor web contra ataques de volumen. Consiste en contar peticiones por cliente en un intervalo y cortar a quien supera el límite. Parece simple; lo difícil es elegir el número.

En el borde

Desde 2022, Cloudflare ofrece rate limiting en todos los planes, pero con límites muy diferentes. Según la documentación de rate limiting rules:

  • Free: 1 regla, ventana de conteo de hasta 10 segundos, bloqueo de hasta 10 segundos, conteo solo por IP y filtro solo por ruta.
  • Pro: 2 reglas, ventana de hasta 1 minuto, bloqueo de hasta 1 hora.
  • Business: 5 reglas, ventana de hasta 10 minutos, bloqueo de hasta 1 día, y conteo por IP con soporte a NAT.

Con una única regla en el plan Free, úsala en la ruta de inicio de sesión. Es donde el beneficio es mayor.

En el servidor web

En Nginx, el módulo limit_req realiza el trabajo con el algoritmo de cubo con fugas (leaky bucket): defines la tasa (por ejemplo, 5r/m para /wp-login.php) y una ráfaga tolerada con burst. En Apache, el equivalente suele ser mod_evasive o reglas del propio ModSecurity. Lo importante es limitar ruta por ruta: inicio de sesión y búsqueda con un límite bajo; archivos estáticos, ninguno.

En la aplicación

La capa más precisa es la propia aplicación, porque ella sabe quién es el usuario. En el panel administrativo de este sitio, implementamos un registro de intentos de inicio de sesión en la base de datos que bloquea por cuenta y por IP después de una secuencia de errores. Moodle tiene esto nativo: en Administración del sitio › Seguridad › Políticas del sitio, los parámetros de bloqueo de cuenta (límite de intentos, ventana y duración) vienen desactivados por defecto — y casi nadie los activa.

Trampa: el NAT de la escuela y la empresa

Una escuela entera, un call center o una operadora 4G pueden salir a internet por la misma IP. Ya hemos visto plataformas EAD (Educación a Distancia) bloquear el examen de una clase entera porque un rate limit de 60 peticiones por minuto por IP contaba a 40 alumnos como "un cliente". Calibra basándote en el log real de pico, no en números de tutorial.

fail2ban: quien insiste, fuera

El fail2ban lee archivos de log, busca patrones de fallo (contraseña errónea en SSH, 401 en el inicio de sesión, 404 en serie) y, al superar el límite, crea una regla de firewall baneando la IP por un tiempo.

Los valores por defecto (y por qué cambiarlos)

fail2ban es la capa más antigua para proteger un servidor web contra ataques persistentes, pero viene con valores conservadores. En el jail.conf oficial, el estándar es bantime = 10m, findtime = 10m y maxretry = 5: cinco fallos en diez minutos resultan en diez minutos de baneo. Para un robot, diez minutos es una pausa para el café. Lo que aplicamos:

  • bantime.increment = true — viene comentado por defecto; activado, cada reincidencia duplica el tiempo de baneo.
  • Jail recidive — ya viene en el paquete y banea por 1 semana a quien ha sido baneado varias veces en 1 día.
  • Jails específicas para la aplicación: nginx-limit-req (quien supera el rate limit de Nginx), filtros para el inicio de sesión de WordPress y del panel del sistema.
  • SSH sin contraseña, solo con clave — así fail2ban en SSH se convierte en segunda línea, no en primera.

La trampa que tumba el sitio: fail2ban detrás de Cloudflare

Intentar proteger un servidor web contra ataques con fail2ban detrás de un CDN sin ajuste es el error que más encontramos en servidores que recibimos para mantener. Con Cloudflare delante, la IP que llega a Nginx es la de Cloudflare, no la del visitante. fail2ban lee el log, ve "la misma IP" errando la contraseña y banea… a Cloudflare. Resultado: el sitio deja de estar disponible para una parte de los visitantes, sin error aparente.

Para evitarlo:

  1. Configura el módulo real_ip de Nginx (o mod_remoteip en Apache) para confiar solo en los rangos de IP publicados por Cloudflare y leer la cabecera CF-Connecting-IP. No uses X-Forwarded-For sin procesar — puede ser falsificado.
  2. Incluso con la IP real en el log, banear vía iptables en el servidor no bloquea nada: la conexión sigue viniendo de Cloudflare. Utiliza la acción de Cloudflare de fail2ban (que crea la regla vía API en el borde) o cierra el origen para aceptar solo a Cloudflare.

Lo que no resuelve (y cuesta caro)

Algunas medidas para proteger un servidor web contra ataques aparecen en todo checklist y ofrecen poco:

  • Plugin de seguridad como única capa. En WordPress, el plugin se ejecuta dentro de PHP: cuando bloquea, el servidor ya ha gastado el procesamiento. Ayuda, pero no soporta una inundación.
  • Cambiar el puerto SSH y detenerse ahí. Reduce el ruido en el log, no protege nada contra quien realiza un escaneo completo.
  • Bloquear países enteros en el firewall del servidor. Las listas de IP por país cambian; mal mantenidas, bloquean a clientes reales y no detienen a la botnet brasileña — que, como vimos, lidera el ranking.
  • Comprar un servidor más grande para soportar el ataque. Escalar verticalmente para absorber bots es pagar para ser atacado. Filtrar en el borde es más barato.
  • Configurar y olvidar. Una regla de WAF sin revisión genera un falso positivo silencioso; fail2ban sin monitorización deja de funcionar cuando el formato del log cambia en una actualización y nadie se da cuenta.

Si tu servidor está en la nube pública, el coste de ignorar esto también aparece en la factura: el tráfico de salida y la CPU extra de los bots se cobran como si fueran de clientes. Detallé esta cuenta en Moodle en AWS vs alojamiento gestionado.

Checklist práctico para proteger un servidor web contra ataques en 30 días

Para quien quiera proteger un servidor web contra ataques por su cuenta, este es el orden que recomendamos — de mayor a menor reducción de riesgo por hora invertida:

Semana 1 — borde

  • Coloca el dominio detrás de Cloudflare (proxy activo, naranja).
  • Cierra el origen: firewall aceptando HTTP/HTTPS solo de los rangos de Cloudflare.
  • Activa el Free Managed Ruleset y crea las reglas de desafío para rutas administrativas.

Semana 2 — acceso

  • SSH solo con clave, inicio de sesión de root desactivado.
  • MFA en panel de alojamiento, registrador de dominio y cuentas administrativas del sistema.
  • Bloqueo de cuenta por intentos en la aplicación (Moodle, WordPress, panel propio).

Semana 3 — servidor

  • real_ip configurado y probado (¿aparece la IP del visitante en el log?).
  • fail2ban con bantime.increment, recidive y jails de la aplicación.
  • limit_req en las rutas de inicio de sesión y búsqueda.

Semana 4 — observación

  • Revisa los bloqueos: ¿quién fue bloqueado era realmente un robot?
  • Prueba la restauración de la copia de seguridad. La protección falla; la copia de seguridad es el plan B. Para Moodle, el paso a paso está en copia de seguridad de Moodle: la rutina que salva a la institución.
  • Define quién recibe la alerta cuando algo salga de lo normal — y en cuánto tiempo responde.

Si has llegado hasta aquí pensando "no tengo quien haga esto", esta es la respuesta honesta: sin alguien que domine el tema, el checklist se convierte en un archivo olvidado.

Cómo Agathas Web lo resuelve

En el alojamiento gestionado de Agathas Web, el trabajo de proteger un servidor web contra ataques descrito en este post no es un opcional: viene configurado por defecto y es mantenido por quien opera el servidor. Concretamente, lo que está incluido:

  • WAF Cloudflare con reglas personalizadas para tu stack (WordPress, Laravel, Next.js, Moodle, ERP), mitigación automática de DDoS y bloqueo de bots maliciosos.
  • fail2ban, rate limit y hardening del sistema operativo, con la IP real configurada correctamente detrás del proxy — la trampa de la sección anterior no sucede.
  • SSL Let's Encrypt automático, MFA obligatorio y auditoría de logs.
  • Monitorización 24/7 con Grafana, Prometheus, Sentry y UptimeRobot, y alertas en el WhatsApp del equipo técnico.
  • Copia de seguridad diaria + incremental, cifrada (AES-256) y fuera del servidor, con restauración probada mensualmente.
  • Parche crítico aplicado en hasta 72 horas tras CVE público, pasando por staging.
  • SLA contractual: 99,9% de uptime, respuesta en hasta 15 minutos y resolución en hasta 2 horas para incidente crítico — con multa si no cumplimos.
  • Informe mensual con uptime, eventos, copias de seguridad probadas y amenazas mitigadas por el WAF.

Cómo funciona: comienza con un diagnóstico gratuito de la infraestructura actual, entregado en hasta 3 días hábiles, con riesgos señalados. Si tiene sentido continuar, migramos sitio web, base de datos, correos electrónicos y DNS en hasta 7 días hábiles, con staging para validación y plan de rollback (el entorno antiguo permanece intacto durante 30 días). Contrato mensual, sin permanencia, 30 días de aviso para cancelar.

Cuánto cuesta: los sitios web institucionales y blogs cuestan, de media, entre 45 € y 90 € al mes; e-commerce y SaaS, entre 110 € y 450 € al mes; la configuración de 150 € a 650 € según la complejidad. Los entornos Moodle tienen una oferta propia — los requisitos están en requisitos de servidor para Moodle 5.x.

Hablas directamente con quien opera tu entorno, por WhatsApp, sin centro de atención al cliente.

Conclusión: la protección es un proceso, no un producto

WAF, rate limit y fail2ban son piezas baratas — gran parte es gratuita. Lo que cuesta es la operación: calibrar límites basándose en el tráfico real, darse cuenta cuando una regla empezó a bloquear a un cliente, reaccionar en minutos cuando el 90% de los ataques duran menos de diez. Para proteger un servidor web contra ataques de forma sostenible, alguien necesita ser responsable de ello cada semana.

Si esa persona aún no existe en tu empresa, pide el diagnóstico gratuito del alojamiento gestionado: en hasta 3 días hábiles sabrás dónde está expuesto tu servidor — y decides qué hacer con ello.