
Un plugin de seguridad funciona dentro de WordPress: para revisar una petición, PHP y WordPress ya tuvieron que cargarse. Eso consume recursos y, si la petición es un ataque, ya llegó bastante lejos.
Un cortafuegos en el servidor o en Cloudflare actúa antes. Las peticiones maliciosas se rechazan en milisegundos, sin tocar PHP ni la base de datos. La combinación de las dos capas es lo que usan los sitios bien protegidos.
Capa 1: reglas en el .htaccess
Estas reglas van en el .htaccess de la raíz, arriba del bloque # BEGIN WordPress. Son para Apache y LiteSpeed (lo habitual en hostings con cPanel).
# --- Cortafuegos básico (Curso WordPress) ---
# 1. Archivos que nunca deben ser públicos
<FilesMatch "^(wp-config\.php|readme\.html|license\.txt|xmlrpc\.php|\.user\.ini|php\.ini|error_log)$">
Require all denied
</FilesMatch>
# 2. Copias y respaldos olvidados
<FilesMatch "\.(bak|backup|old|orig|sql|sql\.gz|zip|tar|tar\.gz|log|swp|dist)$">
Require all denied
</FilesMatch>
# 3. Archivos y carpetas ocultos (.git, .env, .DS_Store), excepto .well-known
RedirectMatch 403 /\.(?!well-known)
<IfModule mod_rewrite.c>
RewriteEngine On
# 4. Peticiones con métodos que tu sitio no usa
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK|DEBUG) [NC]
RewriteRule .* - [F,L]
# 5. Intentos típicos de inyección en la URL
RewriteCond %{QUERY_STRING} (\.\./|\.\.%2f|etc/passwd|proc/self|base64_encode|GLOBALS\[|_REQUEST\[) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (union.*select|concat\(|information_schema) [NC]
RewriteRule .* - [F,L]
</IfModule>
Sobre la regla 1: bloquea xmlrpc.php. Si usas la app móvil de WordPress o un servicio que lo necesite, quítalo de esa línea. Y sobre la regla 2: si tienes descargas legítimas en .zip (por ejemplo, productos digitales), quita zip de la lista o la regla las bloqueará.
Capa 2: Cloudflare WAF
Si tu sitio está detrás de Cloudflare (incluso en el plan gratuito), ve a Seguridad → Reglas de WAF → Reglas personalizadas. El plan gratuito permite varias reglas; estas son las más útiles para WordPress:
Regla 1. Proteger el acceso (acción: Desafío administrado):
(http.request.uri.path eq "/wp-login.php")
or (http.request.uri.path contains "/wp-admin/" and not http.request.uri.path contains "/wp-admin/admin-ajax.php")
Si siempre administras desde Chile, agrega and ip.geoip.country ne "CL" al final para que a ti no te pida nada.
Regla 2. Bloquear rutas que no existen en tu sitio (acción: Bloquear):
(http.request.uri.path contains "/.env")
or (http.request.uri.path contains "/.git")
or (http.request.uri.path contains "/phpmyadmin")
or (http.request.uri.path contains "/vendor/phpunit")
or (http.request.uri.path eq "/xmlrpc.php")
Regla 3. Desafiar a quien se presenta como un robot conocido pero no lo es (acción: Bloquear):
(http.user_agent contains "Googlebot" and not cf.client.bot)
cf.client.bot es verdadero solo para robots verificados por Cloudflare. Un «Googlebot» que no lo es, es falso.
En Seguridad → Bots, activa también Bot Fight Mode si tu plan lo ofrece. Pero ojo: puede bloquear peticiones legítimas de tu propio servidor (WP-Cron, el importador, servicios de pago que avisan a tu tienda). Si algo deja de funcionar después de activarlo, es lo primero que debes revisar.
Probar sin bloquearte
- Antes de tocar el
.htaccess, descarga una copia. Si el sitio da error 500, vuelve a subirla. - Después de cada cambio, comprueba que puedes entrar al escritorio, que la portada carga y que los formularios funcionan.
- Prueba que las reglas bloquean:
curl -sI https://tudominio.cl/wp-config.php | head -1
curl -sI https://tudominio.cl/.env | head -1
curl -sI "https://tudominio.cl/?x=../../etc/passwd" | head -1
Las tres deberían responder 403.
- En Cloudflare, revisa Seguridad → Eventos durante los primeros días: ahí ves qué bloqueó cada regla y si hay algún falso positivo.
¿Alguna regla te bloqueó algo legítimo? Cuéntanos en el foro qué dejó de funcionar y ajustamos la regla en comunidad.





