Por Qué la Limitación de Velocidad es Importante
Todo servidor web público está sujeto a picos de tráfico, scrapers automatizados, intentos de fuerza bruta y ataques de denegación de servicio distribuido (DDoS). Sin limitación de velocidad, un solo cliente abusivo puede agotar la CPU, memoria y descriptores de archivo de su servidor, haciendo el servicio inaccesible para usuarios legítimos.
La limitación de velocidad integrada de Nginx proporciona una capa de defensa ligera y de alto rendimiento que opera a nivel de proxy inverso, antes de que las solicitudes lleguen a su aplicación. Usando los módulos ngx_http_limit_req_module y ngx_http_limit_conn_module, puede aplicar tasas de solicitud por IP o por usuario, límites de conexión y permisos de ráfaga con mínima configuración.
Esta guía muestra configuraciones prácticas de limitación de velocidad para endpoints de API, páginas de inicio de sesión, activos estáticos y protección general del sitio.
Requisitos Previos
- Nginx 1.18+ instalado (ambos módulos están compilados por defecto).
- Acceso
sudoo root para editar archivos de configuración de Nginx. - Familiaridad básica con la sintaxis de configuración de Nginx (
http,server,location). - Una herramienta de prueba como
curl, Apache Bench (ab) owrk.
Entendiendo el Algoritmo de Cubo con Fugas
La limitación de velocidad de Nginx usa el algoritmo de cubo con fugas (leaky bucket). Imagine un cubo con un pequeño agujero en el fondo:
- Las solicitudes llenan el cubo desde arriba.
- El cubo drena a una tasa fija (su tasa configurada, ej. 10 solicitudes/segundo).
- Si el cubo se desborda, las solicitudes excedentes son rechazadas o encoladas (burst).
Solución Paso a Paso
1. Definir una Zona de Limitación
En su nginx.conf (dentro del bloque http), defina una zona de memoria compartida:
http {
# Zona "api": por IP del cliente, 10MB almacenamiento, 10 solicitudes/segundo
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# Zona "login": más estricta, 5 solicitudes/minuto
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# Zona "general": moderada, 30 solicitudes/segundo
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
}
2. Aplicar Límites a Ubicaciones
server {
listen 80;
server_name ejemplo.com;
limit_req zone=general burst=50 nodelay;
limit_req_status 429;
location /api/auth/login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://backend;
}
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
}
location /static/ {
limit_req off;
alias /var/www/static/;
}
}
Entendiendo burst y nodelay:
burst=N: Permite hasta N solicitudes adicionales sobre el límite que se encolan en lugar de rechazarse inmediatamente.nodelay: Procesa las solicitudes de ráfaga inmediatamente sin demora.delay=N: (Nginx 1.15.7+) Híbrido: las primeras N solicitudes de ráfaga se procesan inmediatamente, el resto se demoran.
3. Configurar Limitación de Conexiones
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
limit_conn addr 10;
limit_conn_status 429;
location /descargas/ {
limit_conn addr 2;
limit_rate 500k;
}
}
}
4. Excluir IPs Confiables
http {
geo $limit_key {
default $binary_remote_addr;
10.0.0.0/8 "";
192.168.1.0/24 "";
203.0.113.50 "";
}
limit_req_zone $limit_key zone=api:10m rate=10r/s;
}
5. Respuestas de Error Personalizadas
error_page 429 = @rate_limited;
location @rate_limited {
default_type application/json;
return 429 '{"error": "rate_limit_exceeded", "message": "Demasiadas solicitudes. Intente nuevamente en unos segundos.", "retry_after": 1}';
}
6. Probar la Configuración
sudo nginx -t
sudo systemctl reload nginx
# Probar con Apache Bench
ab -n 100 -c 10 http://ejemplo.com/api/data
# O con curl en un bucle
for i in $(seq 1 20); do
echo "Solicitud $i: $(curl -s -o /dev/null -w '%{http_code}' http://ejemplo.com/api/data)"
done
Errores Comunes y Casos Especiales
- Cadenas de proxy inverso: Si Nginx está detrás de un balanceador de carga o CDN,
$binary_remote_addrserá la IP del proxy. Use el módulorealippara extraer la IP real del cliente. - Direcciones IPv6:
$binary_remote_addres 16 bytes para IPv6 (vs 4 para IPv4). Dimensione las zonas apropiadamente. - Claves API en lugar de IPs: Para APIs autenticadas, puede usar un header como clave:
limit_req_zone $http_x_api_key zone=apikey:10m rate=100r/s;
Prevención
- Combine con un WAF: Use ModSecurity, Cloudflare o AWS WAF para defensa en profundidad.
- Use fail2ban: Bloquee automáticamente IPs que excedan los límites persistentemente.
- Monitoree con métricas: Exporte métricas con el módulo
stub_statusy alerte sobre tasas elevadas de 429. - Ajuste gradualmente: Comience con límites generosos y ajústelos según los patrones de tráfico observados.
Resumen
- La limitación de velocidad de Nginx usa
limit_req_zone/limit_reqpara tasas de solicitud ylimit_conn_zone/limit_connpara límites de conexión. - El algoritmo de cubo con fugas suaviza los picos de tráfico en lugar de imponer conteos rígidos por segundo.
- Configure siempre
burstynodelaypara cargas de producción. - Use
limit_req_status 429para devolver el código HTTP 429 estándar. - Excluya IPs confiables con bloques
geoy pruebe exhaustivamente antes de desplegar.