Controle de Rate Limiting por IP no Nginx para Proteção de APIs
Aprenda a implementar o controle de tráfego no Nginx usando zonas de memória e limit_req. Proteja sua infraestrutura contra abusos e ataques de negação de serviço de forma eficiente.
Resumo
- A configuração de limit_req no Nginx evita a sobrecarga do servidor ao restringir a frequência de requisições por endereço IP.
- Zonas de memória compartilhada permitem que diferentes processos de trabalho do Nginx identifiquem requisições excessivas do mesmo cliente.
- O uso do parâmetro burst permite que picos de tráfego temporários sejam tolerados sem bloquear imediatamente usuários legítimos.
- A resposta padrão 503 Service Unavailable é a forma recomendada de indicar ao cliente que a taxa de requisições excedeu o limite permitido.
- Testes de carga são indispensáveis para definir os valores de rate limiting, garantindo um equilíbrio entre segurança e experiência do usuário.
Entendendo o Problema da Exaustão de Recursos
Servidores web costumam ser bombardeados por uma quantidade desproporcional de requisições vindas de uma única fonte. Seja por um script mal escrito, uma tentativa de força bruta em um formulário de login, ou um ataque intencional de negação de serviço, o resultado é o mesmo: seu servidor esgota a CPU ou a memória, tornando o sistema lento para usuários reais. O Rate Limiting, ou limitação de taxa, é a estratégia técnica de impor um teto de requisições que um determinado cliente, identificado pelo seu endereço IP, pode fazer dentro de um intervalo de tempo.
Configuração da Zona de Memória Compartilhada
O Nginx utiliza o módulo ngx_http_limit_req_module para gerenciar essas restrições. A primeira etapa é definir uma área na memória RAM onde o servidor vai registrar a contagem de requisições por cada IP. Isso é chamado de 'shared memory zone'. Sem essa área, o Nginx não teria memória comum para compartilhar entre os vários 'workers' ou processos internos, o que impediria um controle global preciso.
Para configurar isso no seu arquivo nginx.conf, você deve inserir o bloco limit_req_zone no seu contexto HTTP, fora de qualquer bloco de servidor ou localização. O comando fica assim:
http { limit_req_zone $binary_remote_addr zone=meulimite:10m rate=5r/s; }Aqui, definimos que 10MB de memória serão usados para a zona chamada 'meulimite' e que o limite será de 5 requisições por segundo.Implementando a Restrição no Bloco de Localização
Com a zona de memória criada, precisamos aplicar essa regra dentro das rotas que queremos proteger. O objetivo é bloquear requisições que passem desse teto estabelecido. Você pode aplicar isso globalmente no seu site ou apenas em rotas sensíveis, como em uma API de autenticação.
Adicione o parâmetro limit_req dentro do bloco location correspondente:
location /api/ { limit_req zone=meulimite burst=10 nodelay; proxy_pass http://backend; }O parâmetro burst=10 permite que o servidor enfileire até 10 requisições extras caso o cliente ultrapasse o limite momentaneamente, em vez de rejeitá-las de imediato. A flag nodelay processa essas requisições extras sem atrasar a resposta, mantendo a performance da sua API.Escolhendo os Limites de Forma Pragmática
Definir o número ideal de requisições por segundo não é uma ciência exata. Se o valor for muito baixo, você corre o risco de bloquear usuários legítimos que navegam rápido por uma aplicação Single Page Application (SPA). Se for muito alto, sua proteção perde a eficácia contra abusos. A recomendação técnica é analisar os logs de acesso para verificar o comportamento médio dos seus usuários reais.
Para visualizar as tentativas de acesso bloqueadas, monitore o log de erros do Nginx. O servidor registra automaticamente o código de status HTTP 503 quando um cliente ultrapassa o limite. Você pode customizar essa resposta para retornar um JSON amigável, facilitando a depuração caso um sistema interno legítimo seja bloqueado por engano durante um pico de tráfego.
Considerações Sobre a Operação em Produção
Ao operar em ambientes atrás de Load Balancers, como o AWS ALB ou Cloudflare, o endereço IP enviado ao Nginx pode ser o IP do balanceador, e não do usuário final. Nesse cenário, o rate limiting bloqueia o balanceador inteiro, parando o serviço para todos. Certifique-se de configurar o Nginx para ler o cabeçalho X-Forwarded-For ou CF-Connecting-IP utilizando o módulo real_ip.
Concluímos que a proteção por IP é uma camada defensiva necessária, mas nunca deve ser a única. A segurança em profundidade sugere que você combine o rate limiting com outras estratégias, como autenticação via tokens (JWT) e firewalls de aplicação web. O monitoramento contínuo das métricas de bloqueio garantirá que sua infraestrutura permaneça resiliente sem sacrificar a usabilidade de quem realmente importa: o seu cliente.