(转)如何在CloudFlare中集成fail2ban - How to Integrate fail2ban with CloudFlare API v4 Guide

CloudFlare的流速控制有点贵,应付小规模的ddos攻击,用fail2ban就行了,刚开始会断一下,但随着对攻击ip的收集并提交给CloudFlare,攻击会被CloudFlare的防火墙挡掉。
https://guides.wp-bullet.com/integrate-fail2ban-cloudflare-api-v4-guide/
CloudFlare is a pretty sweet free security, firewall and acceleration service that I use on all my WordPress sites. The old CloudFlare API is being retired shortly (November 2016, source). Since the CloudFlare v4 API is already live, I wanted to be prepared for the new API switch.
I use fail2ban to protect my wp-login with basic HTTP authentication (nginxApache) and D(D)oS protection from hacker bots that slam wp-login and xmlrpc.php. When you use CloudFlare, it will route all safe traffic to your web server unless you block certain IPs. Blocking IPs on my web servers alone is therefore not sufficient. Luckily fail2ban support custom actions so I wrote this integration with CloudFlare’s API v4 so CloudFlare won’t send unwanted traffic to my servers.
If you are using CloudFlare with WordPress or WooCommerce I highly recommend this sort of integration for additional security.
This fail2ban CloudFlare tutorial was tested on Ubuntu and Debian but should have no problems on CentOS or other Linux distributions.

How to Integrate fail2ban with CloudFlare API v4 Guide

Installation overview
  • Test CloudFlare API v4 with cURL
  • Create custom CloudFlare action for integration with fail2ban
I have only tested this on fail2ban 0.8.3 and 0.9.4, check your version with this command before proceeding.
sudo fail2ban-client -V

Test CloudFlare API v4

First install cURL
sudo apt-get update
sudo apt-get install curl -y
Go get your CloudFlare API key from here and replace the values below, we will ban IP 1.2.3.4 as a test.
This will be the fail2ban ban action.
curl -s -X POST "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules" \
  -H "X-Auth-Email: CloudFlare-username" \
  -H "X-Auth-Key: CloudFlare-API-Key" \
  -H "Content-Type: application/json" \
  --data '{"mode":"block","configuration":{"target":"ip","value":"1.2.3.4"},"notes":"Fail2ban"}'
You should get this feedback showing the IP rule was added to CloudFlare, note the success: true.
{"result":{"id":"8286c03a200db3b5d09bab0f414dc111","mode":"block","allowed_modes":["block","challenge","whitelist","js_challenge"],"status":"active","notes":"Fail2ban","scope":{"id":"b39e813030ef3ce72a82896683932a7d","email":"CloudFlare-username","type":"user"},"configuration":{"value":"1.2.3.4","target":"ip"},"created_on":"2016-09-08T14:36:36.770021Z","modified_on":"2016-09-08T14:36:36.770021Z"},"success":true,"errors":[],"messages":[]}
Now test deleting the CloudFlare firewall ban rule we just created. This will be used for the fail2ban unban action.
Note: This uses a nested cURL command, we need to get the rule ID in order to delete it.
curl -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=1.2.3.4&page=1&per_page=1&match=all" \
-H "X-Auth-Email: CloudFlare-username" \
-H "X-Auth-Key: CloudFlare-API-Key" \
-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: CloudFlare-username" \
-H "X-Auth-Key: CloudFlare-API-Key" \
-H "Content-Type: application/json"
You should get this feedback showing the IP rule was deleted from CloudFlare.
{"result":{"id":"8286c03a200db3b5d09bab0f414dc111"},"success":true,"errors":[],"messages":[]}

Create Custom CloudFlare Action for Integration with fail2ban

Create the CloudFlare fail2ban action, if it exists already you can back it up first
sudo mv /etc/fail2ban/action.d/cloudflare.conf /etc/fail2ban/action.d/cloudflare.conf.bak
sudo nano /etc/fail2ban/action.d/cloudflare.conf
Paste this configuration which we tested above using CloudFlare’s API v4 to ban an IP.
The unban action is the nested cURL command from above that deletes the ban when fail2ban’s bantime expires This will keep your CloudFlare IP blacklist clean.
Remember to put your CloudFlare username (your email) in cfuser and your API key which can be found here in cftoken.
#
# Author: Mike Andreasen from https://guides.wp-bullet.com
# Adapted Source: https://github.com/fail2ban/fail2ban/blob/master/config/action.d/cloudflare.conf
# Referenced from: https://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE
#
# To get your Cloudflare API key: https://www.cloudflare.com/my-account
#

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart =

