Last active
October 6, 2024 21:46
-
-
Save Xunnamius/6057a660d06bcf13cc1f478af9131423 to your computer and use it in GitHub Desktop.
Fail2ban action.d for Cloudflare meant to replace the version that ships with fail2ban currently. This updated version of the action uses Cloudflare's 2023 v4 API (free tier WAF + free tier WAF lists) to ban hostile IPs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This version works with CF WAF (using zone rulesets) and obsoletes previous | |
# versions. This works will all CF account types. This action depends on curl | |
# and jp and will add/remove IPs from the $known_hostile_ips list. Creating the | |
# WAF rules need only be done once per zone. Creating the list need only be done | |
# once per account. | |
# | |
# Author: Bernard Dickens III (Xunnamius) | |
# | |
# Inspired by work from: Mike Rushton | |
# https://github.com/fail2ban/fail2ban/blob/master/config/action.d/cloudflare.conf | |
# | |
# 1. REQUIRES jp TO BE INSTALLED IN THE USER PATH! Install it here: | |
# https://github.com/jmespath/jp | |
# | |
# 2. ! IMPORTANT ! Set jail.local's permission to 640 because it contains one of | |
# your CF API tokens. Grab your account id, your api token, and your "hostile | |
# ip" list id before continuing (see end of file for details). | |
# | |
# 3. Create a new custom list. Name it known_hostile_ips. | |
# https://developers.cloudflare.com/waf/tools/lists | |
# | |
# 4. Ensure every zone you want fail2ban to protect has an enabled WAF ban rule | |
# referencing $known_hostile_ips. | |
# https://developers.cloudflare.com/waf/custom-rules | |
# | |
# 5. Use the fail2ban CLI and the Cloudflare dashboard/Traces to test and make | |
# sure everything is working properly. You may need to add a permission to | |
# your api token to ensure proper function. See the end of this file for | |
# details. | |
# | |
# To get your CloudFlare API Key: | |
# https://www.cloudflare.com/a/account/my-account | |
# | |
# CloudFlare API error codes: https://www.cloudflare.com/docs/host-api.html#s4.2 | |
# | |
# Note that if you're using Nginx, Apache, Litespeed, etc, you need to modify | |
# your logs and/or your filters such that the real client IP is being captured | |
# and not Cloudflare's IPs. | |
[Definition] | |
# Option: actionstart | |
# Notes.: command executed on demand at the first ban (or at the start of | |
# Fail2Ban if actionstart_on_demand is set to false). | |
# Values: CMD | |
# | |
actionstart = | |
# Option: actionstop | |
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban) | |
# Values: CMD | |
# | |
actionstop = | |
# Option: actioncheck | |
# Notes.: command executed once before each actionban command | |
# Values: CMD | |
# | |
actioncheck = | |
# Option: actionban | |
# Notes.: command executed when banning an IP. Take care that the | |
# command is executed with Fail2Ban user rights. | |
# Tags: <ip> IP address | |
# <failures> number of failures | |
# <time> unix timestamp of the ban time | |
# Values: CMD | |
# | |
# API v4 WAF | |
actionban = curl -s -o /dev/null -X POST <_cf_api_prms> \ | |
-d '[{"ip":"<ip>","comment":"Created by fail2ban <name>"}]' \ | |
<_cf_api_url> | |
# Option: actionunban | |
# Notes.: command executed when unbanning an IP. Take care that the | |
# command is executed with Fail2Ban user rights. | |
# Tags: <ip> IP address | |
# <failures> number of failures | |
# <time> unix timestamp of the ban time | |
# Values: CMD | |
# | |
# API v4 WAF | |
actionunban = id=$(curl -s -X GET <_cf_api_prms> \ | |
"<_cf_api_url>?search=<ip>&per_page=1" \ | |
| { jp --unquoted 'result[0].id | not_null(@, `""`)' 2>/dev/null; }) | |
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found"; exit 0; fi; | |
curl -s -o /dev/null -X DELETE <_cf_api_prms> \ | |
-d '{"items":[{"id":"'"$id"'"}]}' \ | |
<_cf_api_url> | |
_cf_api_url = https://api.cloudflare.com/client/v4/accounts/<cfaccountid>/rules/lists/<cfbanlistid>/items | |
_cf_api_prms = -H 'Authorization: bearer <cfapitoken>' -H 'Content-Type: application/json' | |
[Init] | |
# If you like to use this action with mailing whois lines, you could use the | |
# composite action action_cf_mwl predefined in jail.conf, just define in your | |
# jail: | |
# | |
# action = %(action_cf_mwl) | |
# # Your CF API Key | |
# cfapitoken = | |
# cfaccountid = | |
# cfbanlistid = | |
# Your Cloudflare User API Token. It will need "EDIT" level on the "Account | |
# Filter Lists" permission. | |
# https://dash.cloudflare.com/profile/api-tokens | |
cfapitoken = | |
# The identifier of the Cloudflare account used to update the hostile IP list. | |
cfaccountid = | |
# Your Cloudflare WAF "hostile ip" List id. You can find it using the API or or | |
# following the instructions here: | |
# https://community.cloudflare.com/t/what-token-permissions-for-ip-list-edits/525222/6 | |
# https://api.cloudflare.com/client/v4/accounts/:cfaccountid/rules/lists | |
# | |
# Note that even free CF accounts get 1 free list with 10,000 slots, yay! | |
# https://dash.cloudflare.com/:cfaccountid/configurations/lists | |
cfbanlistid = |
For this to work I have append > /dev/null to the end of the curl commands. For some reason my curl version was ignoring the -o param...
actionban = curl -s -o /dev/null -X POST <_cf_api_url> \
<_cf_api_prms> \
-d '[{"ip":"'"<cfip>"'","comment":"<cfcomment>"}]' \
> /dev/null
For a more confortable solution because I've already work with jq but not jp command I end using the solution in this thread https://community.cloudflare.com/t/does-cloudflares-fail2ban-action-still-work/640904/3 that display the { jq -r '.result[0].id' 2>/dev/null || tr -d '\n' | sed -nE 's/^.*"result"\s*:\s*\[\s*\{\s*"id"\s*:\s*"([^"]+)".*$/\1/p'; }
command to the pipe part of the actionunban.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For those who are using a docker-compose. This is how I installed jp as the instructions require. Add this to your docker-compose.yaml file underneath the fail2ban container.
command: /bin/sh -c "apk add --update jp && fail2ban-server -f"