Cloudflare Firewall Rules for WordPress Security
maintenance
Cloudflare firewall and WAF rules can stop common WordPress probes before they reach PHP. Effective rules are narrow: they protect login, XML-RPC, admin, or sensitive REST paths without blocking the block editor, webhooks, authenticated integrations, and real administrators.
How Cloudflare Rules Fit Together
Cloudflare uses field-based expressions to select requests. Common fields include http.request.uri.path, http.request.method, cf.client.bot, and http.user_agent. The older ip.geoip.country and ip.geoip.asnum fields remain supported, but Cloudflare now recommends their ip.src.country and ip.src.asnum equivalents. A matching custom rule can apply an action such as Block, Managed Challenge, JS Challenge, Log, or Skip. Product availability and action names can vary by Cloudflare plan and ruleset; modern WAF custom rules use Skip rather than an Allow action.
Rate Limiting rules are separate from ordinary custom WAF rules. They count matching requests, typically by source IP, over a configured period and apply a mitigation after a threshold is exceeded. The expression selects traffic; the threshold, counting characteristics, time window, mitigation, and duration are configured as rule settings.
Start new rules in Log mode where that option is available, inspect matches, and place exceptions deliberately. Rule order matters when an earlier Skip or blocking rule changes how later security products evaluate a request.
1. Rate-Limit the Login Endpoint
wp-login.php is a predictable target for brute-force and credential-stuffing traffic. A dedicated Rate Limiting rule can match the login path:
(http.request.uri.path eq "/wp-login.php")
Configure a per-IP threshold over a short window, followed by a temporary Block or Managed Challenge. There is no universal safe threshold. A membership site where customers sign in will need a different value from a brochure site with two administrators. Failed and successful login requests use the same path, so an overly low limit can lock out legitimate users behind a shared office, mobile carrier, or VPN address.
The /wp-admin/ prefix also contains login-adjacent traffic, but do not blindly rate-limit every admin request. Logged-in editors load scripts, styles, screens, and background requests there. WordPress also uses /wp-admin/admin-ajax.php for both public and authenticated AJAX features. If you include admin traffic, match specific methods or endpoints based on observed logs and give trusted workflows enough headroom.
A broad expression for observing login and admin paths before creating narrower mitigations is:
(http.request.uri.path eq "/wp-login.php") or
(starts_with(http.request.uri.path, "/wp-admin/"))
Use it for logging or analysis first. A rate limit on wp-login.php alone is easier to reason about than one that treats every admin asset request as an authentication attempt.
2. Block XML-RPC When It Is Unused
xmlrpc.php supports a legacy remote publishing interface. It is also a frequent target for password attacks and abuse of pingback functionality. Sites that do not depend on XML-RPC can match the exact path:
(http.request.uri.path eq "/xmlrpc.php")
Apply a Block action after verifying that the site does not use a legacy XML-RPC mobile client, remote publishing tool, or Jetpack feature that still depends on the endpoint. Blocking it at Cloudflare prevents the request from consuming WordPress and PHP resources.
If XML-RPC is required, use Rate Limiting or a Managed Challenge cautiously instead of a blanket block. Test the actual integration: non-browser clients may not be able to complete an interactive challenge. An allowlist for known source addresses can work for a controlled integration, but it is unsuitable when upstream addresses change without notice.
3. Scope REST API Protection
Blocking /wp-json/ wholesale is likely to break the block editor and legitimate plugins. Protect the sensitive route instead. For example, this expression matches GET requests to the core users path:
(http.request.method eq "GET" and
http.request.uri.path contains "/wp-json/wp/v2/users")
A Block action reduces anonymous enumeration, but Cloudflare does not inherently know WordPress login state merely from this expression. If authenticated editors or applications need the route, build a tested exception based on a trustworthy control available in your deployment. Do not treat a user-supplied header as proof of authentication.
The application should still restrict the data. The guide to hiding users from wp-json/wp/v2/users shows scoped WordPress filters and explains the separate ?author= enumeration route. Edge rules reduce abusive traffic; WordPress authorization remains the definitive access boundary.
4. Use Country Signals Carefully
If administrators and contributors operate only in known regions, you can challenge login and admin requests from other countries. This example selects login traffic outside the United States and Canada:
(http.request.uri.path eq "/wp-login.php" and
not ip.geoip.country in {"US" "CA"})
The country list is only an example, not a recommendation for every site. GeoIP classification is imperfect, and legitimate staff may travel or use a VPN. Managed Challenge is generally safer than Block when country is the primary signal. Maintain a recovery path so an administrator is not permanently locked out by an incorrect location decision.
For /wp-admin/, exclude paths that serve intentional public behavior before applying a geographic control. admin-ajax.php is the common example, but the correct exclusions depend on the plugins and front-end features in use.
5. Evaluate ASN and Bot Signals
Automated login probes often originate from hosting-provider networks. Cloudflare exposes an autonomous system number through ip.geoip.asnum, which can be combined with a login or admin path:
((http.request.uri.path eq "/wp-login.php" or
starts_with(http.request.uri.path, "/wp-admin/")) and
ip.geoip.asnum in {64500 64501})
Those ASNs are documentation-range examples, not networks to block. Build a real list from your own security events and verify ownership before using it. Developers, uptime services, corporate VPNs, and legitimate integrations also run in data centers. Prefer a Challenge for ASN-only suspicion and reserve hard blocks for evidence you can defend.
The cf.client.bot field identifies known good bots verified by Cloudflare. It can complement path, method, country, ASN, and user-agent conditions:
(not cf.client.bot and
http.request.uri.path eq "/wp-login.php")
It does not identify every benign client or every hostile bot. Likewise, http.user_agent is easy for an attacker to change. Use these fields as signals in a layered rule, not as authentication.
Test Without Locking Out WordPress
Create a test plan before enabling a mitigation:
- Confirm that administrators can log in, reset passwords, edit posts, upload media, and save in the block editor.
- Exercise public forms, ecommerce, membership login, search, and any feature using
admin-ajax.php. - Test Jetpack, mobile clients, webhooks, application passwords, and remote publishing integrations.
- Review Cloudflare security events for false positives, then tune paths, thresholds, exclusions, and challenge actions.
- Keep an origin-level access path and rollback procedure appropriate to your environment.
Cloudflare rules protect only traffic that actually passes through Cloudflare. Prevent direct public access to the origin where the architecture permits it, or attackers may bypass the rules by reaching the server address directly.
Nova uses Traefik ingress and a WAF at the edge of its Kubernetes-based managed WordPress hosting. Hostile requests can be stopped before they reach a tenant's isolated WordPress containers, which is the platform-level analogue of the do-it-yourself rules above. Application updates and ongoing controls also belong in a complete WordPress maintenance process.
FAQ
Should I block all traffic to wp-admin?
No. Administrators need the area, and some plugins use admin-ajax.php for public features. Restrict or challenge suspicious traffic using tested path, location, identity, and rate signals.
Is a challenge better than a block?
It often is when country or ASN data is the main signal because those classifications can catch legitimate users. Non-browser integrations cannot always solve challenges, so test them before enforcement.
Can Cloudflare replace a WordPress security fix?
No. It can absorb abusive traffic and enforce edge policy, but WordPress must still apply correct authentication, authorization, updates, and data exposure controls.
What rate limit should wp-login.php use?
There is no universal value. Choose a configurable threshold from observed legitimate login behavior, account for shared IP addresses, and tune it after reviewing security events.
See What's Included With Nova Managed Hosting
Nova runs every managed WordPress tenant in an isolated Kubernetes namespace with daily automated backups and managed core/plugin updates. If you're troubleshooting a specific issue on your own site, our team can help.