El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Infra

Rate Limiting en las APIs del servidor de MU Online: cómo evitar abuso y ataques

Implementa rate limiting en las APIs del panel y del sitio de tu servidor de MU Online, protegiendo login, ranking y tienda contra fuerza bruta, scraping abusivo y sobrecarga de base de datos.

GA Gabriel · Actualizado el 15 nov 2025 · ⏱ 16 min de lectura
Respuesta rápida

Toda API expuesta por el sitio o el panel de un servidor de MU Online — login, consulta de ranking, canje de código promocional, compra en la tienda de WCoin — es un blanco potencial de abuso: bots intentando adivinar contraseñas, scrapers golpeando el ranking cientos de veces por segundo, o simplem

Toda API expuesta por el sitio o el panel de un servidor de MU Online — login, consulta de ranking, canje de código promocional, compra en la tienda de WCoin — es un blanco potencial de abuso: bots intentando adivinar contraseñas, scrapers golpeando el ranking cientos de veces por segundo, o simplemente un pico de tráfico legítimo que tumba la base de datos. Rate limiting es la técnica de limitar cuántas solicitudes puede hacer un origen en una ventana de tiempo, y es una de las defensas de infraestructura más costo-efectivas que existen: pocas líneas de configuración evitan horas de inestabilidad y una buena fracción de intentos de intrusión. Este tutorial cubre la implementación en dos capas — proxy reverso (Nginx) y aplicación (PHP/Node con Redis) — aplicada a los endpoints más sensibles de un servidor de MU.

Por qué las APIs de servidores de MU son un blanco constante

A diferencia de un sitio institucional común, el sitio de un servidor de MU tiene un incentivo económico directo detrás de varios endpoints: el ranking influye en la reputación y atrae jugadores, el login guarda cuentas con ítems valiosos, y la tienda mueve dinero real vía WCoin. Esto atrae tres tipos de abuso recurrentes: fuerza bruta de login (probar contraseñas en masa), scraping de ranking (bots capturando datos para sitios de terceros o sobrecargando la base de datos), y abuso de canje de código (scripts intentando canjear cupones promocionales en volumen antes de que expiren).

Capas donde aplicar rate limiting

CapaQué controlaGranularidad
Proxy reverso (Nginx/Cloudflare)Volumen bruto de solicitudes por IPGruesa, pero muy barata en recursos
Aplicación (PHP/Node)Reglas de negocio: intentos de login por cuenta, canjes por jugadorFina, consciente del contexto
Base de datosConexiones simultáneas y queries lentasÚltima línea de defensa, ya en modo de emergencia

Ninguna capa sola es suficiente. El proxy detiene el volumen bruto de bots simples; la aplicación detiene abusos más sofisticados que distribuyen solicitudes entre pocas IPs, pero se concentran en una cuenta.

Configurando rate limiting en Nginx

El módulo limit_req de Nginx es la forma más eficiente de frenar el volumen antes de que llegue a PHP-FPM o Node.

# En el bloque 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 solicitudes por minuto por IP en la zona de login.
  • burst=2 nodelay permite un pequeño exceso de tráfico sin encolar la solicitud, algo común en recargas dobles de página.
  • limit_req_status 429 devuelve el código HTTP correcto ("Too Many Requests") en vez del 503 por defecto, facilitando el manejo en el front-end.

Rate limiting en la aplicación con Redis

Para reglas que dependen del contexto de negocio (cuenta específica, no solo IP), implementa el control en la aplicación usando Redis como almacenamiento compartido de los 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 en el 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' => 'Demasiados intentos. Vuelve a intentarlo en unos minutos.']));
}

Este enfoque combina IP y nombre de usuario en la clave, lo cual evita bloquear injustamente a toda una red (NAT de operador móvil, por ejemplo) mientras sigue impidiendo que un solo bot intente contraseñas en masa contra una cuenta específica.

Definiendo límites por endpoint

Cada endpoint tiene un perfil de uso legítimo diferente, y el límite debe reflejarlo:

EndpointLímite sugeridoJustificación
Login del panel5 intentos / 5 min por IP+cuentaEl uso legítimo rara vez excede 2-3 intentos
Canje de código promocional10 intentos / 10 min por cuentaEvita la fuerza bruta de códigos cortos
Consulta de ranking (API pública)30 req/min por IPSoporta la actualización automática de la página sin abrir la puerta a scraping pesado
Compra en la tienda (WCoin)20 req/min por cuentaLas transacciones reales rara vez exceden este volumen por usuario
Registro de nueva cuenta3 registros / hora por IPLimita la creación masiva de cuentas para farm/bot

Respondiendo correctamente cuando se excede el límite

Devolver solo un error genérico frustra al jugador legítimo que solo tuvo mala suerte al alcanzar el tope. La respuesta ideal incluye el encabezado Retry-After y un mensaje claro:

<?php
http_response_code(429);
header('Retry-After: 60');
echo json_encode([
    'erro' => 'rate_limit_excedido',
    'mensagem' => 'Alcanzaste el límite de intentos. Vuelve a intentarlo en 60 segundos.'
]);

En el front-end, captura el estado 429 y muestra una cuenta regresiva en lugar de dejar que el usuario siga presionando el botón, lo cual solo prolongaría el bloqueo.

Rate limiting específico para scraping de ranking

