How to Install and Configure Fail2ban on Linux: Block SSH and Web Server Brute-Force Attacks

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Just spin up a brand-new Linux VPS and open the public SSH port, then check your authentication logs: hundreds of automated bots from all over the world are hammering away, attempting to brute-force the root password every minute. If you rely on a simple password, your server could be compromised at any moment.

Fail2ban is the classic, go-to tool to eliminate this headache. It continuously scans system log files, detects IPs showing signs of repeated failed login attempts, and automatically creates firewall rules (using iptables or nftables) to ban those IPs on the spot.

1. Quick Start: Install and Enable SSH Protection in 5 Minutes

To get started quickly on Ubuntu/Debian or CentOS/AlmaLinux, simply follow these steps in order.

Installing Fail2ban

On Ubuntu or Debian:

sudo apt update
sudo apt install -y fail2ban

On RHEL/AlmaLinux/Rocky Linux (requires enabling the EPEL repository first):

sudo dnf install -y epel-release
sudo dnf install -y fail2ban

Creating a Dedicated Configuration File

A golden rule with Fail2ban is to never directly edit the original /etc/fail2ban/jail.conf file, as package updates will overwrite it. Instead, create a jail.local file:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Quick SSH Protection Setup

Open /etc/fail2ban/jail.local using your preferred text editor:

sudo nano /etc/fail2ban/jail.local

Locate the [sshd] block or append the following configuration to the end of the file:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(syslog_backend)s
maxretry = 5
findtime = 600
bantime = 3600

Starting the Service

Save the file and run the following commands to start Fail2ban:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

Verify whether the SSH protection jail is active:

sudo fail2ban-client status sshd

2. Deep Dive: Core Fail2ban Configuration Parameters

Once you have this basic shield in place, it helps to understand the underlying mechanics so you can fine-tune them for your specific environment.

Default Parameters (DEFAULT Section)

Inside the jail.local file, the most critical parameters include:

  • ignoreip: A list of trusted IPs that should never be banned. For example, your static office IP, home IP, or internal subnets (127.0.0.1/8 ::1 192.168.1.0/24).
  • bantime: The duration (in seconds) an offending IP remains banned. For example, 3600 equals 1 hour. To ban permanently, you can set a negative number (-1).
  • findtime: The time window (in seconds) in which Fail2ban tallies failed login attempts.
  • maxretry: The maximum number of failed attempts permitted within findtime before an IP is blacklisted.

For example: With findtime = 600 and maxretry = 3, if an IP fails SSH authentication 3 times within 10 minutes, it is immediately banned for the duration defined by bantime.

Understanding Jails and Filters

Fail2ban operates on two primary components:

  • Filter: Located in /etc/fail2ban/filter.d/, containing regular expressions (regex) designed to match failed authentication patterns in log files.
  • Jail: Pairs a Filter with an Action (such as blocking traffic via iptables/nftables or sending email alerts) applied to a specific service.

3. Advanced: Extending Protection to Nginx and Web Servers

Beyond safeguarding SSH, Fail2ban is exceptionally effective at stopping directory traversal vulnerability scans and brute-force attacks against administrative login portals (such as wp-login.php on WordPress).

Blocking Malicious URL Scanning on Nginx

Open /etc/fail2ban/jail.local and configure an additional jail to block repeated queries probing for sensitive files that trigger 404/403 HTTP status codes:

[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 300
bantime = 86400

Blocking Brute-Force Attacks on WordPress / Web App Login Pages

Create a custom filter to catch rapid POST requests targeted at authentication endpoints. Create the file /etc/fail2ban/filter.d/nginx-login.conf:

[Definition]
failregex = ^<HOST> -.* "POST /wp-login.php HTTP/.*" 200
            ^<HOST> -.* "POST /login HTTP/.*" 200
ignoreregex =

Next, add the corresponding jail block to /etc/fail2ban/jail.local:

[nginx-login]
enabled = true
port = http,https
filter = nginx-login
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 7200

Reload the configuration so the new jails take effect immediately:

sudo fail2ban-client reload

4. Administration and Practical Production Tips

After managing over 10 Linux VPSs for three years, I’ve learned that thorough testing before pushing to production is essential. I once had a colleague mistype their VPN/SSH password, and Fail2ban locked out our entire office IP during peak business hours simply because someone forgot to add it to the whitelist.

Essential Daily Management Commands

View active jails and the count of banned IPs:

sudo fail2ban-client status

Inspect detailed information and currently banned IPs for the sshd jail:

sudo fail2ban-client status sshd

If you or a teammate accidentally get banned, unban the IP immediately using:

sudo fail2ban-client set sshd unbanip 203.0.113.45

Inspect the Fail2ban activity log directly for troubleshooting:

sudo tail -f /var/log/fail2ban.log

Battle-Tested Best Practices

  • Always whitelist your office and personal IPs: Add your static IP or subnet to ignoreip before enabling any jail with an aggressive bantime.
  • Be cautious when changing SSH ports: If you switch the default SSH port from 22 to something like 2222, remember to update the port = 2222 line in the [sshd] section of jail.local. Otherwise, Fail2ban will block port 22 while leaving the new port completely unprotected.
  • Test your regex before enabling: Use Fail2ban’s built-in testing utility to verify that your filter matches log entries accurately before running it in production:
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-login.conf

Mastering Fail2ban gives your system a proactive defense layer, filtering out up to 99% of automated botnet scans with minimal server overhead.

Share: