CloudFlare API v4 and Fail2ban: Fixing the unban action

This posting is ~5 years years old. You should keep this in mind. IT is a short living business. This information might be outdated.

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.

Free-Photos/ Creative Commons CC0

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- 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>' \
  $(curl -s -X GET -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \
            '<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>' \
  $(curl -s -X GET -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \
            '<ip>&page=1&per_page=1' | tr -d '\n' | cut -d'"' -f6)

I found the solution at 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.

enabled  = true
filter   = wordpress
logpath  = /var/log/messages
action   = mycloudflare
Rate this post
Patrick Terlisten
Follow me

6 thoughts on “CloudFlare API v4 and Fail2ban: Fixing the unban action

  1. Bernd Helber

    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
    Require not ip

    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

    1. Patrick Terlisten Post author

      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,

  2. L L

    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.


  3. Woyobema

    Hello, this actionban doesn’t support subnets like, only ips like

Comments are closed.