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.

Publish date: 11/22/2024

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

sudo apt update

Step 2. Install Fail2Ban

sudo apt install 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:

sudo yum install epel-release
sudo yum install fail2ban

(Though, it may be time to consider upgrading.)

Configuring Fail2Ban

After installing Fail2Ban, you'll need to configure it to suit your server's security needs.

Step 1. Create a local configuration file

First, make sure you have the required logging system (which may not be included in your distribution template):

# Debian/Ubuntu systems 
sudo apt install rsyslog 
sudo systemctl enable rsyslog 
sudo systemctl start rsyslog

# For RHEL 8/Rocky/Alma
sudo dnf install rsyslog
sudo systemctl enable rsyslog
sudo systemctl start rsyslog

Then it's best practice not to modify the default jail.conf file.

So instead, create a jail.local file:

# For Debian/Ubuntu systems
sudo nano /etc/fail2ban/jail.local

# For RHEL-derived systems
sudo vi /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 failures
findtime = 10m

# Failures before ban
maxretry = 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 notifications
destemail = [email protected]
sender = [email protected]
sendername = Fail2Ban
mta = sendmail
# Simple notification
action = %(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 = true
port = ssh
filter = sshd
# For Debian/Ubuntu:
logpath = /var/log/auth.log
# For RHEL/CentOS/Rocky/AlmaLinux (uncomment if needed):
# logpath = /var/log/secure
maxretry = 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.

Web server protection

For Nginx:

[nginx-http-auth]
enabled = true
port    = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 1d
findtime = 10m

[nginx-botsearch]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/access.log
maxretry = 2
bantime = 1d
findtime = 10m

For Apache:

[apache-auth]
enabled = true
port    = 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.log

maxretry = 3
bantime = 1d
findtime = 10m

[apache-badbots]
enabled  = true
port     = http,https

# For RHEL/CentOS/Rocky/Alma:
logpath = /var/log/httpd/access_log
# For Debian/Ubuntu:
# logpath = /var/log/apache2/access.log

maxretry = 2
bantime = 1d
findtime = 10m

WordPress protection

Create the WordPress jail configuration:

[wordpress]
enabled  = true
filter   = wordpress
port     = http,https

# If using Nginx
logpath  = /var/log/nginx/access.log
# If using Apache (RHEL)
# logpath = /var/log/httpd/access_log
# If using Apache (Debian)
# logpath = /var/log/apache2/access.log

maxretry = 3
findtime = 5m
bantime  = 1d

Create the WordPress filter:

# For RHEL-based systems
sudo vi /etc/fail2ban/filter.d/wordpress.conf

# For Debian-based systems
sudo nano /etc/fail2ban/filter.d/wordpress.conf

Add these patterns to detect WordPress login failures:

[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
            ^<HOST> .* "POST /wordpress/wp-login.php
            ^<HOST> .* "POST /blog/wp-login.php
            ^<HOST> .* "POST .*/xmlrpc\.php

ignoreregex =

Step 3. Restart Fail2Ban

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.

For more insights on securing your Linux server, we recommend giving 7 Quick and Easy Ways to Secure SSH on a Linux Server and The 7 Best Linux Firewalls as of 2025 a read.

Need hosting?

If you're looking to host on reliable infrastructure, xTom provides a range of solutions including dedicated servers, colocation services, and IP transit.

For affordable, flexible, and scalable virtual private servers, check out V.PS for NVMe-powered VPS hosting.