🛡️ Layered WordPress hardening: Cloudflare, wp-config, and origin shielding
If your WordPress site shows intermittent slowness or sudden traffic spikes from countries unrelated to your business (for example, China, Russia, or Taiwan), you are likely being targeted by recon bots or brute-force traffic.
This guide documents how to use Cloudflare's free plan to implement defense in depth, filtering malicious requests before they reach your origin server.
My operational goal is always the same: push hostile traffic handling to the edge, keep the origin focused on legitimate users, and reduce CPU/IO pressure with predictable behavior.
---
1. WAF role in WordPress protection
Cloudflare's Web Application Firewall (WAF) inspects traffic in real time, filtering suspicious patterns such as SQL injection, XSS, and protocol abuse. For a high-exposure CMS like WordPress, targeted rules are mandatory.
🛡️ Rule 1: critical path shielding
This rule blocks direct access to files that should not be loaded in isolation, including legacy XML-RPC and system path abuse.
- Objective: block
xmlrpc.phpabuse and direct hotlinking to system paths. - Expression:
(http.request.uri.path eq "/xmlrpc.php") or
(http.request.uri.path contains "/wp-content/" and http.referer ne "dominio.com.br") or
(http.request.uri.path contains "/wp-includes/" and http.referer ne "dominio.com.br")
- Action: Managed Challenge.
🛡️ Rule 2: admin panel access restriction
Restricting /wp-admin to Brazil-only IP geography significantly reduces global brute-force attempts.
- Objective: block non-business brute-force traffic.
- Expression:
(ip.geoip.country ne "BR" and http.request.uri.path contains "/wp-admin/")
- Action: Block.
Operational note: if your team travels or works globally, keep explicit IP allow rules in a separate policy to prevent admin lockouts.
---
2. Bot mitigation on contact and AJAX endpoints
Form spam abuse through admin-ajax.php pollutes inboxes and also drives CPU usage on origin.
🛡️ Rule 3: AJAX request validation
- Expression:
(not cf.client.bot and http.request.uri.path contains "/wp-admin/admin-ajax.php" and http.request.method eq "POST" and not http.referer contains "dominio.com.br")
- Action: Managed Challenge.
This endpoint is sensitive because many plugins depend on it. I usually deploy this in challenge mode first, monitor traffic analytics, then raise to strict blocking only after validating no legitimate flow is impacted.
---
3. Rate limiting implementation
Even with WAF blocking, attackers can flood endpoints with valid-looking requests. Rate limiting sets hard per-IP ceilings and protects availability.
⚙️ Recommended baseline
- Protected paths:
/wp-login.php,/wp-admin/,admin-ajax.php. - Threshold: 130 requests per 10 seconds.
- Action: block for 10 seconds (HTTP 429 - Too Many Requests).
Practical result: under stress testing without protection, origin usually collapses around 500 concurrent hits. With active limits, abusive clients are throttled automatically while real users keep service continuity.
Operationally this gives two direct benefits:
- Lower saturation on PHP-FPM and database.
- Stable user experience during hostile traffic peaks.
---
4. Senior tip: origin shielding (Cloudflare IP only)
Cloudflare configuration is useless if attackers can still hit your real origin IP directly.
- Gray cloud vs orange cloud: ensure all relevant A/CNAME records are
proxied (orange cloud).
- Server firewall (CSF/IPTables): accept ports 80/443 only from
Cloudflare IP ranges, denying direct public origin access.
Practical hardening cycle on the host
In production hardening I execute this sequence:
- Retrieve official Cloudflare IP ranges.
- Build allow rules for 80/443.
- Deny remaining direct HTTP/HTTPS traffic.
- Validate domain works through Cloudflare and fails by direct origin IP.
This prevents the common false sense of security where WAF is active but origin is still exposed.
---
5. Application-layer control: isolate wp-config.php
Edge controls are not enough if sensitive WordPress configuration stays in public web root. Moving wp-config.php one level above public_html reduces disclosure risk during parser or handler failures.
Practical flow:
- Back up config and database.
- Move
wp-config.phpoutside web root. - Validate syntax and full admin/login behavior.
- Enforce restrictive permissions (
400or440).
cp public_html/wp-config.php public_html/wp-config.php.bak.$(date +%F-%H%M)
mv public_html/wp-config.php /home/accountuser/wp-config.php
php -l /home/accountuser/wp-config.php
chmod 400 /home/accountuser/wp-config.php
For custom layouts, keep a minimal loader stub in public_html with require_once pointing to the secure path.
6. Recommended internal cluster
Keep this as the pillar article and connect with:
blindagem-wordpress-alterar-proteger-diretorio-uploadsauditoria-tecnica-wordpress-xml-rpc-rest-api-cves
---
🏁 Strategic conclusion
WordPress security should not rely only on in-app plugins (for example, Wordfence or Sucuri), which consume origin resources. Moving security logic to the edge (Cloudflare) gives near-zero added latency and reduces hosting processing cost.
From an operational perspective, the payoff is clear: less infrastructure noise, fewer intermittent incidents during peaks, and better predictability when scaling.
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.