O maior portal de MU Online do Brasil — desde 2003
Tutorial Avançado Infra

Rate Limiting nas APIs do servidor de MU Online: como evitar abuso e ataques

Implemente rate limiting nas APIs do painel e do site do seu servidor de MU Online, protegendo login, ranking e loja contra brute-force, scraping abusivo e sobrecarga de banco de dados.

GA Gabriel · Atualizado em 15 nov 2025 · ⏱ 16 min de leitura
Resposta rápida

Toda API exposta pelo site ou painel de um servidor de MU Online — login, consulta de ranking, resgate de código promocional, compra na loja de WCoin — é um alvo em potencial para abuso: bots tentando adivinhar senhas, scrapers batendo no ranking centenas de vezes por segundo, ou simplesmente um pic

Toda API exposta pelo site ou painel de um servidor de MU Online — login, consulta de ranking, resgate de código promocional, compra na loja de WCoin — é um alvo em potencial para abuso: bots tentando adivinhar senhas, scrapers batendo no ranking centenas de vezes por segundo, ou simplesmente um pico de tráfego legítimo que derruba o banco de dados. Rate limiting é a técnica de limitar quantas requisições uma origem pode fazer em uma janela de tempo, e é uma das defesas de infraestrutura mais custo-benefício que existem: poucas linhas de configuração evitam horas de instabilidade e uma boa fração de tentativas de invasão. Este tutorial cobre a implementação em duas camadas — proxy reverso (Nginx) e aplicação (PHP/Node com Redis) — aplicada aos endpoints mais sensíveis de um servidor de MU.

Por que APIs de servidor de MU são alvo constante

Diferente de um site institucional comum, o site de um servidor de MU tem incentivo econômico direto por trás de vários endpoints: ranking influencia reputação e atrai jogadores, login guarda contas com itens valiosos, e a loja movimenta dinheiro real via WCoin. Isso atrai três tipos de abuso recorrentes: brute-force de login (testar senhas em massa), scraping de ranking (bots capturando dados para sites de terceiros ou sobrecarregando o banco), e abuso de resgate de código (scripts tentando resgatar cupons promocionais em volume antes que expirem).

Camadas onde aplicar rate limiting

CamadaO que controlaGranularidade
Proxy reverso (Nginx/Cloudflare)Volume bruto de requisições por IPGrosseira, mas muito barata em recursos
Aplicação (PHP/Node)Regras de negócio: tentativas de login por conta, resgates por jogadorFina, ciente do contexto
Banco de dadosConexões simultâneas e queries lentasÚltima linha de defesa, já em modo de emergência

Nenhuma camada sozinha é suficiente. O proxy pega o volume bruto de bots simples; a aplicação pega abuso mais sofisticado que distribui requisições entre poucos IPs, mas concentra em uma conta.

Configurando rate limiting no Nginx

O módulo limit_req do Nginx é a forma mais eficiente de barrar volume antes que ele chegue ao PHP-FPM ou Node.

# No bloco http {}
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=ranking:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=geral:10m rate=60r/m;

