NetGoos
WordPress 08 de abril de 2026 · 6 min de lectura

Cómo bloquear ataques de fuerza bruta a WordPress sin perder rendimiento

Cómo bloquear ataques de fuerza bruta a WordPress sin perder rendimiento

TL;DR

  • El error más común: instalar un plugin de seguridad pesado que procesa el bloqueo dentro de WordPress. El bot sigue consumiendo CPU y memoria aunque sea bloqueado.
  • La solución correcta es bloquear en la capa exterior: Cloudflare antes de que llegue al servidor, o Nginx antes de que llegue a PHP.
  • Bloquear /xmlrpc.php completamente si no lo usas activamente es una de las acciones de mayor impacto inmediato para reducir el ruido de ataques.
  • Cloudflare gratuito con 5 reglas de firewall es suficiente para proteger el login de WordPress en la mayoría de sitios de pymes.
  • Los plugins de seguridad (Wordfence) tienen sentido como capa de monitorización e integridad de ficheros, no como primera línea de bloqueo de volumen.

El error más habitual al proteger WordPress contra ataques de fuerza bruta es instalar un plugin de seguridad pesado que procesa el bloqueo dentro de WordPress. El bot sigue llegando hasta PHP, cargando WordPress, ejecutando el plugin y consumiendo CPU y memoria del servidor, aunque el plugin lo bloquee al final del proceso. Si recibes miles de intentos de login simultáneos (algo habitual para cualquier WordPress público), el servidor se satura antes de que el plugin tenga oportunidad de bloquear nada. El resultado es un sitio lento o inaccesible mientras los bots siguen intentándolo.

La solución está en bloquear en la capa correcta: antes de que la petición llegue a WordPress. Esta guía describe las tres capas donde puede bloquearse un ataque de fuerza bruta, de mayor a menor eficiencia, con la configuración específica para cada una.

1. El coste real del bloqueo por capa

La eficiencia de cada capa de bloqueo se mide en recursos que consume el servidor por cada petición bloqueada. Cuanto más tarde se bloquea en la pila, más recursos se consumen antes de que el bloqueo ocurra:

  • CDN/WAF externo (Cloudflare, Sucuri): el bloqueo ocurre antes de que la petición salga de la red del CDN. El servidor de origen ni ve la petición. Coste por petición bloqueada: prácticamente cero para tu servidor. Ideal para volúmenes altos de ataque.
  • Servidor web (Nginx, Apache): la petición llega al servidor pero se bloquea antes de que PHP se cargue. No se ejecuta WordPress, no hay consulta a la base de datos. Coste bajo por petición bloqueada. Eficiente para volúmenes medios.
  • PHP / plugin de WordPress: la petición llega hasta PHP, WordPress carga todos sus plugins y temas, la base de datos es consultada, y entonces el plugin bloquea. Coste alto por petición bloqueada. Solo adecuado para volúmenes muy bajos de ataque.

Para un WordPress en un VPS de gama media (2 vCPU, 4 GB RAM), recibir 500 peticiones simultáneas a /wp-login.php procesadas todas por PHP puede llevar el servidor al límite de capacidad o saturarlo. Las mismas 500 peticiones bloqueadas por Cloudflare no tienen ningún impacto en el servidor. Este es el punto clave que determina qué configuración elegir según las características del hosting.

2. Bloqueo a nivel de servidor web: Nginx y Apache

Para sitios en servidores propios (VPS, servidor dedicado) con acceso a la configuración del servidor web, el bloqueo a nivel de Nginx o Apache es la primera línea de defensa que no requiere un CDN externo.

En Nginx, la directiva limit_req_zone permite limitar el número de peticiones por IP en un periodo de tiempo. La configuración básica para proteger /wp-login.php:

# En el bloque http de nginx.conf:

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

# En el server del sitio:

location = /wp-login.php {

    limit_req zone=login burst=3 nodelay;

    fastcgi_pass unix:/run/php/php8.1-fpm.sock;

}

# Bloquear xmlrpc.php completamente:

location = /xmlrpc.php {

    deny all;

    return 403;

}

