This post will talk about how I set up Cloudflare WAF rules for my WordPress sites, and it is meant for only free tier Cloudflare accounts. If you use other paid tiers of Cloudflare, there may be better settings to use.
If you don’t know yet, Cloudflare announced giving free tier users for up to 5 rules in WAF this year. This is helpful for small websites or hobby sites that can’t justify other paid plans.
I have decided the best use case for this new feature would be using it to block off some bad traffic, secure important WordPress pages such as the login page and block contact form spam or comment spam.
Here are Cloudflare firewall logs for one of my WordPress sites:
Let’s get straight into the WAF rules I currently use in the next section.
Cloudflare WAF Rules for WordPress
I am currently using only 3 rules for my WordPress site. However, please understand that firewall rules aren’t going to be one size fits all. It is something that you should optimize based on your firewall logs to improve accuracy and reduce false positives.
Please note that below rules are in expression format, so they doesn’t work with Cloudflare expression builder. This is because some of them contain nested rules.
1. Secure WordPress sensitive directory such as wp-login.php
((http.request.uri.path contains "/xmlrpc.php") or (http.request.uri.path contains "/wp-login.php") or (http.request.uri.path contains "/wp-admin/" and not http.request.uri.path contains "/wp-admin/admin-ajax.php" and not http.request.uri.path contains "/wp-admin/theme-editor.php")) and ((not ip.geoip.country in {"MY" "JP"}) or (cf.threat_score gt 5))
Set this rule to Managed Challenge
As you can see, I do, however, exclude both countries where I am located, but not if the threat score is above 5. This is optional, though. You can remove the entire part if you want.
I also recommend setting a rate limit in your Nginx / apache configuration or even using Cloudflare Zero Trust Access to protect your login page against brute force attempts.
2. Challenge that block bad bots, bad IP reputation and spammy countries
(http.user_agent contains "Yandex") or (http.user_agent contains "muckrack") or (http.user_agent contains "Qwantify") or (http.user_agent contains "Sogou") or (http.user_agent contains "BUbiNG") or (http.user_agent contains "knowledge") or (http.user_agent contains "CFNetwork") or (http.user_agent contains "Scrapy") or (http.user_agent contains "SemrushBot") or (http.user_agent contains "AhrefsBot") or (http.user_agent contains "Baiduspider") or (http.user_agent contains "python-requests") or (http.user_agent contains "crawl" and not cf.client.bot) or (http.user_agent contains "Crawl" and not cf.client.bot) or (http.user_agent contains "bot" and not http.user_agent contains "bingbot" and not http.user_agent contains "Google" and not http.user_agent contains "Twitter" and not cf.client.bot) or (http.user_agent contains "Bot" and not http.user_agent contains "Google" and not cf.client.bot) or (http.user_agent contains "Spider" and not cf.client.bot) or (http.user_agent contains "spider" and not cf.client.bot) or (cf.threat_score gt 5) or (ip.geoip.country in {"CN" "RU" "TR" "UA" "VN"})
Set this rule to Managed Challenge
This rule works with expression builder because it doesn’t contain nested rules, so you can easily make changes to it, such as adding more bad user agents and countries or changing the threat score.
Do note that this rule does block some SEO tools. For example, if you are using Ahrefs, you will need to remove the line that blocks their crawler’s user agent.
3. Block contact form spam and comment spam
((http.request.uri.path contains "/wp-admin/admin-ajax.php") or (http.request.uri.path contains "/wp-comments-post.php")) and (http.request.method eq "POST") and (cf.threat_score gt 5)
Set this rule to Block
This rule block all POST request to contact form or comment form from IP with a threat score above 5, I have this rule because I have other contact channels to let real user contact me, so I have my threat score set lower. However, if many real users cannot use your contact form, you may increase the threat score to 10.
Other rules
I have also tried using a list of bad IPs in the WAF rules. However, as the free tier only lets you set a list of up to 10k items, I feel like it is much better just to use their threat score for all my rules.
You can also have rules based on ASN, but again as it only allows up to 4096 lengths, you can only define so many ASN within the limitation, which, again, I chose just to use threat score only for simplicity.
However, you should understand that using Cloudflare doesn’t mean your site are now completely secured and spam-free. It should only be used in combination with other security or spam countermeasures.