Servidores de Jogos

Rate limiting no Nginx: proteja o site do seu servidor de jogo contra bot spam

O problema

Se você tem site pro seu servidor de jogo (loja de VIP, painel de admin, fórum), vai receber:

  • Scrapers puxando conteúdo pra revender
  • Brute force tentando adivinhar login admin
  • Bots de spam enchendo formulários
  • DDoS de aplicação (Layer 7)

Rate limiting no Nginx = limitar quantas requisições cada IP pode fazer por segundo/minuto. Barato, eficaz, embutido.

Como funciona (conceito)

Nginx conta requests por IP numa "leaky bucket" (balde furado):

  • Bucket enche a cada request
  • Fura constantemente na taxa que você define
  • Se transbordar: request rejeitada (HTTP 503)

Setup básico

Adicione em /etc/nginx/nginx.conf dentro do bloco http:

http {
    # Zona compartilhada de rate limit (10 MB armazena ~160k IPs)
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m   rate=1r/s;
    limit_req_zone $binary_remote_addr zone=api:10m     rate=30r/s;

    # Limita conexões simultâneas por IP
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    # Custom response
    limit_req_status 429;
    limit_conn_status 429;

    # ...resto do config...
}

Cada limit_req_zone cria uma "zona" nomeada. Explicação:

  • $binary_remote_addr — chave (IP do cliente em formato binário compacto)
  • zone=general:10m — nome + 10 MB de RAM
  • rate=10r/s — 10 requests por segundo (sustained)

Aplicar por rota

No seu server block:

server {
    server_name loja.meuservidor.com.br;

    # Regra geral (10 req/s)
    location / {
        limit_req zone=general burst=20 nodelay;
        limit_conn addr 10;
        try_files $uri $uri/ /index.php?$args;
    }

    # Login: 1 req/s (protege brute force)
    location = /wp-login.php {
        limit_req zone=login burst=3 nodelay;
        include fastcgi_params;
        # ...
    }

    # API: 30 req/s
    location /api/ {
        limit_req zone=api burst=50 nodelay;
        proxy_pass http://backend;
    }

    # Assets estáticos: sem limit
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 30d;
    }
}

Explicação dos parâmetros

  • burst=20 — permite pico de 20 req antes de aplicar rate limit
  • nodelay — processa o burst imediatamente (senão fica em fila)
  • limit_conn addr 10 — cada IP pode ter no máx 10 conexões abertas simultâneas

Casos de uso reais

Proteger /wp-login.php (WordPress)

Cada tentativa custa 1 req. Bot tentando 1000 senhas/min = bloqueado em segundos:

location = /wp-login.php {
    limit_req zone=login burst=3 nodelay;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}

Proteger /api/checkout

Bot testando roubo de cartão? Limita a 5/min:

limit_req_zone $binary_remote_addr zone=checkout:10m rate=5r/m;
# ...
location /api/checkout {
    limit_req zone=checkout burst=2 nodelay;
    proxy_pass http://backend;
}

Proteger formulário de contato

Uma pessoa não envia 20 msg em 1s. Bot sim:

limit_req_zone $binary_remote_addr zone=contact:5m rate=2r/m;

location /contato/enviar {
    limit_req zone=contact burst=1;
    # ...
}

Whitelist de IPs confiáveis

Não quer limitar seu próprio IP (admin) ou o Cloudflare?

geo $limit_ip {
    default 1;
    192.168.1.0/24 0;    # rede local
    173.245.48.0/20 0;   # CF
    103.21.244.0/22 0;   # CF
}

map $limit_ip $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=general:10m rate=10r/s;

Quando $limit_key é vazio, o Nginx não conta aquele IP.

Combinar com Fail2Ban (banimento persistente)

Rate limit devolve 429 mas ainda usa CPU. Fail2Ban bane no firewall:

/etc/fail2ban/jail.d/nginx-req-limit.conf:

[nginx-req-limit]
enabled = true
filter = nginx-req-limit
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /var/log/nginx/*error.log
findtime = 600
bantime = 3600
maxretry = 10

/etc/fail2ban/filter.d/nginx-req-limit.conf:

[Definition]
failregex = limiting requests, excess:.* by zone.*client: <HOST>
ignoreregex =

Reinicie: systemctl restart fail2ban.

Agora IPs que excederem 10x em 10min ficam banidos 1h no firewall (nem chegam ao Nginx).

Testes com ab (Apache Bench)

Simule ataque no seu próprio site:

apt install -y apache2-utils
ab -n 100 -c 20 https://meuservidor.com.br/
  • -n 100 — total de requests
  • -c 20 — 20 concorrentes

Se rate limit está funcionando: você vai ver várias respostas 429.

Detectar problemas

Log de rate limit no Nginx:

tail -f /var/log/nginx/error.log | grep "limiting requests"

Ver contagem de 429 no access log:

grep " 429 " /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

Isso mostra top 20 IPs bloqueados.

Combos que fazem sentido

Loja de VIP simples

/         → general (10r/s)
/checkout → checkout (5r/m)
/api/*    → api (30r/s)

Site com admin WordPress

/           → general
/wp-login   → login (1r/s, burst 3)
/wp-json    → api (30r/s)
/xmlrpc.php → hard block (bloquear 100%, deprecado)

Painel Pterodactyl

/       → general
/api/*  → api (60r/s pra dashboard)
/login  → login (2r/s)

Erros comuns

"Rate limit não funciona"
Confira ordem: limit_req_zone deve estar em http (nginx.conf), limit_req em location.

"Bloqueou meu próprio acesso"
Aumente rate. Ou adicione whitelist (geo).

"Nginx 502 aleatório"
Não relacionado a rate limit (503/429 são de RL). 502 é backend PHP/proxy travando.

"Cloudflare mascara IP real do cliente"
Sem real_ip_header, todos requests aparecem como o IP do Cloudflare. Configure:

real_ip_header CF-Connecting-IP;
set_real_ip_from 173.245.48.0/20;
# ... resto dos ranges de CF

Ganhos práticos

Com config sensata:

  • -70% de tráfego lixo (bots vão bater 429 e desistir)
  • CPU do PHP-FPM ~40% menor (menos requests processadas)
  • Login brute force impossível na prática
  • Você continua com mesma UX (usuários normais nunca batem no limite)

Conclusão

Rate limit no Nginx é must-have pra qualquer site público. Custa 15 minutos pra configurar, protege pra sempre.

Combinado com Fail2Ban vira defesa profissional. Combinado com Cloudflare (Layer 7 na frente) fica praticamente impenetrável.

Nossos VPS-BR rodam Nginx pré-instalado nas imagens Ubuntu.

Links

Compartilhar:

Pronto para hospedar seu próximo projeto?

VPS com painel pré-instalado em 1 clique. Ativação imediata.

Ver planos VPS
⏰ 20% OFF em VPS-BR --:--:-- Ver oferta →