Rate limiting avançado com Nginx
Rate limiting no Nginx protege a API contra abuso, brute force e DDoS de camada 7 sem depender de software externo. Com limit_req_zone e limit_conn_zone, você controla quantas requisições por segundo cada IP pode fazer — granularmente por rota, método HTTP ou até por usuário autenticado.
Configurar zonas de rate limiting
Defina zonas de memória para rastrear contadores por IP:
nginx
# /etc/nginx/nginx.conf — dentro do bloco http {}
# Zona de rate limit por IP (10m de memória = ~160.000 IPs)
limit_req_zone $binary_remote_addr zone=api_rate:10m rate=10r/s;
# Zona para rotas sensíveis (login, cadastro)
limit_req_zone $binary_remote_addr zone=auth_rate:10m rate=3r/m;
# Zona para uploads (1 por segundo por IP)
limit_req_zone $binary_remote_addr zone=upload_rate:5m rate=1r/s;
# Zona de conexões simultâneas por IP
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# Logging de requisições limitadas (level warning)
limit_req_log_level warn;
limit_req_status 429; # retornar HTTP 429 em vez de 503
# Cabeçalhos para informar o cliente sobre o limite:
# (disponível no Nginx 1.23+)
# limit_req_dry_run on; # testar sem bloquear (apenas logar)Aplicar rate limiting por rota
Aplicar limites diferentes para cada endpoint da API:
nginx
server {
listen 443 ssl http2;
server_name api.seudominio.com.br;
# Rate limit padrão para toda a API: 10 req/s com burst de 20
location /api/ {
limit_req zone=api_rate burst=20 nodelay;
limit_conn conn_limit 20;
proxy_pass http://127.0.0.1:3000;
}
# Login: máx 3 tentativas por minuto por IP
location /api/auth/login {
limit_req zone=auth_rate burst=5 nodelay;
proxy_pass http://127.0.0.1:3000;
}
# Cadastro: máx 3 por minuto
location /api/auth/register {
limit_req zone=auth_rate burst=3 nodelay;
proxy_pass http://127.0.0.1:3000;
}
# Upload de arquivos: 1 por segundo, máx 3 simultâneos
location /api/upload {
limit_req zone=upload_rate burst=3;
limit_conn conn_limit 3;
client_max_body_size 100M;
proxy_pass http://127.0.0.1:3000;
}
# Healthcheck: sem rate limit
location /health {
proxy_pass http://127.0.0.1:3000;
}
}Dica
nodelay: processa requisições do burst imediatamente (sem atraso), mas conta contra o limite. Sem nodelay: requisições do burst são enfileiradas — o cliente espera. Para APIs: use nodelay para não adicionar latência desnecessária.
Whitelist e limites diferenciados por IP
Isentar IPs internos e aplicar limites diferentes por origem:
nginx
# /etc/nginx/conf.d/rate-limit-map.conf
# Mapa para definir limite por IP de origem
geo $limit_key {
default $binary_remote_addr; # IPs não listados: limite por IP
10.0.0.0/8 ""; # rede interna: sem limite (key vazia)
177.10.0.1/32 ""; # IP do escritório: sem limite
192.168.0.0/16 ""; # rede local: sem limite
}
# Zona usando a key condicional
limit_req_zone $limit_key zone=api_conditional:10m rate=10r/s;
# No server block:
location /api/ {
# IPs internos ($limit_key = "") não são limitados
# IPs externos são limitados por $binary_remote_addr
limit_req zone=api_conditional burst=20 nodelay;
proxy_pass http://127.0.0.1:3000;
}
# Alternativa: mapa de limites por tier
map $http_x_api_key $rate_limit_zone {
default "default_zone";
"chave_premium_1" ""; # sem limite para clientes premium
"chave_premium_2" "";
}Resposta customizada para requisições limitadas
Retornar JSON adequado quando o rate limit é atingido:
nginx
# /etc/nginx/conf.d/errors.conf
# Página de erro customizada para 429
error_page 429 /rate-limit.json;
location = /rate-limit.json {
internal;
default_type application/json;
return 429 '{"error":"rate_limit_exceeded","message":"Muitas requisições. Tente novamente em alguns segundos.","status":429}';
}
# No bloco server — adicionar headers Retry-After:
location /api/ {
limit_req zone=api_rate burst=20 nodelay;
# Header informando quanto tempo aguardar:
add_header Retry-After 1 always;
add_header X-RateLimit-Limit 10 always;
proxy_pass http://127.0.0.1:3000;
}Monitorar rate limiting nos logs
Identificar IPs que atingem o rate limit frequentemente:
bash
# Contar IPs que receberam 429 nas últimas horas:
sudo grep "limiting requests" /var/log/nginx/error.log \
| awk '{print $NF}' \
| sort | uniq -c | sort -rn | head -20
# Identificar endpoints mais limitados:
sudo awk '$9 == 429 {print $7}' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn | head -10
# Script para bloquear IPs abusivos com fail2ban:
# /etc/fail2ban/filter.d/nginx-ratelimit.conf
[Definition]
failregex = limiting requests, excess:.* by zone .*, client: <HOST>
ignoreregex =
# /etc/fail2ban/jail.d/nginx-ratelimit.conf
[nginx-ratelimit]
enabled = true
filter = nginx-ratelimit
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 60
bantime = 3600$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.