Esta configuración permite 5 peticiones por minuto a /wp-login.php por IP, con una ráfaga de 3 antes de empezar a rechazar. Un usuario legítimo que falla su contraseña y lo reintenta dos o tres veces nunca alcanza ese límite. Un bot que intenta cientos de passwords por minuto se bloquea en el segundo intento, con un coste de procesamiento para el servidor de unos pocos microsegundos por petición rechazada (versus el coste de carga completa de WordPress).

En Apache, el equivalente usa mod_evasive o mod_qos para rate limiting, o simplemente LimitRequestBody y Order deny,allow para bloqueo de IPs específicas en .htaccess. Apache tiene menos granularidad para rate limiting que Nginx, por lo que para hosting en Apache la combinación con Cloudflare suele ser más efectiva que solo configuración de Apache.

3. Cloudflare: la solución más escalable para cualquier hosting

Con Cloudflare delante de WordPress, el bloqueo ocurre antes de que la petición salga de la red de Cloudflare y llegue a tu servidor. Esto funciona independientemente del tipo de hosting: hosting compartido, VPS, servidor dedicado. El servidor de origen queda protegido sin tocar su configuración.

Las reglas de firewall de Cloudflare para WordPress (plan gratuito, hasta 5 reglas):

  • Regla 1 - Bloquear acceso a /xmlrpc.php: condición: http.request.uri.path eq "/xmlrpc.php" → acción: Block. Elimina el vector de ataque amplificado de xmlrpc de forma inmediata.
  • Regla 2 - Limitar /wp-login.php a IPs de la empresa: condición: http.request.uri.path eq "/wp-login.php" AND not ip.src in {IP_oficina, IP_casa_admin} → acción: Challenge o Block. Significa que el panel de login solo es accesible desde las IPs autorizadas.
  • Regla 3 - Rate limiting en /wp-login.php para IPs no bloqueadas: si no quieres restringir por IP (porque el admin accede desde ubicaciones variables), una regla de rate limiting que bloquea temporalmente una IP tras 10 intentos en 2 minutos.
  • Regla 4 - Bloquear acceso a /wp-admin desde IPs que no son de la empresa: excepto /wp-admin/admin-ajax.php que necesita ser accesible para el funcionamiento de algunos plugins y temas.

El plan gratuito de Cloudflare permite crear hasta 5 reglas de firewall personalizadas, suficientes para cubrir los vectores principales. El plan Pro (25 $/mes) añade el WAF gestionado con conjuntos de reglas para WordPress (OWASP Core Rule Set, WordPress Managed Rules) que detectan patrones de ataques más sofisticados como inyección SQL en parámetros de plugins o intentos de path traversal. Para sitios de empresa con datos sensibles o ecommerce, el plan Pro es la recomendación. La protección de WordPress a nivel de servidor complementa la protección del panel de administración cubierta en el artículo sobre cómo proteger WP-admin contra bots.

4. Comparativa de configuraciones de protección

Configuración Capa de bloqueo Impacto en rendimiento bajo ataque Coste Requiere acceso al servidor
Solo plugin (Wordfence) PHP / WordPress Alto (satura el servidor) Gratis / 99 $/año No
Nginx rate limiting Servidor web Bajo (sin carga PHP) Gratis Sí (SSH)
Cloudflare gratuito + reglas CDN (antes del servidor) Nulo (server no ve la petición) Gratis No
Cloudflare Pro + WAF CDN + WAF gestionado Nulo 25 $/mes No
Cloudflare + Nginx + Wordfence 3 capas complementarias Mínimo Gratis o 25 $/mes + tiempo config Sí (para Nginx)

5. Cuándo sí tiene sentido un plugin de seguridad

Los plugins de seguridad como Wordfence, iThemes Security o Solid Security tienen sentido como capa de detección y auditoría, no como primera línea de bloqueo de volumen. Lo que hacen bien que las capas externas no pueden hacer:

Monitorización de integridad de ficheros: detectan cuando un fichero del core de WordPress, de un tema o de un plugin ha sido modificado comparándolo con los hashes originales del repositorio. Si alguien logra acceder y modifica un fichero PHP para inyectar código, el plugin lo detecta aunque Cloudflare y Nginx no hayan visto nada sospechoso en las peticiones.

