Objetivos de aprendizaje
Después de leer este artículo podrás:
- Entender qué filtra un proveedor y qué sigue siendo problema de tu aplicación
- Configurar límite de peticiones, timeouts y límite de cuerpo en una API Node.js
- Comprobar con curl que la protección funciona
En esta página
Un ataque DDoS (denegación de servicio distribuida) usa muchas máquinas a la vez para dejar a un objetivo sin capacidad de respuesta. Según la CISA, los atacantes suelen usar botnets, redes de dispositivos secuestrados. El efecto para ti es simple: los usuarios legítimos no pueden acceder a tu sitio, tu API o tu bot.
No existe protección total solo con código. Una parte del ataque debe filtrarse antes de llegar a tu servidor, y otra la resuelves en la propia aplicación. Los ejemplos de abajo muestran qué hace cada capa y cómo configurar la tuya, con una API en Node.js.
¿Qué tipos de ataque DDoS existen?#
Tres familias cubren casi todo:
- Volumétrico: inunda el enlace de red con tráfico (capas 3 y 4 del modelo OSI). Tu código ni siquiera se ejecuta, porque el ancho de banda se agota antes.
- De protocolo: abusa del funcionamiento de TCP, por ejemplo con miles de conexiones semiabiertas, para agotar las tablas de estado del servidor o del firewall.
- De aplicación (capa 7): envía peticiones HTTP aparentemente legítimas, como miles de búsquedas por segundo en una ruta pesada. Es el más barato de lanzar y el que más depende de ti.
Esta división decide la defensa. Solo quien tiene mucha capacidad de red puede absorber los dos primeros. El tercero lo reduces con caché, límites y código eficiente.
¿Qué hace tu proveedor y qué te toca a ti?#
Cloudflare, por ejemplo, describe mitigación automática en las capas 3, 4 y 7 aplicada en el borde de la red. Es el modelo habitual: una CDN o un proxy inverso recibe todo el tráfico, descarta lo que reconoce como ataque y reenvía el resto.
Aun así, lo que pasa el filtro llega a tu código. Te quedan:
- limitar cuántas peticiones hace cada cliente;
- cerrar conexiones lentas o detenidas;
- rechazar cuerpos de petición enormes;
- cachear respuestas costosas;
- no dejar la aplicación accesible por un camino que ignore el borde.
¿Cómo limitar peticiones por cliente?#
El rate limit responde 429 (Too Many Requests) cuando un cliente supera el límite en una ventana de tiempo, como describe MDN. En Express lo hace el paquete express-rate-limit. Los ejemplos usan una versión reciente de Node.js y Express 5.
npm install express express-rate-limit// server.js
import express from "express";
import { rateLimit } from "express-rate-limit";
const app = express();
// Detrás de 1 proxy (CDN o balanceador), usa la IP real del cliente.
// Ajusta el número a tu caso: mira la sección sobre trust proxy.
app.set("trust proxy", 1);
// Límite global: 100 peticiones por minuto por IP.
app.use(
rateLimit({
windowMs: 60 * 1000,
limit: 100,
standardHeaders: "draft-7",
legacyHeaders: false,
}),
);
// Las rutas sensibles tienen un límite más bajo.
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 10,
standardHeaders: "draft-7",
legacyHeaders: false,
});
// Cuerpo JSON limitado a 100 KB.
app.use(express.json({ limit: "100kb" }));
app.get("/", (req, res) => res.json({ ok: true }));
app.post("/login", loginLimiter, (req, res) => res.json({ ok: true }));
const server = app.listen(process.env.PORT ?? 3000);
// Corta conexiones lentas (slowloris) y peticiones que nunca terminan.
server.headersTimeout = 15_000;
server.requestTimeout = 30_000;Puntos a tener en cuenta:
- En la documentación del paquete,
limites el máximo por ventana ywindowMsla duración de la ventana en milisegundos. El valor por defecto de la biblioteca eslimit: 5por minuto, así que define siempre el tuyo. legacyHeaders: falsedesactiva las cabeceras antiguasX-RateLimit-*, ystandardHeadersactiva las cabeceras estandarizadas del IETF.- El contador vive en la memoria del proceso por defecto. Con varias instancias, cada una cuenta por separado. Para un límite compartido, usa un store externo, como Redis.
¿Por qué importa tanto trust proxy?#
Detrás de un proxy, req.ip sería la dirección del proxy, y el rate limit trataría a todos los usuarios como uno solo: un cliente abusivo bloquearía a todos. trust proxy le dice a Express en qué valores de la cabecera X-Forwarded-For confiar, según la guía de Express.
El error opuesto también es peligroso. Si confías en más saltos de los que existen, el cliente falsifica la cabecera y elige la IP que quiera, lo que anula el rate limit. Por eso:
- Averigua cuántos proxies hay entre el usuario y tu aplicación.
- Usa ese número en
trust proxy, y notrue, salvo que el último proxy sobrescriba la cabecera. - Compruébalo registrando
req.ipen una ruta de prueba, desde dos IPs distintas.
¿Qué timeouts configurar?#
Un ataque de conexión lenta mantiene sockets abiertos enviando pocos bytes cada vez. La documentación de Node.js indica que server.headersTimeout y server.requestTimeout deben tener un valor distinto de cero para proteger contra denegación de servicio cuando el servidor no está detrás de un proxy inverso. El valor por defecto de requestTimeout es 300 segundos y el de headersTimeout es el menor entre requestTimeout y 60 segundos. En el código anterior bajan a 15 y 30 segundos. Node comprueba estos plazos cada 30 segundos por defecto (connectionsCheckingInterval), así que el corte puede llegar un poco después del valor configurado.
Si tu API recibe subidas grandes, 30 segundos para todo el cuerpo pueden ser pocos. En ese caso, mantén un requestTimeout más alto y acepta las subidas en un servicio aparte.
¿Cómo reducir el costo de cada petición?#
En un ataque de capa 7, el daño es proporcional a lo que cuesta cada petición. Tres ajustes baratos:
- Caché: sirve páginas y respuestas públicas con
Cache-Controlpara que el borde responda sin llamar a tu código. Mira qué es Cache-Control. - Rutas pesadas tras autenticación: búsquedas, exportaciones y generación de informes no tienen por qué estar abiertas al mundo.
- Paginación y topes: nunca devuelvas una tabla entera ni aceptes
limit=1000000.
El resto del endurecimiento de la API, como validación de entrada y logs, está en el checklist de producción de una API.
¿Cómo comprobar que funciona?#
Con el servidor en marcha, lanza 130 peticiones seguidas y cuenta los códigos de respuesta:
for i in $(seq 1 130); do
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/
done | sort | uniq -cLa salida esperada con limit: 100, si lo ejecutas justo después de iniciar el servidor, es:
100 200
30 429Para el timeout de cabeceras, envía una petición incompleta (sin la línea en blanco final) y espera:
(printf 'GET / HTTP/1.1\r\nHost: localhost\r\n'; sleep 60) | nc localhost 3000
# el servidor responde 408 Request Timeout y cierra la conexiónEn producción, la prueba real es mirar los logs: muchos 429 desde pocas IPs muestran el límite actuando, y picos de tráfico en rutas inesperadas señalan el objetivo del ataque.
¿Cuáles son los errores comunes?#
- Rate limit sin
trust proxy: todos los usuarios comparten la IP del proxy y se bloquean juntos. trust proxy: truesin necesidad: el cliente falsifica su IP y escapa del límite.- Aplicación accesible por la IP directa: el atacante se salta la CDN y golpea el servidor directamente. Responde solo por el dominio o acepta tráfico únicamente del borde.
- Un mismo límite para todo: login y búsqueda necesitan límites mucho más bajos que los archivos estáticos.
- Conteo en memoria con varias instancias: el límite real pasa a ser N veces el configurado.
Cómo hacerlo en Square Cloud#
En Square Cloud, la primera capa viene en todos los planes: mitigación de DDoS en las capas 3, 4 y 7 y un WAF delante de las aplicaciones, en una red con CDN Anycast de más de 200 puntos de presencia (basada en Cloudflare) y hasta 10 Gbps por servidor. Solo el puerto 80 de la aplicación recibe tráfico, publicado por HTTPS en el subdominio squareweb.app o en tu dominio. Ninguna mitigación vuelve inmune a un servicio, y la segunda capa sigue siendo tuya, porque el código es tuyo.
Así encajan los ejemplos de este artículo. La CDN respeta el Cache-Control de tu aplicación, así que las respuestas públicas que marques como cacheables salen del borde sin llamar a tu código, y el purge de caché borra la caché del host cuando publicas un cambio. Confirma el valor de trust proxy con la prueba de req.ip desde dos IP, como en la sección sobre él. Si repartes un dominio entre varias aplicaciones con load balancing (desde el plan Standard), lleva el contador del rate limit al hospedaje de Redis, en el mismo datacenter, para que el límite no se convierta en N veces lo configurado.
Para seguir un ataque, el analytics web incluido en todos los planes muestra rutas, países, status codes y bots verificados: un pico de 429 en una ruta muestra el límite en acción. Mira qué incluye la red en la página de red y conoce el hospedaje de Redis.
Infraestructura
Mitigación de DDoS L3/L4/L7 y WAF en todos los planes
Preguntas frecuentes
¿Puedo protegerme de un DDoS sin proveedor?
Solo de ataques pequeños. Un ataque volumétrico satura el enlace de red antes de llegar a tu código, así que la mitigación debe ocurrir en el borde, con quien tenga capacidad de red para absorber el tráfico.
¿El rate limit por IP detiene un DDoS?
Detiene el abuso de una IP o de pocas, pero no un ataque distribuido con miles de IPs. Es una capa de la defensa, junto con caché, WAF y mitigación en el proveedor.
¿Mi bot de Discord necesita protección contra DDoS?
Normalmente el riesgo es bajo, porque el bot abre conexiones salientes hacia el Gateway y no recibe tráfico público. Vigila cualquier puerto o webhook expuesto y la IP de tu equipo si el bot corre en casa.
¿Cómo sé si estoy sufriendo un ataque DDoS?
Las señales comunes son lentitud repentina, picos de peticiones desde muchas IPs a las mismas rutas y uso alto de CPU o muchas conexiones abiertas sin más usuarios reales. Confírmalo revisando los logs de acceso.
Más en Seguridad
Ver los 10 artículos- ¿Qué es un ataque de fuerza bruta y cómo protegerte?Un ataque de fuerza bruta prueba contraseñas en masa hasta acertar una. Mira los tipos (spraying, credential stuffing), cómo funcionan y las defensas con código.
- Hackearon mi aplicación: qué hacer ahoraSi hackearon tu aplicación, contén el acceso, cambia todos los secretos y conserva los logs antes de limpiar. El orden correcto, cómo hallar la causa y cómo volver.
- Checklist de seguridad para publicar un bot, sitio o APIChecklist de seguridad antes de publicar un bot, sitio o API: secretos en variables de entorno, dependencias, HTTPS, cabeceras, permisos mínimos y logs.
- ¿Se filtró el token de tu bot? Qué hacer ahoraSi se filtró el token de tu bot, restablécelo en el Portal de Discord (o con /token en BotFather) antes que nada. Mira el orden correcto y cómo revisar el daño.