Los sitios de ranking de terceros (agregadores de servidores de MU) suelen hacer scraping de tu ranking con alta frecuencia para mantener sus propios datos actualizados. Si esto sobrecarga tu base de datos, considera: (1) publicar un endpoint de API oficial con caché de algunos minutos, servido por un job programado en vez de una consulta directa a la base de datos en cada solicitud, y (2) aplicar un límite más generoso, pero real, en ese endpoint público, dejando claro en los términos del sitio que el scraping fuera de esa API está prohibido.

Monitoreo y ajuste fino

Un rate limiting mal calibrado el primer día es normal — el objetivo es registrar y ajustar. Mantén un log de los rechazos (429) con IP, endpoint y timestamp, y revísalo semanalmente en las primeras semanas después del lanzamiento:

# Ejemplo de conteo de rechazos por endpoint en los logs de Nginx
grep ' 429 ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn

Si un endpoint específico genera muchos rechazos de IPs distintas y sin un patrón de abuso aparente, el límite probablemente está calibrado por debajo del uso legítimo real — súbelo. Si la mayoría de los rechazos provienen de pocas IPs repetidas, el límite está funcionando como se esperaba.

Rate limiting versus CAPTCHA y otras defensas complementarias

El rate limiting no reemplaza al CAPTCHA en formularios de registro y recuperación de contraseña — reduce el volumen de intentos, pero no distingue entre humano y bot dentro del límite permitido. Para endpoints de altísimo riesgo (registro de cuenta, recuperación de contraseña), combina rate limiting con CAPTCHA (reCAPTCHA o hCaptcha) y, cuando tenga sentido, con verificación de correo antes de habilitar totalmente la cuenta nueva.

Errores comunes y soluciones

SíntomaCausa probableSolución
Jugadores legítimos bloqueados en el loginLímite calibrado solo por IP, sin considerar NAT compartidoCombina IP + cuenta en la clave del rate limit
El rate limiting no reduce los ataques de fuerza brutaLímite aplicado solo en la aplicación, sin proxy al frenteAgrega limit_req en Nginx como primera capa
Página de ranking lenta incluso con rate limitingConsulta directa a la base de datos en cada solicitud, sin cachéSirve el ranking desde una caché actualizada por un job programado
Un error genérico confunde al jugadorRespuesta 429 sin Retry-After ni mensaje claroIncluye el encabezado Retry-After y un mensaje específico en el JSON de error
Los contadores de rate limit "desaparecen" al reiniciar el servidorContadores en memoria local en vez de RedisUsa almacenamiento persistente/compartido (Redis) para los contadores

Lista de verificación de implementación de rate limiting

  • limit_req configurado en Nginx para login, ranking y endpoints de tienda.
  • Reglas de negocio (IP + cuenta) implementadas en la aplicación vía Redis o equivalente.
  • Límites por endpoint definidos según el volumen legítimo esperado.
  • Respuesta 429 con Retry-After y mensaje claro implementada.
  • CAPTCHA combinado en registro y recuperación de contraseña.
  • Endpoint de ranking con caché programada, reduciendo la carga en la base de datos.
  • Logs de rechazo monitoreados y límites ajustados en las primeras semanas.

Con el rate limiting en funcionamiento, el siguiente paso natural es revisar las demás capas de seguridad de las APIs del panel — validación de entrada, protección CSRF y autenticación — para que el servidor tenga una defensa en profundidad real. Si la infraestructura todavía está en fase de planificación, vale la pena revisar la guía de creación de servidor de MU Online para alinear estas prácticas desde la fundación. </content>

Preguntas frecuentes

¿Rate limiting es lo mismo que un firewall?

No. Un firewall bloquea con base en reglas de red (IP, puerto, protocolo); el rate limiting controla la frecuencia de solicitudes legítimas a un endpoint específico, sin importar si el origen es 'confiable' o no. Ambos se complementan.

¿Dónde aplico rate limiting: en Nginx, en la aplicación o en ambos?

Lo ideal es en ambos. Nginx (o un proxy reverso equivalente) filtra el volumen bruto antes de que llegue a la aplicación, ahorrando recursos; la aplicación aplica reglas más finas, como un límite por cuenta de usuario en vez de solo por IP, algo que el proxy por sí solo no puede ver.

¿El rate limiting puede bloquear a jugadores legítimos?

Puede, si se configura de forma muy agresiva o sin considerar IPs compartidas (redes móviles, NAT de proveedor). Por eso es importante limitar por combinación de IP + cuenta cuando sea posible, y siempre devolver un mensaje claro en vez de simplemente bloquear la página.

¿Necesito Redis para implementar rate limiting?

No es obligatorio, pero es la opción más robusta cuando tienes más de un servidor web detrás de un balanceador, porque el contador de solicitudes necesita compartirse entre instancias. Para un solo servidor, una caché en archivo o en memoria de la aplicación ya resuelve la mayoría de los casos.

¿Qué límite de solicitudes es razonable para la página de login?

Una referencia común es 5 intentos por IP cada 5 minutos para el login, con bloqueo progresivo (backoff) en intentos posteriores. Ajusta según el volumen real de jugadores de tu servidor y monitorea falsos positivos en las primeras semanas.

GA
Editor de guías y builds

Gabriel cubre gameplay, builds de clases, PvP y progresión. Prueba cada estrategia en un servidor antes de publicar.

Sigue leyendo

Artículos relacionados