Fail2ban is a tool that protects your server against brute force attacks by monitoring system logs and automatically blocking IP addresses that show malicious behavior. This guide explains how to install and configure fail2ban to protect the SSH service.
How It Works
Fail2ban analyzes log files looking for patterns of failed authentication attempts. When an IP exceeds the allowed number of attempts within a time period, fail2ban adds a firewall rule to temporarily block that IP.
Prerequisites
- Root or sudo access to the server
- Server running Ubuntu/Debian or AlmaLinux/CentOS/RHEL
Step 1: Install fail2ban
Ubuntu / Debian
sudo apt update
sudo apt install fail2ban -yAlmaLinux / CentOS / RHEL
sudo dnf install epel-release -y
sudo dnf install fail2ban -yStep 2: Configure fail2ban
Fail2ban uses configuration files in /etc/fail2ban/. Never edit the original files (jail.conf, fail2ban.conf) as they get overwritten during updates. Instead, create .local files that take priority.
Create the local configuration file
sudo nano /etc/fail2ban/jail.localAdd the following configuration:
[DEFAULT]
# Ban time in seconds (1 hour)
bantime = 3600
# Time window to count failed attempts (10 minutes)
findtime = 600
# Number of failed attempts before banning
maxretry = 5
# Ignore local and trusted IPs (space-separated)
ignoreip = 127.0.0.1/8 ::1
# Default action: block with iptables
banaction = iptables-multiport
# Email for notifications (optional)
# destemail = admin@yourdomain.com
# sender = fail2ban@yourdomain.com
# action = %(action_mwl)s
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600Note: If using AlmaLinux/CentOS/RHEL, change the log path:
logpath = /var/log/secureConfiguration with custom SSH port
If you changed the default SSH port (for example, to 2222), modify the port line:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600Configuration with progressive banning
For bans that increase with each repeat offense, add:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
bantime = 604800
findtime = 86400
maxretry = 3This configuration bans for one week (604800 seconds) IPs that have been banned 3 times in the last 24 hours.
Step 3: Start and enable fail2ban
sudo systemctl start fail2ban
sudo systemctl enable fail2banVerify the service is running:
sudo systemctl status fail2banStep 4: Verify the configuration
View active jails status
sudo fail2ban-client statusExpected output:
Status
|- Number of jail: 1
`- Jail list: sshdView SSH jail details
sudo fail2ban-client status sshdExpected output:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 5
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 1
|- Total banned: 2
`- Banned IP list: 192.168.1.100View firewall rules
sudo iptables -L -n | grep -A 10 fail2banManaging fail2ban
Unban an IP manually
sudo fail2ban-client set sshd unbanip 192.168.1.100Ban an IP manually
sudo fail2ban-client set sshd banip 192.168.1.100Reload configuration
After modifying configuration files:
sudo fail2ban-client reloadView fail2ban log
sudo tail -f /var/log/fail2ban.logAdditional recommended configurations
Protect other services
You can add jails for other services in /etc/fail2ban/jail.local:
# Protect Apache
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/*error.log
maxretry = 3
bantime = 3600
# Protect Nginx
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/*error.log
maxretry = 3
bantime = 3600
# Protect Postfix
[postfix]
enabled = true
port = smtp,465,submission
filter = postfix
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
# Protect Dovecot
[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps
filter = dovecot
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600Use nftables instead of iptables
On modern systems using nftables:
[DEFAULT]
banaction = nftables-multiportConfigure email notifications
To receive notifications when an IP is banned:
[DEFAULT]
destemail = admin@yourdomain.com
sender = fail2ban@yourdomain.com
mta = sendmail
action = %(action_mwl)sTroubleshooting
Fail2ban is not banning IPs
- Verify the log path is correct:
# Ubuntu/Debian
ls -la /var/log/auth.log
# AlmaLinux/CentOS
ls -la /var/log/secure- Confirm the filter detects failed attempts:
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf- Check the fail2ban log:
sudo tail -50 /var/log/fail2ban.logService won't start
- Check for syntax errors in configuration:
sudo fail2ban-client -t- Check system logs:
sudo journalctl -u fail2ban -n 50I banned myself
If you have physical or console access to the server:
sudo fail2ban-client set sshd unbanip YOUR_IPIf you don't have access, wait for the configured bantime or access through another method (KVM console, IPMI, provider panel).
To prevent this, add your IP to the ignore list:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_STATIC_IPIPs get unbanned after restart
By default, fail2ban doesn't persist bans between restarts. To enable persistence, add:
[DEFAULT]
banaction = iptables-multiport
banaction_allports = iptables-allports
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
# Save bans to database
backend = systemdOr create a script that restores bans from /var/lib/fail2ban/fail2ban.sqlite3.
Best Practices
-
Don't ban for too long: A
bantimeof 1-24 hours is sufficient for most attacks. - Add your IPs to ignoreip: Avoid accidentally banning yourself.
-
Monitor the logs: Periodically review
/var/log/fail2ban.log. - Combine with SSH keys: Fail2ban complements, not replaces, public key authentication.
- Keep fail2ban updated: Updates include new filters and security fixes.