Como configurar rate limiting no Nginx
1. Introdução ao Rate Limiting no Nginx
Rate limiting é uma técnica essencial para proteger servidores web e APIs contra abusos, ataques de negação de serviço (DoS) e uso excessivo de recursos. No Nginx, o módulo ngx_http_limit_req_module oferece uma implementação robusta e flexível para controlar a taxa de requisições.
A importância do rate limiting se manifesta em diversos cenários:
- Proteção de APIs: Evita que um único cliente consuma todos os recursos
- Mitigação de ataques: Reduz o impacto de ataques de força bruta e DDoS
- Garantia de qualidade: Mantém a experiência do usuário durante picos de tráfego
- Controle de custos: Limita o uso de recursos em ambientes com cobrança por requisição
O Nginx gerencia o rate limiting através de duas diretivas principais: limit_req_zone, que define as zonas de memória compartilhada para rastreamento, e limit_req, que aplica os limites às requisições.
O rate limiting pode ser baseado em diferentes critérios:
- Por IP: Utilizando $binary_remote_addr para identificar cada cliente
- Por chave personalizada: Combinando variáveis como $http_x_api_key ou $uri
- Por geolocalização: Usando módulos GeoIP para limitar regiões específicas
2. Configuração Básica com limit_req_zone
A diretiva limit_req_zone define uma zona de memória compartilhada onde o Nginx armazena o estado de cada chave de limitação. A sintaxe básica é:
limit_req_zone $binary_remote_addr zone=minhazona:10m rate=10r/s;
Parâmetros essenciais:
- $binary_remote_addr: Chave baseada no endereço IP do cliente (formato binário para economia de memória)
- zone=minhazona:10m: Nome da zona e tamanho da memória compartilhada (10 MB)
- rate=10r/s: Taxa máxima de 10 requisições por segundo
Exemplo prático completo:
http {
# Define a zona de rate limiting
limit_req_zone $binary_remote_addr zone=limite_ip:10m rate=10r/s;
server {
listen 80;
server_name exemplo.com;
location /api/ {
# Aplica o limite definido na zona
limit_req zone=limite_ip;
proxy_pass http://backend_api;
}
}
}
3. Aplicação de Limites com limit_req
A diretiva limit_req aplica os limites definidos nas zonas. Ela pode ser usada nos blocos http, server ou location.
Controle de burst (rajadas):
location /api/ {
limit_req zone=limite_ip burst=20;
proxy_pass http://backend_api;
}
O parâmetro burst permite que requisições excedentes sejam enfileiradas temporariamente, em vez de serem rejeitadas imediatamente.
Gerenciamento com nodelay:
location /api/ {
limit_req zone=limite_ip burst=20 nodelay;
proxy_pass http://backend_api;
}
- Sem
nodelay: Requisições em burst são atrasadas para respeitar a taxa - Com
nodelay: Requisições em burst são processadas imediatamente, mas o burst é consumido mais rapidamente
4. Personalização de Respostas e Erros
Quando o limite é excedido, o Nginx retorna o código de status 503 por padrão. Podemos personalizar essa resposta:
Alterando o código de status:
location /api/ {
limit_req zone=limite_ip burst=20;
limit_req_status 429;
proxy_pass http://backend_api;
}
Customizando a mensagem de erro:
location /api/ {
limit_req zone=limite_ip burst=20;
limit_req_status 429;
error_page 429 /custom_429.html;
location = /custom_429.html {
internal;
root /usr/share/nginx/html;
}
}
Adicionando cabeçalho Retry-After:
location /api/ {
limit_req zone=limite_ip burst=20;
limit_req_status 429;
# Adiciona cabeçalho Retry-After
add_header Retry-After 60 always;
proxy_pass http://backend_api;
}
5. Estratégias Avançadas de Rate Limiting
Limitação por múltiplas zonas:
http {
# Limite por IP
limit_req_zone $binary_remote_addr zone=por_ip:10m rate=10r/s;
# Limite por chave de API
limit_req_zone $http_x_api_key zone=por_chave:10m rate=100r/s;
server {
location /api/ {
# Aplica ambos os limites
limit_req zone=por_ip burst=20;
limit_req zone=por_chave burst=200;
proxy_pass http://backend_api;
}
}
}
Uso de variáveis personalizadas:
http {
# Combina IP com caminho da requisição
limit_req_zone $binary_remote_addr$uri zone=por_ip_uri:10m rate=5r/s;
# Limita por método HTTP
map $request_method $limit_key {
default "";
POST $binary_remote_addr;
}
limit_req_zone $limit_key zone=post_limit:10m rate=2r/s;
}
Combinação com limit_conn para controle de conexões:
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /api/ {
limit_req zone=req_limit burst=20;
limit_conn conn_limit 10;
proxy_pass http://backend_api;
}
}
}
6. Monitoramento e Logs de Rate Limiting
Configuração de logs detalhados:
http {
log_format rate_limit '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'limit=$limit_req_status';
server {
access_log /var/log/nginx/access.log rate_limit;
location /api/ {
limit_req zone=limite_ip burst=20;
proxy_pass http://backend_api;
}
}
}
Identificação de requisições limitadas: Os logs conterão registros com código 503 ou 429, indicando requisições que excederam os limites.
Análise com stub_status:
server {
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
}
7. Testes e Validação da Configuração
Teste básico com curl:
# Teste de requisição normal
curl -I http://localhost/api/teste
# Teste de rate limiting (enviar 15 requisições rapidamente)
for i in {1..15}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost/api/teste; done
Simulação de carga com ab (Apache Benchmark):
# 100 requisições, 10 concorrentes
ab -n 100 -c 10 http://localhost/api/teste
Teste com wrk para cenários mais realistas:
# 10 conexões por 30 segundos
wrk -t2 -c10 -d30s http://localhost/api/teste
Validação de burst e nodelay:
# Envia 30 requisições rapidamente (burst de 20 + taxa normal)
for i in {1..30}; do curl -s -o /dev/null -w "%{http_code} " http://localhost/api/teste; done
echo ""
8. Boas Práticas e Considerações Finais
Escolha adequada de taxa e burst:
- Analise o tráfego normal para definir limites realistas
- Comece com valores conservadores e ajuste gradualmente
- Considere o comportamento de bots e crawlers legítimos
Impacto em cache e balanceamento de carga:
- Rate limiting pode afetar a eficiência do cache
- Em ambientes com múltiplos servidores, use sticky sessions ou armazenamento compartilhado
- Considere o uso de limit_req_zone com variáveis que incluam o servidor de destino
Documentação e versionamento:
- Mantenha as configurações em arquivos versionados (Git)
- Documente cada zona de rate limiting com seu propósito
- Estabeleça procedimentos para revisão periódica dos limites
Exemplo de configuração final completa:
http {
# Zonas de rate limiting
limit_req_zone $binary_remote_addr zone=limite_geral:10m rate=10r/s;
limit_req_zone $http_x_api_key zone=limite_api:10m rate=100r/s;
# Log personalizado
log_format rate_limit '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'limit_status=$limit_req_status';
server {
listen 80;
server_name api.exemplo.com;
access_log /var/log/nginx/api_access.log rate_limit;
location /api/v1/ {
limit_req zone=limite_geral burst=20 nodelay;
limit_req zone=limite_api burst=200 nodelay;
limit_req_status 429;
add_header Retry-After 60 always;
error_page 429 /429.html;
proxy_pass http://backend_api;
}
location = /429.html {
internal;
root /usr/share/nginx/html;
}
}
}
Rate limiting é uma ferramenta poderosa quando configurada corretamente. A chave está em encontrar o equilíbrio entre proteção e usabilidade, ajustando os parâmetros com base em dados reais de tráfego e feedback dos usuários.
Referências
-
Documentação Oficial do Módulo limit_req no Nginx — Referência completa sobre as diretivas
limit_req_zoneelimit_req, incluindo todos os parâmetros e exemplos de uso. -
Rate Limiting com Nginx e ngx_http_limit_req_module — Guia oficial da Nginx Inc. sobre controle de acesso e rate limiting em ambientes de produção.
-
Tutorial Prático de Rate Limiting no Nginx — Tutorial completo da DigitalOcean com exemplos passo a passo para configurar rate limiting em servidores web.
-
Estratégias Avançadas de Rate Limiting com Nginx — Artigo do blog oficial da Nginx abordando técnicas avançadas, incluindo múltiplas zonas e personalização de respostas.
-
Ferramenta wrk para Testes de Carga HTTP — Repositório oficial da ferramenta wrk, ideal para simular cargas de trabalho e validar configurações de rate limiting.