Alertas de plugins vulnerables: notifican cuando hay una actualización de seguridad pendiente en algún plugin instalado, incluyendo plugins fuera del repositorio de WordPress.org que Cloudflare no puede monitorizar. Esta función es especialmente valiosa para detectar plugins abandonados con vulnerabilidades conocidas. El artículo sobre vulnerabilidades de plugins abandonados en WordPress describe el riesgo específico de estos componentes.

WAF a nivel de aplicación: aunque menos eficiente que el WAF de Cloudflare en términos de rendimiento, el WAF de Wordfence puede detectar ciertos ataques que ocurren dentro de sesiones de usuario autenticado (ataques a través de formularios de administración, CSRF en funciones de admin) que Cloudflare no ve porque el tráfico está autenticado y parece legítimo.

La configuración óptima combina Cloudflare o Nginx como primera capa de bloqueo de volumen (elimina el ruido de bots antes de que lleguen al servidor) y Wordfence en modo ligero como capa de monitorización de integridad y alertas de vulnerabilidades. Con Cloudflare bien configurado, las reglas de firewall de Wordfence pueden desactivarse para reducir el impacto en rendimiento, manteniendo activa la monitorización de ficheros y las alertas de seguridad.

6. Caso real: servidor saturado por ataques de fuerza bruta

Una empresa de servicios jurídicos de Bilbao tenía su WordPress corporativo en un VPS compartido con Wordfence gratuito instalado. El sitio era básicamente un escaparate corporativo con algunos formularios de contacto. Un día de marzo, el sitio empezó a cargar en más de 20 segundos y a devolver errores 502 esporádicamente.

El análisis del técnico IT reveló que el sitio estaba recibiendo aproximadamente 3.000 intentos de login por hora en /wp-login.php, distribuidos desde unos 200 rangos de IP distintos. Wordfence estaba bloqueando la mayoría, pero para hacerlo cargaba WordPress completo en cada petición: 3.000 cargas de PHP y WordPress por hora, más las del tráfico legítimo. El VPS de 2 vCPU y 2 GB RAM estaba al 100% de CPU de forma sostenida.

La solución implementada en tres horas: activar Cloudflare (cambio de DNS, 5 minutos), crear una regla de firewall en Cloudflare que bloquea /xmlrpc.php completamente y otra que añade un JavaScript Challenge a /wp-login.php para cualquier IP no en la lista blanca, y configurar rate limiting en Nginx para /wp-login.php como segunda capa. El resultado inmediato: el servidor bajó al 5% de uso de CPU, el sitio cargó en menos de 2 segundos, y el número de peticiones de fuerza bruta que llegaban al servidor cayó de 3.000/hora a 0. Wordfence se dejó instalado en modo monitorización de ficheros únicamente, sin WAF activo, para mantener las alertas de integridad sin el coste de rendimiento. Para sitios con más funcionalidad web, el mantenimiento de WordPress para empresas incluye esta configuración de protección multicapa como parte del servicio.

7. Medidas adicionales de endurecimiento del login

Más allá del bloqueo de fuerza bruta, hay medidas de configuración que reducen significativamente la superficie de ataque del panel de login:

Eliminar la enumeración de usuarios: WordPress por defecto permite descubrir los nombres de usuario mediante la URL /?author=1, /?author=2, etc. Si el atacante conoce el nombre de usuario del administrador, la mitad del trabajo de fuerza bruta está hecho. La enumeración puede bloquearse con una línea en functions.php del tema o con un plugin como Perfmatters.

Activar MFA en el panel de WordPress: plugins como WP 2FA añaden autenticación de doble factor al login de WordPress. Incluso si el bot adivina la contraseña, sin el segundo factor no puede completar el login. Para los administradores del sitio, MFA en WordPress debe ser obligatorio, no opcional.

Cambiar la URL del panel de login: el plugin WPS Hide Login cambia /wp-login.php por cualquier URL personalizada que elijas. Los bots que simplemente prueban la URL estándar no encuentran el formulario. No es seguridad robusta (la URL puede descubrirse por otras vías), pero elimina el ruido de ataques automatizados que no verifican primero si el path existe. Combinar con el bloqueo de la URL estándar en Nginx o Cloudflare (devolver 404 para /wp-login.php) refuerza el efecto.

