Tutoriales de VPS
Qué hacer cuando un sitio web en VPS sufre un ataque CC (2026): WAF de Cloudflare, limitación de velocidad en Nginx y lista de emergencia para proteger el origen
Cuando un sitio web en VPS de repente muestra CPU alta, ancho de banda saturado y un access.log de Nginx inundado por el mismo lote de IP o rutas, no necesariamente es un aumento normal de tráfico: bien puede ser un ataque CC, un rastreador malicioso o un abuso de API. Este artículo sigue el orden real de emergencia: primero confirmar desde los registros si es un ataque en la capa HTTP, luego usar Cloudflare WAF/Rate Limiting para bloquear en el borde, usar Nginx limit_req y limit_conn para proteger el origen como respaldo, y explicar cómo evitar perjudicar a los motores de búsqueda y a los usuarios normales.

Cuando un sitio web de repente se vuelve lento, no te apresures a reiniciar el VPS.
Si ves la CPU disparada, el ancho de banda saturado, PHP-FPM o la aplicación backend con tiempos de espera agotados por todas partes, y la misma ruta siendo machacada en el access.log de Nginx, esto se parece más a un ataque CC / rastreador malicioso / abuso de API que a un "aumento de tráfico" normal.
La parte más problemática de este tipo de problema es que las solicitudes parecen todas solicitudes HTTP normales, a diferencia de un DDoS tradicional que es solo una inundación de tráfico. Puede machacar la página de inicio, las páginas de búsqueda, las páginas de inicio de sesión o las API, y también puede usar un montón de IP dispersas para saturar lentamente tu base de datos y PHP-FPM.
Este artículo sigue el orden real de manejo: primero confirmar el ataque, luego dejar que Cloudflare bloquee una capa en el borde y, finalmente, usar Nginx para hacer una limitación de velocidad de respaldo en el origen.
Las señales más intuitivas suelen ser estas:
- La CPU o el load average del VPS sube de repente;
- El volumen de solicitudes de
access.loges anómalo, de varias a decenas de veces superior a lo normal; - Una determinada ruta se solicita repetidamente, por ejemplo
/wp-login.php,/xmlrpc.php,/search,/api/*; - Nginx todavía puede responder, pero el backend empieza a devolver 502, 504;
- Cloudflare Analytics o el gráfico de tráfico del proveedor muestra picos anómalos;
- Los usuarios normales acceden lentamente, pero los recursos estáticos pueden seguir funcionando bien.
Primero mira las IP con mayor volumen de solicitudes recientes:
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Luego mira las rutas más machacadas:
sudo awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Si tu sitio web está detrás de Cloudflare, los registros de Nginx pueden estar llenos de IP de nodos de Cloudflare, en cuyo caso primero debes configurar la IP real del visitante, de lo contrario harás un juicio erróneo.
La práctica común en Nginx es usar CF-Connecting-IP:
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
real_ip_header CF-Connecting-IP;
Los rangos de IP de Cloudflare se actualizan, por lo que en producción se recomienda verificar la lista oficial periódicamente. Después de configurar, primero ejecuta:
sudo nginx -t
sudo systemctl reload nginx
Si aún no estás familiarizado con la localización de problemas en los registros, puedes leer esto primero:
Si el tráfico del ataque ya pasa por Cloudflare, manéjalo primero en Cloudflare. La razón es simple: bloquear las solicitudes en el borde evita consumir la CPU, la memoria, el ancho de banda y las conexiones de base de datos de tu VPS.
Para una emergencia temporal, primero puedes hacer tres cosas:
- Activar las reglas gestionadas en Security / WAF;
- Añadir una Custom Rule para las rutas anómalas;
- Añadir una Rate Limiting Rule para rutas pesadas como inicio de sesión, búsqueda y API.
Por ejemplo, si el ataque se concentra en /wp-login.php, primero puedes añadir una regla más estricta:
- Ruta coincidente:
/wp-login.php - Dimensión de conteo: IP
- Umbral: 5-10 veces por minuto
- Acción: Managed Challenge o Block
- Duración del bloqueo: de 10 minutos a 1 hora
Si lo que se machaca es una API, por ejemplo /api/search, el umbral puede ser más holgado que el de la página de inicio de sesión:
- 60-120 veces por minuto;
- Devolver 429 o Managed Challenge al superarlo;
- Hacer excepciones para usuarios con sesión iniciada, monitorización interna o IP de confianza.
No bloquees todo el sitio de inmediato. Así es como muchos sitios pequeños se perjudican: se bloquean juntos los motores de búsqueda, las devoluciones de pago, las sondas de monitorización y los usuarios móviles normales; el ataque se mitiga, pero el negocio también.
La documentación oficial de Cloudflare Rate Limiting también advierte: la limitación de velocidad no permite con precisión un número fijo de solicitudes, y puede haber unos segundos de retraso entre el conteo y el bloqueo. Por eso el origen todavía necesita configuración de respaldo.
El limit_req de Nginx usa un enfoque similar al "cubo con fugas": las solicitudes pueden tener ráfagas breves, pero la tasa a largo plazo no puede superar el umbral que establezcas.
Primero define las zonas de limitación de velocidad en el bloque http, normalmente colocadas en /etc/nginx/nginx.conf o /etc/nginx/conf.d/limits.conf:
limit_req_zone $binary_remote_addr zone=site_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr_limit:10m;
El significado es aproximadamente:
- Páginas normales: 10 solicitudes por segundo por IP;
- Inicio de sesión/API sensibles: 1 solicitud por segundo por IP;
- La memoria compartida de
10mes suficiente para rastrear una gran cantidad de IP; $binary_remote_addrusa menos memoria que una cadena de IP normal.
Luego aplícalo en la configuración del sitio:
server {
server_name example.com;
limit_req zone=site_limit burst=30 nodelay;
limit_conn addr_limit 20;
limit_req_status 429;
limit_conn_status 429;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /wp-login.php {
limit_req zone=login_limit burst=5 nodelay;
limit_req_status 429;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location = /xmlrpc.php {
deny all;
}
}
Aquí hay varios detalles importantes:
burst=30da a los navegadores normales un breve margen de ráfaga al cargar una página;nodelaysignifica que las solicitudes en ráfaga no se ponen en cola y se manejan directamente según la regla una vez superado el límite;limit_req_status 429es más claro que el 503 predeterminado, significa demasiadas solicitudes;- El
xmlrpc.phpde WordPress debe desactivarse directamente si no se usa; - Las API, el inicio de sesión y las páginas de búsqueda deben limitarse por separado; no uses un solo umbral para todo el sitio.
Después de modificar, siempre prueba primero:
sudo nginx -t
sudo systemctl reload nginx
Si recientemente cambiaste la configuración de Nginx y encuentras un fallo de reload, puedes leer esto primero:
La limitación de velocidad no es mejor cuanto más estricta.
He visto un sitio pequeño limitar todo el sitio a 1r/s, y como resultado la página de inicio tenía una docena de recursos CSS, JS e imágenes, así que los usuarios recibían 429 en cuanto abrían la página. El ataque no se bloqueó del todo, pero los usuarios normales quedaron fuera primero.
Después de ponerlo en marcha, primero mira el registro de errores de Nginx:
sudo tail -f /var/log/nginx/error.log | grep "limiting requests"
Si ves algo como:
limiting requests, excess: 12.450 by zone "site_limit", client: 203.0.113.10
significa que esta IP está activando la limitación de velocidad.
Luego cuenta por código de estado:
sudo awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
Si los 429 de repente son muchos, sigue mirando las rutas:
sudo awk '$9 == 429 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Si los 429 se concentran en /wp-login.php, /xmlrpc.php, /api/search, normalmente es algo bueno; si la página de inicio, los recursos estáticos y las comprobaciones de estado también reciben muchos 429, las reglas son demasiado gruesas.
Mucha gente se relaja después de poner Cloudflare delante, pero si la IP de origen ya se ha filtrado, los atacantes pueden acceder directamente a la IP de tu VPS y eludir Cloudflare.
Las señales típicas de esta situación son:
- No se ven muchas solicitudes en Cloudflare;
- Pero el ancho de banda del VPS y los registros de Nginx son muy altos;
- Aparecen en Nginx muchas IP de origen que no son de Cloudflare;
- Acceder directamente a
http://你的源站IPpuede abrir el sitio web.
Como mínimo, haz dos cosas.
Primero, el sitio predeterminado de Nginx no debe servir directamente el sitio web real:
server {
listen 80 default_server;
server_name _;
return 444;
}
Segundo, el firewall solo debe permitir que las IP de Cloudflare accedan a 80/443. Ten cuidado con este paso: primero confirma que puedes iniciar sesión por SSH y que los rangos de IP de Cloudflare están completos, de lo contrario podrías cortar tu propio sitio web.
Si la IP de origen ha sido objetivo durante mucho tiempo, el enfoque más limpio suele ser:
- Abrir un nuevo VPS o cambiar la IP pública;
- Poner solo la nueva IP de origen en el DNS de Cloudflare;
- Restringir el firewall para que 80/443 solo acepte Cloudflare;
- No filtrar la nueva IP en encabezados de correo, repositorios Git, DNS histórico ni páginas de monitorización.
Si el ataque provoca Cloudflare 521/522, puedes consultar:
Si el ataque proviene de unas pocas IP fijas, bloquear IP es útil:
sudo ufw deny from 203.0.113.10
O usar iptables temporalmente:
sudo iptables -I INPUT -s 203.0.113.10 -j DROP
Pero si el ataque proviene de cientos o miles de IP, bloquear IP manualmente es básicamente inútil. Harás que la tabla de reglas sea cada vez más desordenada, y la CPU todavía tiene que procesar una gran cantidad de conexiones.
En este caso, es mejor usar:
- Cloudflare WAF / Rate Limiting;
- Nginx
limit_reqylimit_conn; - Fail2Ban para bloquear automáticamente las IP que activan continuamente la limitación de velocidad;
- La protección de alta defensa del proveedor o una protección DDoS más upstream.
Si ya sospechas que la máquina ha sido comprometida en lugar de simplemente inundada de solicitudes, primero sigue el proceso de manejo de intrusiones:
Si el sitio web está siendo machacado, yo lo manejaría en este orden:
- Primero mirar el access.log de Nginx para confirmar las IP de alta frecuencia y las rutas de alta frecuencia;
- Si pasa por Cloudflare, primero activar WAF / Managed Challenge / Rate Limiting;
- Centrar la protección en inicio de sesión, búsqueda, API y
xmlrpc.php; - Añadir en Nginx
limit_req,limit_conny el código de estado 429; - Comprobar la configuración de IP real para evitar que Nginx solo vea IP de nodos de Cloudflare;
- Restringir el firewall para que el origen solo acepte acceso de Cloudflare;
- Observar los cambios en 429, 403, 502, 504 para evitar perjudicar a usuarios normales;
- Después de que termine el ataque, hacer una revisión: si la IP de origen se filtró, qué rutas son las más costosas y si se necesita caché o división de arquitectura.
No trates la limitación de velocidad como una panacea. Para un DDoS volumétrico realmente a gran escala, Nginx se saturará antes de poder manejarlo, y debes apoyarte en Cloudflare, la protección de alta defensa del proveedor o el scrubbing upstream. La limitación de velocidad de Nginx es más adecuada para bloquear CC de pequeña y mediana escala, rastreadores maliciosos, abuso de API y fuerza bruta de inicio de sesión: solicitudes en la capa HTTP.
Puede hacerlo. Especialmente si configuras la limitación de velocidad de todo el sitio demasiado baja, o no dejas suficiente margen para Cloudflare Verified Bots, Googlebot y Bingbot. Un enfoque más estable es priorizar la limitación de inicio de sesión, búsqueda, API y páginas dinámicas, y no atacar directamente con dureza los recursos estáticos y las páginas normales.
Para la mayoría de los sitios pequeños normales, basta la mayor parte del tiempo. El plan gratuito ofrece CDN, protección DDoS básica, reglas WAF y algunas capacidades de protección contra bots. Pero la limitación de velocidad más granular, la gestión de bots y las dimensiones de conteo complejas suelen requerir un plan superior.
Con unas pocas IP fijas, sí. Para ataques distribuidos, no se recomienda el bloqueo manual; usa una combinación de Cloudflare, limitación de velocidad de Nginx, Fail2Ban y protección del proveedor.
La limitación de velocidad es más adecuada para devolver 429, que significa Too Many Requests. Las reglas de maliciosos claros, las listas negras, el User-Agent vacío y las firmas de herramientas de ataque pueden devolver 403.
Cuando un sitio web en VPS sufre un ataque CC, los dos extremos son los más peligrosos: solo saber reiniciar servicios, y bloquear todo el sitio de inmediato.
Un enfoque más estable es el manejo por capas: Cloudflare bloquea el grueso en el borde, Nginx usa limit_req y limit_conn como respaldo en el origen, el firewall evita que se eluda la IP de origen y los registros observan continuamente el daño a usuarios normales y las rutas de ataque.
Si solo recuerdas una cosa: primero usa los registros para confirmar la ruta del ataque, luego limita la velocidad de las rutas más costosas, y no limites la velocidad de todo el sitio a ciegas.