fail2ban Setup on Ubuntu 22.04: Block Brute Force Attacks in 10 Minutes

Mar 15 02:14:50 sshd[1234]: Failed password for root
Mar 15 02:14:51 sshd[1235]: Failed password for root
Mar 15 02:14:52 sshd[1236]: Failed password for root
Mar 15 02:14:53 fail2ban: Ban 185.220.101.42
→ iptables: DROP 185.220.101.42

Within hours of deploying a public-facing Linux server, attackers start scanning for open SSH ports and attempting to brute-force login credentials. fail2ban automatically detects these patterns and bans the offending IPs using iptables. This guide gets you fully protected in under 10 minutes.

ℹ️

This guide uses Ubuntu 22.04 LTS. The commands work on Debian 11/12 with minor adjustments. For CentOS/RHEL, replace apt with dnf.

Step 1 — Install fail2ban

sudo apt update && sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Verify it's running:

sudo systemctl status fail2ban
# Should show: Active: active (running)

Step 2 — Create a Local Configuration

Never edit /etc/fail2ban/jail.conf directly — it gets overwritten on upgrades. Instead, create a local override:

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

Step 3 — Configure the SSH Jail

Open /etc/fail2ban/jail.local and find the [sshd] section. Update it:

[DEFAULT]
# Ban IPs for 1 hour after triggering a jail
bantime  = 1h

# Look back 10 minutes for failed attempts
findtime = 10m

# Ban after 5 failed attempts
maxretry = 5

# Email notification (optional — requires sendmail/postfix)
destemail = [email protected]
action    = %(action_mwl)s

[sshd]
enabled  = true
port     = ssh
logpath  = %(sshd_log)s
backend  = %(sshd_backend)s
maxretry = 3        # Stricter than default for SSH

Save and reload:

sudo systemctl reload fail2ban

Step 4 — Protect Nginx (Optional but recommended)

If you run a web server, add these jails to protect against HTTP brute-force and request floods:

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

[nginx-limit-req]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/error.log
maxretry = 10
💡

VeloxaHost's firewall rules run at the network level before traffic reaches your instance. fail2ban adds a second layer of protection at the OS level — defense in depth.

Step 5 — Verify fail2ban Is Working

# Check the status of all jails
sudo fail2ban-client status

# Check the SSH jail specifically
sudo fail2ban-client status sshd

# See currently banned IPs
sudo fail2ban-client status sshd | grep "Banned IP"

Sample output:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     47
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 3
   |- Total banned:     12
   `- Banned IP list:   185.220.101.42 168.138.167.201 193.32.162.80

Unbanning an IP

If you accidentally ban yourself (we've all done it):

sudo fail2ban-client set sshd unbanip YOUR.IP.ADDRESS

Whitelist Your Own IP

Add your office/home IP to the ignore list in jail.local:

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24   # Add your IP/subnet here

Aggressive Mode: Persistent Bans

For public-facing servers with high attack volume, increase the ban duration:

[DEFAULT]
bantime  = 1d      # 24-hour ban
findtime = 5m      # 5-minute window
maxretry = 3       # Only 3 attempts allowed

For repeat offenders, use exponential ban times (requires fail2ban 0.11+):

bantime.increment   = true
bantime.multiplier  = 1 5 30 60 300 720 1440 2880

Summary

With fail2ban configured, every attacker gets a maximum of 3–5 attempts before being blocked for an hour (or longer). Combined with SSH key-only authentication and VeloxaHost's network-level firewall, your server's attack surface is dramatically reduced.

Next: Read the full Zero-Trust Security Checklist →


Deploy hardened cloud instances on VeloxaHost — firewall rules, monitoring alerts, and fail2ban setup takes under 10 minutes. Start free →