Deshabilitar XML-RPC si no se usa: la regla más efectiva por su simplicidad. Si ninguna integración activa de tu WordPress requiere xmlrpc.php (verificar con el proveedor de cualquier plugin que use comunicación remota), bloquearlo completamente en Nginx o Cloudflare elimina un vector de ataque masivo con cero impacto en la funcionalidad del sitio. Para los sitios que usan monitorización de seguridad continua, la verificación del estado de estas configuraciones forma parte de las comprobaciones periódicas del servicio.

Por dónde empezar mañana

  1. Activa Cloudflare y cambia los DNS del dominio a los de Cloudflare: el proceso toma 5-30 minutos dependiendo del TTL de los DNS actuales. Con Cloudflare activo, tienes acceso inmediato a la capa de protección más eficiente sin tocar la configuración del servidor. El plan gratuito es suficiente para empezar.
  2. Crea la primera regla de Cloudflare: bloquear /xmlrpc.php completamente. Es la acción de mayor impacto inmediato con el menor esfuerzo. Si no usas Jetpack en modo clásico ni apps móviles antiguas de WordPress, xmlrpc.php puede bloquearse sin consecuencias.
  3. Verifica qué usuarios tienen acceso de administrador al WordPress: ve a Usuarios en el panel de WordPress y filtra por rol "Administrador". Si hay cuentas de administrador de personas que ya no están en la empresa o que no necesitan ese nivel de acceso, cambiar el rol o eliminar la cuenta reduce la superficie de ataque independientemente de cualquier configuración técnica.

Preguntas frecuentes

¿Cuál es la diferencia entre un plugin de seguridad y Cloudflare para proteger el login?

El plugin bloquea después de que la petición llegó a PHP y WordPress: consume recursos por cada intento. Cloudflare bloquea antes de que llegue al servidor: coste prácticamente cero para tu infraestructura. Para ataques de alto volumen, el plugin se satura junto con el servidor; Cloudflare no.

¿Es necesario bloquear xmlrpc.php en WordPress?

Para la mayoría de instalaciones sí. xmlrpc.php es explotado por bots masivamente para fuerza bruta y DDoS amplificado. Si no usas Jetpack en modo clásico ni apps móviles antiguas de WordPress, bloquearlo no tiene consecuencias funcionales y elimina un vector de ataque significativo.

¿Qué hace limit_req_zone en Nginx para WordPress?

Define una zona de rate limiting por IP y la aplica en la URL de login. Con rate=5r/m y burst=3, permite 5 peticiones por minuto por IP con ráfaga de 3. Los intentos que exceden ese límite reciben error 503 sin que PHP se ejecute, con coste mínimo para el servidor.

¿Cambiar la URL del panel de WordPress ayuda realmente?

Elimina los ataques de bots que prueban /wp-login.php sin verificar si existe. Es seguridad por oscuridad: no es impenetrable, pero reduce el ruido de ataques automatizados de bajo esfuerzo. Complementaria, no sustitutiva, de rate limiting y Cloudflare.

¿El plan gratuito de Cloudflare es suficiente para proteger el login de WordPress?

Para la mayoría de sitios de pymes sí. Hasta 5 reglas de firewall personalizadas son suficientes para bloquear xmlrpc.php, limitar el acceso a wp-login.php desde IPs no autorizadas y añadir rate limiting básico. El plan Pro añade WAF gestionado con reglas específicas para WordPress.

¿Wordfence gratuito o de pago vale la pena?

Wordfence gratuito ofrece monitorización de integridad y alertas con 30 días de retraso en reglas de firewall. Si ya tienes Cloudflare bien configurado, la versión gratuita como capa de monitorización secundaria es razonable. Wordfence Premium añade actualización de reglas en tiempo real, relevante para vulnerabilidades activamente explotadas.

¿Cuántos intentos de login por minuto son normales en un WordPress?

Un usuario legítimo raramente hace más de 1-2 intentos por minuto. Configurar rate limiting a 5 peticiones por minuto es seguro para todos los usuarios reales y efectivo contra bots no sofisticados. Para ataques distribuidos desde muchas IPs, se necesita detección de comportamiento adicional.