Una página de acceso sin límite se puede probar tan rápido como permita la red. Un límite no vuelve fuerte una contraseña débil; hace que adivinarla lleve más tiempo del que nadie va a esperar, que en la práctica es lo mismo.

En el servidor web

limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

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

Cinco por minuto con una ráfaga de tres: nadie escribe más rápido, y una máquina queda parada en seco. Hágalo en el servidor, no en la aplicación: una petición rechazada aquí no llega nunca a PHP.

Obsérvelo antes de imponerlo

grep -c "limiting requests" /var/log/nginx/error.log
Un límite puesto demasiado bajo deja fuera a personas de verdad, y esas no lo denuncian: se van. Observe el registro una semana con una tasa generosa antes de apretar.

Bloquee a los reincidentes

# /etc/fail2ban/jail.local
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 3600

Lo que un límite no hace

  • No detiene un intento repartido entre mil direcciones, cada una probando dos veces.
  • No sirve si la contraseña ya se filtró: al atacante le basta un intento.
El doble factor vuelve el límite casi innecesario, y el límite no vuelve innecesario el doble factor. Si solo va a hacer una cosa, haga el doble factor.