In January 2017, I wrote an article about how to protect your WordPress blog using the WP Fail2Ban plugin, fail2ban on your Linux/ FreeBSD host, and CloudFlare. Back then, the fail2ban was using the CloudFlare API V1, which was already deprecated since November 2016.
Although the actions were updated later to use CloudFlare API V4, I still had problems with the unbaning of IP addresses. IP addresses were banned, but the unban action failed.
This is the unban action, which is included in fail2ban (taken from fail2ban-0.10.3.1 which is shipped with FreeBSD 11.1-RELEASE-p10):
actionunban = curl -s -o /dev/null -X DELETE -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \ https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$(curl -s -X GET -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \ 'https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=<ip>&page=1&per_page=1' | cut -d'"' -f6)
And this is the unban action, which finally solved this issue:
actionunban = curl -s -o /dev/null -X DELETE -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \ https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$(curl -s -X GET -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \ 'https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=<ip>&page=1&per_page=1' | tr -d '\n' | cut -d'"' -f6)
I found the solution at serverfault.com. The only difference is an additional tr -d ‘\n’ in the last line of the statement. Kudos to Jake for fixing this!
To prevent the action file to being overwritten, you should copy the original cloudflare.conf located in the action.d directory, e.g. to mycloudflare.conf , and use the copied action file in your fail definition.
[wordpress] enabled = true filter = wordpress logpath = /var/log/messages action = mycloudflare
- Failed to connect to IKEv2 VPN using iPhone USB tethering - June 26, 2023
- Why you should change your KRBTGT password prior disabling RC4 - July 28, 2022
- Use app-only authentication with the Microsoft Graph PowerShell SDK - July 22, 2022
Morning Patrick, despite i tend to roll my on Stuff regarding Webserver Security. ;) Or Security in general. I’m not very educated regarding Cloudflare. But Unix/Linux and Apache in special offers a lot of “vehicle tools” who may be very useful, especially if it comes to wordpress or any other Web Application hardening.
– Fail2ban is a great tool, but currentyl it lacks ipv6 Features, as i know so far. Possibly the got it fixed.
– Personyl i rely on mod_security, it works well es a Application Firewall, the flipside of the coin is, that you have to invest a huge amount of time, to get it where you want it to be. But in the end it pays off.
Apache offers another great Tool most Webmasters tend to ignore. You can create Blacklists for IP’s or IP Ranges, and include them into your Apache Config as well. ;)
At Example
vi /etc/apache2/custom.d/bliacklist-ip.conf
Require not ip 1.2.4.0/11
Require not ip 2.3.4.5
You may be able to attach this to you’re Virtual Host Configuration.
# just in case if .htaccess gets disabled
Require all denied
Include /etc/apache2/custom.d/globalblacklist.conf
Take Care
Hi Bernd and thank you for your comment! Cloudflare is doing several things, like code-optimization, load balancing, caching and security. Because it is acting as a load balancer, I don‘t see the real client IP in my webserver logs. That‘s why I have to use a combination of a WordPress plugin and Fail2Ban.
Thanks for your hint regarding mod_security!
Best regards,
Patrick
Hi Bernd, Patrick,
Cloudflare is a proxy, so the connections to the web server are actually coming from a Cloudflare IP. You can get the real client IP in a few different ways. If you’re using Apache, and have access to add modules to Apache, you can use mod_cloudflare, which is the simplest way to log the real client IP to the Apache logs and doesn’t depend on specific support at the software level (ie, WordPress). I’m not sure of other web servers, such as NGINX, but there’s probably a solution that’s similar.
Even then, the REAL connection to the web server is from the Cloudflare subnets, not the client IP. With mod_cloudflare, you are logging the client IP, but if you block the client IP in local iptables/firewalld or Apache blacklists, it will do nothing at all, because that isn’t really where the connection is coming from. You have to integrate with Cloudflare’s API, as Patrick has illustrated, to actually block the client IP from connecting. This is preferable anyways, because then Cloudflare is blocking the client IP before it hits the web server, saving on bandwidth, CPU and RAM usage for busy sites when those metrics matter.
If you do not have access to modify Apache, Patrick’s solution for WordPress works great. However, if you do have access to add a module to Apache, mod_cloudflare is the best route to go because there’s no website code dependency. WordPress plugins sometimes break, due to updates or coding errors by the plugin authors, so I prefer a solution not specific to a single piece of site code (WordPress, Drupal, etc).
Any additional modules/plugins can have a hit as far as site latency. If I remember correctly, for most WordPress plugins to run, most of the WordPress core needs to load. That’s CPU and RAM usage that’s really not needed. If you’re running a very busy website, you definitely do not want to introduce any unneeded latency or increased CPU/RAM usage if you can help it.
Patrick, thanks so much for the proper unban action! Fail2ban still comes with the old API version.
Thanks.
Thank you for your detailed and very helpful comment, Lenny!
Hello, this actionban doesn’t support subnets like 10.0.0.0/22, only ips like 1.2.3.4.
Thanks.
Thanks this is only solution for fail2ban 0.11 working.
Very useful