How to Set Up and Configure Fail2ban on Your VPS for SSH Brute-Force Protection

SSH brute-force attacks are one of the most common threats facing any internet-connected VPS. Automated bots scan the entire IPv4 address space every few minutes, trying default credentials and common passwords. Fail2ban is a lightweight, open-source intrusion prevention tool that monitors log files for repeated failed authentication attempts and temporarily bans the offending IP addresses using iptables or nftables.

This guide covers installing Fail2ban on a Linux VPS (Ubuntu/Debian and CentOS/Rocky), configuring it for SSH protection, creating custom jail rules, and testing the setup to ensure it works correctly. Before you begin, make sure you have a non-root sudo user configured — you do not want to lock yourself out. If you are still choosing a provider, compare VPS providers for your security setup to find one with strong DDoS protection and firewall options.

Prerequisites

  • A Linux VPS running Ubuntu 20.04+, Debian 11+, CentOS Stream 8, or Rocky Linux 8+
  • Root or sudo access
  • SSH access configured with key-based authentication (optional but recommended)

Step 1: Install Fail2ban

Ubuntu / Debian

sudo apt update
sudo apt install fail2ban -y

CentOS / Rocky Linux / AlmaLinux

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

After installation, Fail2ban starts automatically. Verify the service status:

sudo systemctl status fail2ban

Step 2: Configure Fail2ban for SSH Protection

Fail2ban uses a two-file configuration system: jail.conf (default, overwritten on updates) and jail.local (your custom settings, persistent). Never edit jail.conf directly — create or edit /etc/fail2ban/jail.local instead.

Create or edit jail.local:

sudo nano /etc/fail2ban/jail.local

Add the following configuration:

[DEFAULT]
# Ban IPs for 1 hour (3600 seconds)
bantime = 3600

# Find failed attempts within the last 10 minutes
findtime = 600

# Max 5 failed attempts before banning
maxretry = 5

# Ban action: use iptables (or nftables on newer systems)
banaction = iptables-multiport

# Ignore these IPs (never ban your own IP)
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Explanation of key settings:

  • bantime: How long an IP is banned (in seconds). 3600 = 1 hour. Set to -1 for permanent ban.
  • findtime: The window of time (in seconds) in which failed attempts are counted.
  • maxretry: Number of failed attempts allowed within findtime before a ban is triggered.
  • ignoreip: IP addresses that should never be banned. Add your own public IP here.

Step 3: Customizing for Non-Standard SSH Ports

If you changed your SSH port from the default 22, update the [sshd] section:

[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Step 4: Creating Custom Jails

Fail2ban ships with dozens of pre-configured jails for services like Apache, Nginx, Postfix, Dovecot, and WordPress. Enable them by adding sections to jail.local. Here is an example for Nginx and WordPress:

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log

[wordpress]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 300
bantime = 1800

To see all available jails on your system: ls /etc/fail2ban/jail.d/ and ls /etc/fail2ban/filter.d/.

Step 5: Restart and Verify Fail2ban

After editing the configuration, restart Fail2ban:

sudo systemctl restart fail2ban

Check the status of all jails:

sudo fail2ban-client status

Check the SSH jail specifically:

sudo fail2ban-client status sshd

You should see output showing the number of currently banned IPs and the total number of failures. Example output:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 12
|  `- File list: /var/log/auth.log
`- Actions
   |- Currently banned: 3
   |- Total banned: 7
   `- Banned IP list: 45.33.32.156 185.220.101.42 103.235.46.94

Step 6: Testing the Configuration

Important: Run this test from a separate terminal session so you do not lock yourself out of your current SSH connection.

Simulate brute-force attacks by attempting SSH logins with incorrect passwords from another machine:

# From another machine, attempt 6 failed logins
ssh nonexistent@your-server-ip
# (enter wrong password 6 times)

After the 5th failed attempt (per our maxretry setting), the IP should be banned. Check the Fail2ban logs:

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

You should see entries like:

2025-12-01 14:32:15,123 fail2ban.actions [1234]: NOTICE  [sshd] Ban 203.0.113.42

To unban an IP manually (e.g., if you accidentally locked yourself out via a second IP):

sudo fail2ban-client set sshd unbanip 203.0.113.42

Step 7: Advanced Configuration

Recidive Jail (Permanent Ban for Repeat Offenders)

Add a recidive jail to permanently ban IPs that keep getting banned repeatedly:

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = iptables-multiport
bantime = 604800   # 1 week
findtime = 86400   # 24 hours
maxretry = 3

Email Notifications

To receive email alerts when an IP is banned, add to jail.local:

[DEFAULT]
destemail = [email protected]
sendername = Fail2ban
mta = sendmail
action = %(action_mwl)s

Conclusion

Fail2ban is one of the most effective and lightweight security tools you can deploy on a VPS. With the simple configuration above, you can block thousands of brute-force attempts per day with minimal CPU or memory overhead. The key is to start with sensible defaults (bantime=1h, maxretry=5) and adjust based on your own usage patterns — you may find that setting maxretry to 3 is too strict if you frequently mistype your password.

For a comprehensive security setup, combine Fail2ban with SSH key-only authentication, a properly configured firewall (UFW or firewalld), and automatic security updates. Compare VPS providers for your security setup to find a host that offers robust firewall, DDoS protection, and a secure default configuration.

Leave a Reply