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.

    Perguntas frequentes