Volver a explorar Snippets

Smart Rate Limiter: Protección contra Abuso y Fuerza Bruta

JAVASCRIPT 20 de abril de 2026 63 lecturas
Implementación de un limitador de peticiones por IP. Ideal para proteger endpoints sensibles (como el login o registro) evitando el consumo excesivo de recursos y garantizando la disponibilidad del servicio para usuarios legítimos.

Escudos Arriba: Seguridad de APIs con Rate Limiting en Express

El internet público es un campo de batalla automatizado. En el instante en que despliegas una API RESTful en la web, comienza a recibir tráfico silencioso: crawlers, scrapers y bots maliciosos que escanean puertos buscando vulnerabilidades. Dos de los ataques más comunes a los que se enfrenta un backend en Node.js son los ataques de Fuerza Bruta (intentos masivos de adivinar contraseñas) y los ataques de Denegación de Servicio (DDoS).

Si un atacante bombardea tu ruta /login con miles de peticiones por segundo, no solo compromete la seguridad de las cuentas de tus usuarios, sino que agota los hilos del Event Loop de Node.js y satura el pool de conexiones de tu base de datos (por ejemplo, en Prisma). La solución definitiva de infraestructura a nivel de aplicación es la implementación de un Smart Rate Limiter.

Anatomía de la Defensa: ¿Cómo funciona este Middleware?

Este snippet utiliza el paquete express-rate-limit para interceptar y contabilizar las peticiones HTTP entrantes basándose en la dirección IP del cliente. Su configuración está diseñada bajo estándares estrictos de la industria:

  1. La Ventana de Tiempo (windowMs y max): El algoritmo divide el tiempo en bloques (en este caso, 15 minutos). Durante esa ventana, una única dirección IP tiene un límite estricto de 100 peticiones. Este número es lo suficientemente alto para no afectar a un usuario legítimo interactuando intensamente con la plataforma, pero lo suficientemente restrictivo para frenar en seco un script automatizado de fuerza bruta.
  2. Estándares RFC (standardHeaders): Una API profesional debe ser predecible. Al activar las cabeceras estándar, nuestro servidor inyecta automáticamente metadatos en la respuesta HTTP (como RateLimit-Remaining y RateLimit-Reset). Esto permite que los clientes (frontend, aplicaciones móviles o servicios de terceros) lean estos headers y entiendan matemáticamente cuándo pueden volver a intentar la petición sin ser bloqueados.
  3. Respuesta Personalizada (handler): Cuando el límite se excede, el middleware intercepta la conexión y retorna un código de estado HTTP 429 (Too Many Requests). He diseñado el manejador para que retorne un JSON estructurado, indicándole amablemente al usuario el motivo del bloqueo y registrando la IP afectada, lo cual es vital para el monitoreo en logs del servidor.

Optimizando la Experiencia del Desarrollador (DX)

Una de las características que distinguen a este snippet como una implementación "Senior" es la función skip. En el ciclo de vida del software, realizar pruebas de carga o ejecutar hot-reloads constantes en un entorno local de desarrollo (NODE_ENV === 'development') dispararía falsos positivos en el Rate Limiter, frustrando al equipo de frontend. La función skip evalúa la variable de entorno y desactiva el escudo automáticamente en local, activándolo de forma silenciosa e infalible únicamente cuando el código llega a producción.

Este middleware es modular. La mejor estrategia de rendimiento no es aplicarlo globalmente a toda la aplicación, sino inyectarlo como un escudo táctico exclusivamente en rutas críticas (mutaciones de base de datos, envío de correos, o controladores de autenticación).

/**
 * SMART RATE LIMITER MIDDLEWARE
 * Controla el flujo de peticiones para evitar saturación del pool de DB
 */
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // Ventana de 15 minutos
    max: 100, // Límite de 100 peticiones por IP por ventana
    standardHeaders: true, // Retorna info de límite en 'RateLimit-*' headers
    legacyHeaders: false, // Desactiva cabeceras antiguas
    
    // Respuesta personalizada cuando se excede el límite
    handler: (req, res) => {
        res.status(429).json({
            success: false,
            message: "Demasiadas peticiones. Por seguridad, intenta de nuevo en 15 minutos.",
            data: { ip: req.ip }
        });
    },
    
    // No limita en entorno de desarrollo local
    skip: (req) => process.env.NODE_ENV === 'development'
});

// Ejemplo: Aplicar solo a rutas críticas para ahorrar recursos
// router.post('/login', apiLimiter, authController.login);

module.exports = apiLimiter;
¿Qué te pareció?
🔥 Brillante 0
💡 Me sirvió 0
🚀 A otro nivel 0