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
You must be logged in to post a comment.