Install and configure fail2ban on VPS servers to automatically ban IP addresses that show malicious signs like too many password failures, seeking exploits, or brute-force attacks.
Configure fail2ban to automatically protect servers against brute-force attacks by banning malicious IP addresses.
This skill helps AI agents install and configure fail2ban on VPS servers. Even with SSH keys configured, bots will constantly hammer your server with login attempts. Fail2ban monitors log files and automatically bans IP addresses that show malicious behavior, such as too many password failures.
Key capabilities:
Use this skill when you need to:
Critical understanding: Three failed attempts in 10 minutes = banned for an hour. This drastically reduces brute-force attack effectiveness.
sudo apt update
sudo apt install fail2ban -y
sudo yum install epel-release -y
sudo yum install fail2ban -y
sudo systemctl status fail2ban
CRITICAL: Never edit jail.conf directly. It gets overwritten on updates!
Create a local configuration file:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Edit the local configuration:
sudo nano /etc/fail2ban/jail.local
Find and update these settings in jail.local:
[DEFAULT]
# Ban time in seconds (1 hour)
bantime = 3600
# Find time window (10 minutes)
findtime = 600
# Number of failures before ban
maxretry = 3
# Destination email for notifications (optional)
destemail = admin@example.com
# Sender email
sendername = Fail2Ban
# Email action
action = %(action_)s
# Or with email: %(action_mwl)s
Find the [sshd] section and configure:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
For custom SSH port:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Verify it's running:
sudo systemctl status fail2ban
Add jails for other services in /etc/fail2ban/jail.local:
Nginx/Apache (HTTP Auth):
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 3
WordPress:
[wordpress-auth]
enabled = true
port = http,https
filter = wordpress-auth
logpath = /var/log/auth.log
maxretry = 3
FTP:
[proftpd]
enabled = true
port = ftp,ftp-data,ftps,ftps-data
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 3
Different ban times for different severity:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600 # 1 hour
findtime = 600 # 10 minutes
[sshd-aggressive]
enabled = true
port = ssh
filter = sshd-aggressive
logpath = /var/log/auth.log
maxretry = 1
bantime = 86400 # 24 hours
findtime = 3600 # 1 hour
For repeated offenders:
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
bantime = 604800 # 1 week
findtime = 86400 # 1 day
maxretry = 3
Never ban trusted IPs:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10 192.168.1.0/24
Enable email alerts:
[DEFAULT]
destemail = admin@example.com
sendername = Fail2Ban
mta = sendmail
# Action with email
action = %(action_mwl)s
# Overall status
sudo fail2ban-client status
# Specific jail status
sudo fail2ban-client status sshd
# List banned IPs for SSH
sudo fail2ban-client status sshd
# List all banned IPs
sudo fail2ban-client banned
# Unban specific IP from specific jail
sudo fail2ban-client set sshd unbanip 203.0.113.100
# Unban from all jails
sudo fail2ban-client unban 203.0.113.100
sudo fail2ban-client set sshd banip 203.0.113.100
Test if a filter matches log lines:
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# View fail2ban log
sudo tail -f /var/log/fail2ban.log
# View recent bans
sudo grep "Ban" /var/log/fail2ban.log
# View unbans
sudo grep "Unban" /var/log/fail2ban.log
Fail2ban adds rules to iptables/UFW:
# View iptables rules
sudo iptables -L -n
# View fail2ban chains
sudo iptables -L fail2ban-sshd -n
# View UFW status
sudo ufw status numbered
# Count bans by jail
sudo fail2ban-client status | grep "Jail list"
# Count current bans
sudo fail2ban-client status sshd | grep "Currently banned"
# Total bans
sudo fail2ban-client status sshd | grep "Total banned"
/etc/fail2ban/fail2ban.conf # Main fail2ban configuration
/etc/fail2ban/fail2ban.local # Local fail2ban config (create if needed)
/etc/fail2ban/jail.conf # Default jail configurations (don't edit!)
/etc/fail2ban/jail.local # Local jail overrides (edit this!)
/etc/fail2ban/jail.d/ # Additional jail configs
/etc/fail2ban/filter.d/ # Log file filters
/etc/fail2ban/action.d/ # Ban actions (iptables, ufw, etc.)
/var/log/fail2ban.log # Fail2ban log file
Create a custom filter for your application:
/etc/fail2ban/filter.d/myapp.conf:[Definition]
failregex = ^.*Failed login attempt from <HOST>.*$
^.*Invalid user .* from <HOST>.*$
ignoreregex =
/etc/fail2ban/jail.local:[myapp]
enabled = true
port = 8080
filter = myapp
logpath = /var/log/myapp/access.log
maxretry = 5
bantime = 3600
fail2ban-regex /var/log/myapp/access.log /etc/fail2ban/filter.d/myapp.conf
sudo systemctl reload fail2ban
# Restart fail2ban
sudo systemctl restart fail2ban
# Check status
sudo systemctl status fail2ban
# Reload without restarting (keeps existing bans)
sudo fail2ban-client reload
# Reload specific jail
sudo fail2ban-client reload sshd
/var/log/fail2ban.log# Check for syntax errors
sudo fail2ban-client -t
# View error logs
sudo journalctl -u fail2ban -n 50
# Check configuration
sudo fail2ban-client -d
# Check jail status
sudo fail2ban-client status
# View jail configuration
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd bantime
# Test filter against log
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Check log paths in jail configuration:
# Ubuntu/Debian SSH logs
/var/log/auth.log
# CentOS/RHEL SSH logs
/var/log/secure
# Nginx logs
/var/log/nginx/error.log
/var/log/nginx/access.log
# Unban your IP
sudo fail2ban-client set sshd unbanip YOUR.IP.ADDRESS
# Or stop fail2ban temporarily
sudo systemctl stop fail2ban
jail.conf instead of creating jail.localSee references/fail2ban-filters.md for common filter patterns.
See scripts/setup-fail2ban.sh for automated setup script.
ssh-hardening - Harden SSH before adding fail2banfirewall-configuration - Fail2ban works with UFW/iptablesauto-updates - Keep fail2ban updated