Fail2ban is an intrusion prevention system written in Python that runs on all POSIX operating systems that have a tamperable packet filtering system or firewall (e.g. iptables on Linux).
The main purpose of fail2ban is to determine and block specific IP addresses that are likely to belong to attackers who want to gain access to the system. fail2ban identifies IP addresses from log files that try to log in with incorrect passwords or perform other dangerous or senseless actions more often in a time frame set by the administrator. Usually, fail2ban is configured to unblock blocked addresses after a certain amount of time so as not to block legitimate connection attempts (for example, if the attacker IP is dynamically allocated to another host). A blocking time of a few minutes is considered helpful to stop flooding the server with malicious connection attempts (brute force).
Fail2ban is capable of performing various actions when a likely malicious IP has been detected, such as blocking that IP with a rule in iptables or the one belonging to TCP wrappers to reject subsequent attacks, email notifications, or any custom action that can be performed with Python.
---
The default configuration includes filters for Apache, Lighttpd, sshd, vsftpd, qmail, and Postfix Server. Filters are defined by regular expressions that can be easily customized by the administrator. The combination of filter and action is called jail and is capable of blocking malicious hosts. A jail can be created for any software that creates log files that can be evaluated with regular expressions.

It is easy to install and configure fail2ban, at least for the basic purpose. SSH to your server and run the following commands:
1 2 3 4 5 6 7 | apt update -y apt upgrade -y apt install fail2ban # check content cat /etc/fail2ban/jail.conf cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local apt install iptables-persistent |
Restart fail2ban :
1 | service fail2ban restart |
Run iptables -L to list current rules:
If firewall rules are not present then you can run :
1 2 3 4 5 | sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -j DROP |
iptables rules are optional when you are using fail2ban for virtual servers and dedicated servers with a webhost-provided firewall. You can see the available filters here:
1 | ls /etc/fail2ban/filter.d |
These filters can be enabled from:
1 | /etc/fail2ban/jail.local |
The steps we have performed should reduce 80% of attacks. From this file, you can change the findtime, bantime etc. By default, they are set to a lower value for testing purposes. If you can increase the bantime to 1 day or more after testing for a few days. Of course, you must enable PEM certificate-based SSH login.
For WordPress, you need a WordPress plugin named Fail2Ban Redux:
1 | https://wordpress.org/plugins/wp-fail2ban-redux/ |
Upload and activate the plugin through the ‘Plugins’ menu in WordPress.
Copy the config/filters/wordpress-hard.conf and config/filters/wordpress-soft.conf files to your Fail2Ban filters directory /etc/fail2ban/filters.d.
If my public directory (where WordPress is installed) is /var/www/html/, then wordpress-hard.conf and wordpress-soft.conf will be located at :
1 | /var/www/html/wp-content/plugins/wp-fail2ban-redux/config/filters |
We need to copy these files (one or both) to:
1 | /etc/fail2ban/filter.d |
Run these commands:
1 2 3 | cp /var/www/html/wp-content/plugins/wp-fail2ban-redux/config/filters/wordpress-soft.conf /etc/fail2ban/filter.d/wordpress-soft.conf ## cp /var/www/html/wp-content/plugins/wp-fail2ban-redux/config/filters/wordpress-hard.conf /etc/fail2ban/filter.d/wordpress-hard.conf |
This is the configuration file:
1 | /var/www/html/wp-content/plugins/wp-fail2ban-redux/config/jail/wordpress.conf |
This is the content of the file:
1 2 3 4 5 6 7 8 9 10 11 12 | [wordpress-hard] enabled = true filter = wordpress-hard logpath = /var/log/auth.log maxretry = 2 port = http,https [wordpress-soft] enabled = true filter = wordpress-soft logpath = /var/log/auth.log maxretry = 5 |
Open:
1 | nano /etc/fail2ban/jail.conf |
Add the above stanza. Restart fail2ban:
1 | service fail2ban restart |
Check whether we did correct or not:
1 | sudo fail2ban-client status wordpress-hard |
You will get output like :
1 2 3 4 5 6 7 8 9 | Status for the jail: wordpress-hard |- Filter | |- Currently failed:0 | |- Total failed: 40 | `- File list: /var/log/auth.log `- Actions |- Currently banned:1 |- Total banned: 1 `- Banned IP list: 91.200.12.155 |
It is an optional step. Open logrotate.conf :
1 | sudo nano /etc/logrotate.conf |
Add this stanza :
1 2 3 4 5 | /var/log/auth.log { size 30k create 0600 root root rotate 4 } |
It is to set the maximum size of the file, permissions of the file, and the number of weeks (4 in the above example) that the file will not become /var/log/auth.log.1. It is an auto-cleaning system in GNU/Linux preserving the record in different files. You can cat on these files :
1 | cat /var/log/auth.log |
This command is very useful for checking Fail2Ban every day, it is divided into number, possible hostname and IP addresses:
1 | grep "Ban " /var/log/fail2ban.log | grep `date +%Y-%m-%d` | awk '{print $NF}' | sort | awk '{print $1,"("$1")"}' | logresolve | uniq -c | sort |
Example output:
1 2 3 4 5 6 7 8 9 10 11 | 1 101.36.123.172 (101.36.123.172) 1 143.110.176.216 (143.110.176.216) 1 169.204.96.34.bc.googleusercontent.com (34.96.204.169) 1 199.15.109.208.host.secureserver.net (208.109.15.199) 1 36.137.56.33 (36.137.56.33) 1 43.134.1.156 (43.134.1.156) 1 43.135.146.161 (43.135.146.161) 3 103.118.29.175 (103.118.29.175) 3 129.146.242.24 (129.146.242.24) 3 192.241.139.149 (192.241.139.149) 3 vps-b13be790.vps.ovh.net (54.38.243.250) |
Now, you can install libapache2-mod-geoip module to get the country names. For nginx, you had to fight to get it configured. We have a guide for compiling GeoIP with Nginx. For Apache2, it is few steps:
1 2 | sudo apt install libapache2-mod-geoip sudo nano /etc/apache2/mods-available/geoip.conf |
geoip.conf should look like this:
1 2 3 4 | <IfModule mod_geoip.c> GeoIPEnable On GeoIPDBFile /usr/share/GeoIP/GeoIP.dat </IfModule> |
Enable the module and restart Apache2 after a successful config test:
1 2 3 4 | sudo apt-get install geoip-bin sudo a2enmod geoip sudo apachectl configtest sudo service apache2 restart |
Now, if you run this command, you’ll get attackers by country:
1 | zgrep -h "Ban " /var/log/fail2ban.log* | awk '{print $NF}' | sort | uniq -c | xargs -n 1 geoiplookup { } | sort | uniq -c | sort |
Like this:
1 2 3 4 5 6 7 | 1 GeoIP Country Edition: FR, France 1 GeoIP Country Edition: RU, Russian Federation 1 GeoIP Country Edition: TW, Taiwan 3 GeoIP Country Edition: CN, China 4 GeoIP Country Edition: JP, Japan 7 GeoIP Country Edition: US, United States 17 GeoIP Country Edition: IP Address not found |
You’ll get more commands on our earlier guide on fail2ban. You can setup Fail2Ban Log Analytics Graph With badips.com.
Tagged With fail2ban apache2 2024