server {
    location /painel/login.php {
        limit_req zone=login burst=2 nodelay;
        limit_req_status 429;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    location /api/ranking {
        limit_req zone=ranking burst=10 nodelay;
        limit_req_status 429;
        proxy_pass http://127.0.0.1:3000;
    }

    location / {
        limit_req zone=geral burst=20 nodelay;
    }
}
  • rate=5r/m limita a 5 requisições por minuto por IP na zona de login.
  • burst=2 nodelay permite um pequeno estouro de tráfego sem enfileirar a requisição, comum em recarregamentos duplos de página.
  • limit_req_status 429 devolve o código HTTP correto ("Too Many Requests") em vez do padrão 503, facilitando o tratamento no front-end.

Rate limiting na aplicação com Redis

Para regras que dependem de contexto de negócio (conta específica, não apenas IP), implemente o controle na aplicação usando Redis como armazenamento compartilhado dos contadores.

<?php
function verificarRateLimit(Redis $redis, string $chave, int $limite, int $janelaSegundos): bool {
    $atual = $redis->incr($chave);
    if ($atual === 1) {
        $redis->expire($chave, $janelaSegundos);
    }
    return $atual <= $limite;
}

// Uso no endpoint de login
$chave = 'login_tentativas:' . $_SERVER['REMOTE_ADDR'] . ':' . $_POST['usuario'];
if (!verificarRateLimit($redis, $chave, 5, 300)) {
    http_response_code(429);
    die(json_encode(['erro' => 'Muitas tentativas. Tente novamente em alguns minutos.']));
}

Essa abordagem combina IP e nome de usuário na chave, o que evita bloquear injustamente uma rede inteira (NAT de operadora móvel, por exemplo) enquanto ainda impede que um único bot tente senhas em massa contra uma conta específica.

Definindo limites por endpoint

Cada endpoint tem um perfil de uso legítimo diferente, e o limite deve refletir isso:

EndpointLimite sugeridoJustificativa
Login do painel5 tentativas / 5 min por IP+contaUso legítimo raramente excede 2-3 tentativas
Resgate de código promocional10 tentativas / 10 min por contaEvita brute-force de códigos curtos
Consulta de ranking (API pública)30 req/min por IPSuporta atualização automática de página sem abrir brecha para scraping pesado
Compra na loja (WCoin)20 req/min por contaTransações reais raramente excedem esse volume por usuário
Cadastro de nova conta3 cadastros / hora por IPLimita criação em massa de contas para farm/bot

Respondendo corretamente quando o limite é excedido

Devolver apenas um erro genérico frustra o jogador legítimo que só teve azar de atingir o teto. A resposta ideal inclui o cabeçalho Retry-After e uma mensagem clara:

<?php
http_response_code(429);
header('Retry-After: 60');
echo json_encode([
    'erro' => 'rate_limit_excedido',
    'mensagem' => 'Você atingiu o limite de tentativas. Tente novamente em 60 segundos.'
]);

No front-end, capture o status 429 e exiba uma contagem regressiva em vez de deixar o usuário martelar o botão de novo, o que só prolongaria o bloqueio.

Rate limiting específico para scraping de ranking

Sites de ranking de terceiros (agregadores de servidores de MU) costumam fazer scraping do seu ranking com alta frequência para manter seus próprios dados atualizados. Se isso sobrecarregar seu banco, considere: (1) publicar um endpoint de API oficial com cache de alguns minutos, servido por um job agendado em vez de consulta direta ao banco a cada requisição, e (2) aplicar um limite mais generoso, porém real, nesse endpoint público, deixando claro nos termos do site que scraping fora dessa API é proibido.

Monitoramento e ajuste fino

Rate limiting mal calibrado no primeiro dia é normal — o objetivo é registrar e ajustar. Mantenha um log das rejeições (429) com IP, endpoint e timestamp, e revise semanalmente nas primeiras semanas após o lançamento:

# Exemplo de contagem de rejeições por endpoint nos logs do Nginx
grep ' 429 ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn

Se um endpoint específico gera muitas rejeições de IPs distintos e sem padrão de abuso aparente, o limite provavelmente está calibrado abaixo do uso legítimo real — suba-o. Se a maioria das rejeições vem de poucos IPs repetidos, o limite está funcionando como esperado.

Rate limiting versus CAPTCHA e outras defesas complementares

Rate limiting não substitui CAPTCHA em formulários de cadastro e recuperação de senha — ele reduz o volume de tentativas, mas não distingue humano de bot dentro do limite permitido. Para endpoints de altíssimo risco (cadastro de conta, recuperação de senha), combine rate limiting com CAPTCHA (reCAPTCHA ou hCaptcha) e, quando fizer sentido, com verificação de e-mail antes de liberar totalmente a conta nova.

Erros comuns e soluções

SintomaCausa provávelSolução
Jogadores legítimos bloqueados no loginLimite calibrado só por IP, sem considerar NAT compartilhadoCombine IP + conta na chave do rate limit
Rate limiting não reduz ataques de brute-forceLimite aplicado só na aplicação, sem proxy na frenteAdicione limit_req no Nginx como primeira camada
Página de ranking lenta mesmo com rate limitingConsulta direta ao banco a cada requisição, sem cacheSirva o ranking a partir de cache atualizado por job agendado
Erro genérico confunde o jogadorResposta 429 sem Retry-After nem mensagem claraInclua cabeçalho Retry-After e mensagem específica no JSON de erro
Contadores de rate limit "somem" após reiniciar o servidorContadores em memória local em vez de RedisUse armazenamento persistente/compartilhado (Redis) para os contadores

Checklist de implementação de rate limiting

  • limit_req configurado no Nginx para login, ranking e endpoints de loja.
  • Regras de negócio (IP + conta) implementadas na aplicação via Redis ou equivalente.
  • Limites por endpoint definidos com base no volume legítimo esperado.
  • Resposta 429 com Retry-After e mensagem clara implementada.
  • CAPTCHA combinado em cadastro e recuperação de senha.
  • Endpoint de ranking com cache agendado, reduzindo carga no banco.
  • Logs de rejeição monitorados e limites ajustados nas primeiras semanas.

Com o rate limiting no ar, o próximo passo natural é revisar as demais camadas de segurança das APIs do painel — validação de entrada, proteção CSRF e autenticação — para que o servidor tenha uma defesa em profundidade real. Se a infraestrutura ainda está em fase de planejamento, vale revisar o guia de criação de servidor de MU Online para alinhar essas práticas desde a fundação. </content>

Perguntas frequentes

Rate limiting é a mesma coisa que firewall?

Não. Um firewall bloqueia com base em regras de rede (IP, porta, protocolo); rate limiting controla a frequência de requisições legítimas a um endpoint específico, independente da origem ser 'confiável' ou não. Os dois se complementam.

Onde aplico rate limiting: no Nginx, na aplicação ou nos dois?

O ideal são os dois. O Nginx (ou proxy reverso equivalente) filtra o volume bruto antes de chegar à aplicação, economizando recursos; a aplicação aplica regras mais finas, como limite por conta de usuário em vez de só por IP, o que o proxy sozinho não enxerga.

Rate limiting pode bloquear jogadores legítimos?

Pode, se configurado de forma muito agressiva ou sem considerar IPs compartilhados (redes móveis, NAT de provedor). Por isso é importante limitar por combinação de IP + conta quando possível, e sempre devolver uma mensagem clara em vez de simplesmente travar a página.

Preciso de Redis para implementar rate limiting?

Não é obrigatório, mas é a opção mais robusta quando você tem mais de um servidor web atrás de um balanceador, porque o contador de requisições precisa ser compartilhado entre instâncias. Para um único servidor, cache em arquivo ou em memória da aplicação já resolve a maioria dos casos.

Qual limite de requisições é razoável para a página de login?

Uma referência comum é 5 tentativas por IP a cada 5 minutos para login, com bloqueio progressivo (backoff) em tentativas subsequentes. Ajuste conforme o volume real de jogadores do seu servidor e monitore falsos positivos nas primeiras semanas.

GA
Editor de guias e builds

Gabriel cobre gameplay, builds de classes, PvP e progressão. Testa cada estratégia em servidor antes de publicar.

Continue lendo

Artigos relacionados