Fail2ban with Cloudflare
In this case, I want to protect an app in Docker container with Fail2ban which uses Cloudflare CDN.
Prerequisites
This tutorial was adapted from my other fail2ban guide (Protect Wordpress Login in Docker container with Fail2Ban) and enables Cloudflare CDN "the orange cloud" on the subdomain. So, in order to follow these steps (Step 1, Step 2 and so on), you may adapt your jail config or deploy the same WP container first:
- Install Docker Engine (docs)
- A docker-compose wordpress-mysql (gists)
- Nginx proxy, if you deployed WP on a different port
- Install curl package with
apt install curl
Step 1: Add a New Fail2ban Jail
Edit jail.local
file:
sudo nano /etc/fail2ban/jail.local
Add a new jail named "cf-wplogin":
[cf-wplogin]
enabled = true
port = http,https
filter = wplogin
chain = DOCKER-USER
logpath = /var/lib/docker/containers/*/*-json.log
banaction = cloudflare-apiv4
iptables-allports
Step 2: Create a Custom Fail2ban Filter
Create a new filter file : nano /etc/fail2ban/filter.d/wplogin.conf
[Definition]
failregex = {"log":"<HOST> -.*POST.*wp-login.php.*
ignoreregex =
Step 3: Create a Fail2ban action
Create a new action file: nano /etc/fail2ban/action.d/cloudflare-apiv4.conf
As you can notice, the actionban and actionunban is curl command to cloudflare restapi.
You can get your cloudflare api key from your profile page. Use the "Global Api Key"
After adding a new jail, filter, and action, Fail2ban should be restarted. Restart fail2ban with:
sudo systemctl stop fail2ban
sudo systemctl start fail2ban
Step 4: Nginx
As I mentioned earlier, these steps adapted from (Protect Wordpress Login in Docker container with Fail2Ban) which a wordpress container running on 127.0.0.1 port 8080 and proxied to 80 with NGINX.
Next step is configuring nginx so that it won't just ban the Cloudflare CDN IP but the actual IP of the visitor. Create a file named cf-realip.conf
in /etc/nginx/conf.d
directory and add the following:
These IPs are Cloudflare's IPs, you can get the list at https://www.cloudflare.com/ips
And edit your main nginx.conf:
nano /etc/nginx/nginx.conf
Add the following code:
##
# CF Real IP
##
include /etc/nginx/conf.d/cf-realip.conf;
real_ip_header X-Forwarded-For;
restart your nginx with:
service nginx restart
Step 5: Let's try it out!
Check the jail status with the following command:
fail2ban-client status cf-wplogin
Output:
root@server:~# fail2ban-client status cf-wplogin
Status for the jail: cf-wplogin
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/lib/docker/containers/599f2f26530ec5b26cbd5d542a3034ef6f54fdd78b32587ef7e33f8518e2493d/599f2f26530ec5b26cbd5d542a3034ef6f54fdd78b32587ef7e33f8518e2493d-json.log
/var/lib/docker/containers/d1dbe55aed91c1f2e4095eb05a5a14dd0750e13b88e49b9786623e5903c22dc6/d1dbe55aed91c1f2e4095eb05a5a14dd0750e13b88e49b9786623e5903c22dc6-json.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
And the last step, let's try creating an error to trigger fail2ban jail with open your wordpress login in your web browser:
If you are trying to access other subdomain, cloudflare will display this error 1006 Access Denied, because your IP has been banned entirely.
List Blocked IP
To get a list of blocked IPs in your server, run the following command:
fail2ban-client status cf-wplogin
Output:
root@server:~# fail2ban-client status cf-wplogin
Status for the jail: cf-wplogin
|- Filter
| |- Currently failed: 0
| |- Total failed: 3
| `- File list: /var/lib/docker/containers/599f2f26530ec5b26cbd5d542a3034ef6f54fdd78b32587ef7e33f8518e2493d/599f2f26530ec5b26cbd5d542a3034ef6f54fdd78b32587ef7e33f8518e2493d-json.log
/var/lib/docker/containers/d1dbe55aed91c1f2e4095eb05a5a14dd0750e13b88e49b9786623e5903c22dc6/d1dbe55aed91c1f2e4095eb05a5a14dd0750e13b88e49b9786623e5903c22dc6-json.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 192.168.0.6
You can also check the list of banned IP on Cloudflare dashboard -> Your domain -> Security -> WAF (Web Application Firewall) -> Tools
Unblock IP
To unblock banned IPs, run the following command:
fail2ban-client set cf-wplogin unbanip 192.168.0.6
banaction
section in jail.local iptables-allports
)Reference:
Thank you for reading!