How to Protect Your Linux Server from Brute Force Attacks with Fail2Ban
Learn how to protect your Linux server from brute force attacks using Fail2Ban. This guide covers installation and configuration steps for both Debian-derived and RHEL-derived systems.
Brute force attacks—where attackers systematically try numerous user/password combinations to gain access—are among the most common reasons Linux servers get compromised. And it's actually rather easy to prevent.
From a fundamental level, you'll need to be able to recognize repeated failed login attempts and automatically take certain actions, such as banning the IP address. Otherwise, the attacker can just keep guessing until they get it right. And depending on how good of a password you have, this could take a very little or a very long time.
Anyway, preventing brute force attacks sounds complicated, but with open-source projects like Fail2Ban, it turns into a 15-minute or less job.
That said in this article, we'll dive into what Fail2Ban is, how it integrates with your firewall (such as nftables), and how to set it up on Debian-derived and RHEL-derived systems. We'll also explain how Fail2Ban can protect other services like Nginx, Apache, and WordPress from brute force attacks by monitoring their log files.
First things first:
What is Fail2Ban?
Fail2Ban is an open-source intrusion prevention software that acts as a protective layer for your Linux server.
It's essentially a security framework that helps protect against automated attacks, particularly brute force attempts, by dynamically monitoring system logs and responding to suspicious activities in real time.
How Fail2Ban works
Log analysis and detection
Fail2Ban constantly watches your server's log files, like /var/log/auth.log for SSH attempts and /var/log/apache2/access.log for web server activity. Using regular expressions (regex), it identifies patterns of suspicious behavior such as repeated failed login attempts or unusual access patterns.
Response system
When suspicious activity is detected, Fail2Ban takes action through what it calls "jails." Each protected service (like SSH or Apache) has its own jail with specific rules. When triggered, Fail2Ban can automatically create firewall rules to block the offending IP address, send email notifications, and execute other custom actions.
Understanding firewall functionality
While Fail2Ban isn't a firewall itself, it works with your existing firewall.
Modern Linux distributions use different firewall systems, and Fail2Ban adapts to work with each:
Debian-derived systems: Starting from Debian 10 (Buster), nftables is the default firewall backend, replacing iptables. Ubuntu uses UFW (and Debian can as well), but it also uses nftables in the background.
RHEL-derived systems: RHEL 8 and newer use nftables through firewalld, which similarly serves as a frontend interface like UFW.
TLDR: Why use Fail2Ban?
Automated defense: Provides real-time protection against brute force attacks.
Customizable: Allows you to set thresholds, ban times, and monitor multiple services.
Versatile protection: Can protect various services like SSH, Nginx, Apache, and WordPress by analyzing their log files.
Lightweight integration: Works with your existing firewall without significant resource consumption.
Now that we've explained a bit more about Fail2Ban, let's install it.
Installing Fail2Ban
The installation process varies slightly between Debian-derived and RHEL-derived systems.
For Debian-derived systems (Ubuntu, Debian, etc.)
Step 1. Update your package list
sudoapt update
Step 2. Install Fail2Ban
sudoaptinstall fail2ban
For RHEL-derived systems (Fedora, Rocky Linux, AlmaLinux, etc.)
Step 1. Update your package manager
sudo dnf update
Step 2. Install Fail2Ban
For RHEL 8 and beyond based distributions, Fail2Ban is available in the default repositories:
sudo dnf install fail2ban
For RHEL 7 and older versions, you may need to enable the EPEL repository:
Then it's best practice not to modify the default jail.conf file.
So instead, create a jail.local file:
# For Debian/Ubuntu systemssudonano /etc/fail2ban/jail.local
# For RHEL-derived systemssudovi /etc/fail2ban/jail.local
Step 2. Configure basic settings
Next, we'll need to edit the configuration file using your system's default editor.
For RHEL users not familiar with vi:
Press i to enter insert mode
Make your changes
Press ESC to exit insert mode
Type :wq and press Enter to save and quit
Or type :q! to quit without saving
Add these basic settings to your jail.local (editing accordingly):
[DEFAULT]# IPs to never ban (add your admin IPs here)ignoreip=127.0.0.1/8 ::1# Ban duration (use time units: s=seconds, m=minutes, h=hours, d=days)bantime=1d# Time window for counting failuresfindtime=10m# Failures before banmaxretry=5# Logs level (can be INFO, WARN, ERROR, CRITICAL)loglevel=INFO# Firewall configuration# For Debian 10+, Ubuntu 20.04+:banaction=nftables-multiport# For RHEL 8/9, Rocky Linux, AlmaLinux (uncomment if needed):# banaction = firewallcmd-multiport# Email notificationsdestemail=[email protected]sender=[email protected]sendername=Fail2Banmta=sendmail# Simple notificationaction=%(action_mw)s# Or detailed notification with whois data:# action = %(action_mwl)s
Note: For Fail2Ban to send you notifications, you need to able to send emails, which some hosts may disable. So double-check.
Step 3. Configure service-specific jails
Next up you'll need to configure Fail2Ban according to what services you want to protect.
Here are a few examples:
SSH protection
[sshd]enabled=trueport=sshfilter=sshd# For Debian/Ubuntu:logpath=/var/log/auth.log# For RHEL/CentOS/Rocky/AlmaLinux (uncomment if needed):# logpath = /var/log/securemaxretry=3
Note: When Fail2Ban is installed, it comes with some defaults in jail.conf, so you'll need to make sure there isn't already an existing configuration before adding it in jail.local, for the most part, you don't need to change much for SSH. jail.local is for additional custom configurations.
[apache-auth]enabled=trueport=http,https# Log path varies by distribution# For RHEL/CentOS/Rocky/Alma:logpath=/var/log/httpd/error_log# For Debian/Ubuntu:# logpath = /var/log/apache2/error.logmaxretry=3bantime=1dfindtime=10m[apache-badbots]enabled=trueport=http,https# For RHEL/CentOS/Rocky/Alma:logpath=/var/log/httpd/access_log# For Debian/Ubuntu:# logpath = /var/log/apache2/access.logmaxretry=2bantime=1dfindtime=10m
WordPress protection
Create the WordPress jail configuration:
[wordpress]enabled=truefilter=wordpressport=http,https# If using Nginxlogpath=/var/log/nginx/access.log# If using Apache (RHEL)# logpath = /var/log/httpd/access_log# If using Apache (Debian)# logpath = /var/log/apache2/access.logmaxretry=3findtime=5mbantime=1d
Create the WordPress filter:
# For RHEL-based systemssudovi /etc/fail2ban/filter.d/wordpress.conf
# For Debian-based systemssudonano /etc/fail2ban/filter.d/wordpress.conf
Add these patterns to detect WordPress login failures:
Apply your new settings by restarting the Fail2Ban service:
sudo systemctl restart fail2ban
Monitoring Fail2Ban
To verify that Fail2Ban is active, check the overall status:
sudo fail2ban-client status
You can also check the status of a specific jail:
sudo fail2ban-client status sshd
This will display the number of currently banned IPs and other relevant information.
Conclusion
By intelligently monitoring log files and interacting with your firewall, Fail2Ban provides automated, real-time defense without significant resource consumption and practically eliminates the risk of being compromised by a brute-force attack.
If you ask us, it's certainly worth giving a shot.