Nginx – Fail2ban unban action fails with Cloudflare

cloudflarefail2bannginx

I'm trying to setup Cloudflare blocking with fail2ban using this guide and while it bans the IP correctly, fail2ban cannot unban the IP from Cloudflare either after timeout or with manual shell command. It always returns 400 Bad Request error.

Am I doing something wrong?

Here is the relevant cURL command:

actionunban = curl -s -X DELETE "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$( \
          curl -s -X GET "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=<ip>&page=1&per_page=1&match=all" \
          -H "X-Auth-Email: <cfuser>" \
          -H "X-Auth-Key: <cftoken>" \
          -H "Content-Type: application/json" | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' | tr -d '"' | head -n 1)" \
          -H "X-Auth-Email: <cfuser>" \
          -H "X-Auth-Key: <cftoken>" \
          -H "Content-Type: application/json"

Update: I can run the above mentioned nested cURL commands separately and they return correct responses.

Best Answer

Looks like Cloudflare has adjusted their API to return formatted JSON (previously the returned JSON was on a single line). You should be able to fix the problem by stripping the new line characters before piping to the awk command:

actionunban = curl -s -X DELETE "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$( \
      curl -s -X GET "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=<ip>&page=1&per_page=1&match=all" \
      -H "X-Auth-Email: <cfuser>" \
      -H "X-Auth-Key: <cftoken>" \
      -H "Content-Type: application/json" | tr -d '\n' | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' | tr -d '"' | head -n 1)" \
      -H "X-Auth-Email: <cfuser>" \
      -H "X-Auth-Key: <cftoken>" \
      -H "Content-Type: application/json"

You also might want to swap to the new Cloudflare filters that ships with Fail2ban 0.10, as it is much more succinct:

actionban = curl -s -o /dev/null -X POST -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \
        -H 'Content-Type: application/json' -d '{ "mode": "block", "configuration": { "target": "ip", "value": "<ip>" } }' \
        https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules

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)