# Option:  actionstop
# Notes.:  command executed once 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 address
#            number of failures
#          
Ctrl+X, Y and Enter to Save and Exit.
EDIT: Thanks to Vini’s research there are now updated ban and unban actions that solve the 400 bad request error
actionban = curl -s -o /dev/null -X POST -H 'X-Auth-Email: ' -H 'X-Auth-Key: ' \
        -H 'Content-Type: application/json' -d '{ "mode": "block", "configuration": { "target": "ip", "value": "" } }' \
        https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules

actionunban = curl -s -o /dev/null -X DELETE -H 'X-Auth-Email: ' -H 'X-Auth-Key: ' \
          https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$(curl -s -X GET -H 'X-Auth-Email: ' -H 'X-Auth-Key: ' \
          'https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=&page=1&per_page=1' | tr -d '\n' | cut -d'"' -f6)
Now open up any fail2ban jail you want to integrate with CloudFlare’s API v4. I am using a pre-configured nginx-limit-req jail for fail2ban to ban users who make too many requests to nginx.
sudo nano /etc/fail2ban/jail.d/nginx-limit-req.conf
Add an action line that includes our CloudFlare action, if you had no action line before the default is iptables-multiport.
In some versions of fail2ban you need to call it actions instead of action otherwise the jail will not be activated and neither will the action.
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport
         cloudflare
port = http,https
logpath = /var/log/nginx/*error*.log
findtime = 10
bantime = 6000
maxretry = 3
Ctrl+X, Y and Enter to Save
Test the CloudFlare fail2ban integration configuration
sudo fail2ban-client -d
You will see multiple actions are added for your fail2ban jail
['set', 'nginx-limit-req', 'addaction', 'iptables-multiport']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'actionban', ' -I f2b- 1 -s  -j ']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'actionstop', ' -D  -p  -m multiport --dports  -j f2b-\n -F f2b-\n -X f2b-']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'actionstart', ' -N f2b-\n -A f2b- -j \n -I  -p  -m multiport --dports  -j f2b-']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'actionunban', ' -D f2b- -s  -j ']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'actioncheck', " -n -L  | grep -q 'f2b-[ \\t]'"]
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'protocol', 'tcp']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'chain', 'INPUT']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'lockingopt', '-w']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/name', 'default']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'blocktype', 'REJECT --reject-with icmp-port-unreachable']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/lockingopt', '-w']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/port', 'ssh']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/protocol', 'tcp']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/lockingopt', '-w']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'port', 'ssh']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/chain', 'INPUT']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/name', 'default']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/protocol', 'tcp']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'iptables', 'iptables ']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/__name__', 'Init']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'returntype', 'RETURN']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/returntype', 'RETURN']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/__name__', 'Init']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/returntype', 'RETURN']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'name', 'default']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/blocktype', 'REJECT --reject-with icmp-port-unreachable']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/port', 'ssh']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/iptables', 'iptables ']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/chain', 'INPUT']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/blocktype', 'REJECT --reject-with icmp-port-unreachable']
['set', 'nginx-limit-req', 'action', 'iptables-multiport', 'known/known/iptables', 'iptables ']
['set', 'nginx-limit-req', 'addaction', 'cloudflare']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'actionban', 'curl -X POST "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules" \\\n-H "X-Auth-Email: " \\\n-H "X-Auth-Key: " \\\n-H "Content-Type: application/json" \\\n--data \'{"mode":"block","configuration":{"target":"ip","value":""},"notes":"Fail2ban"}\'']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'actionstop', '']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'actionstart', '']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'actionunban', 'curl -s -X DELETE "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$(']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'actioncheck', '']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'cfuser', 'CloudFlare-username']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'cftoken', 'CloudFlare-API-Key']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'known/cfuser', 'CloudFlare-username']
['set', 'nginx-limit-req', 'action', 'cloudflare', 'known/cftoken', 'CloudFlare-API-Key']
['start', 'nginx-limit-req']
You can restart fail2ban to activate the CloudFlare integration on your jail.
sudo service fail2ban restart
You can check your logs
sudo tail -f /var/log/fail2ban.log
Now when users violate a rule on your server they will be banned on both your server and CloudFlare, all automatically for convenience.

评论

此博客中的热门博文

(转)利用 Naxsi 在 Nginx 上构建 WAF