📑 Daftar Isi
- Why Brute Force SSH Is Worth Worrying About
- Before You Start: Three Quick Checks
- Step 1: Install Fail2ban
- Step 2: Back Up the Config First
- Step 3: Configure the SSH Jail
- Step 4: Restart and Verify
- Step 5: Test the Brute Force Protection
- Troubleshooting Common Fail2ban Issues
- Field-Tested Tips
- FAQ: Fail2ban and SSH Security
- Q: Is fail2ban safe to run on a production server?
- Q: Why did I get banned from my own server?
- Q: Is fail2ban enough if I keep port 22?
- Q: How do I unban an IP?
- Q: Does fail2ban work on every Linux distro?
- Bottom Line
Skip the fluff. If your server is exposed to the internet and port 22 is open, bots are already hammering it. I see it every single day in auth.log. It’s not a matter of if they’ll find a weak password — it’s a matter of when. Fail2ban is the fastest way to shut that down, and this guide gets you there in five steps.
Here’s a real slice from a client’s auth.log last week. Two IPs, twelve failed attempts in under a minute:
Jul 22 03:11:42 server-01 sshd[22341]: Failed password for root from 203.0.113.10 port 52310 ssh2
Jul 22 03:11:45 server-01 sshd[22344]: Failed password for root from 203.0.113.10 port 52311 ssh2
Jul 22 03:11:47 server-01 sshd[22347]: Failed password for root from 203.0.113.10 port 52312 ssh2
Jul 22 03:11:49 server-01 sshd[22350]: Failed password for root from 198.51.100.42 port 45121 ssh2
Jul 22 03:11:52 server-01 sshd[22353]: Failed password for root from 198.51.100.42 port 45122 ssh2
Jul 22 03:11:55 server-01 sshd[22356]: Failed password for root from 198.51.100.42 port 45123 ssh2
Jul 22 03:12:01 server-01 sshd[22359]: Failed password for root from 203.0.113.10 port 52313 ssh2
Jul 22 03:12:03 server-01 sshd[22362]: Failed password for root from 198.51.100.42 port 45124 ssh2
Jul 22 03:12:08 server-01 sshd[22365]: Failed password for root from 203.0.113.10 port 52314 ssh2
Jul 22 03:12:12 server-01 sshd[22368]: Failed password for root from 198.51.100.42 port 45125 ssh2
Jul 22 03:12:15 server-01 sshd[22371]: Failed password for root from 203.0.113.10 port 52315 ssh2
Jul 22 03:12:18 server-01 sshd[22374]: error: maximum authentication attempts exceeded for root from 198.51.100.42 port 45126 ssh2
See the pattern? Same IP, same username, ports ticking up every few seconds. That’s not a person guessing. That’s a bot, and it doesn’t sleep.
Every failed login costs you CPU, bandwidth, and log space. But the real damage happens when the attacker actually gets in. Weak passwords like admin123 or password fall within minutes. Once in, they’ll install crypto miners, read client data, or use your box to attack others. I cleaned up a server last month that had been running a miner for two weeks without anyone noticing. The client only called after their bandwidth bill doubled.
So here’s the deal. Fail2ban is your doorman. It watches the logs, spots an IP that fails login too many times in a short window, and hands that IP to your firewall to drop. That’s it. Simple, proven, and running on millions of servers. In this guide I’ll show you how to install it, configure the sshd jail properly, and test that it actually works. Commands below are tested on Debian 12 and Ubuntu 22.04.
Why Brute Force SSH Is Worth Worrying About
SSH is the default remote access protocol, and port 22 is basically a public highway. The moment a fresh server gets a public IP, scanners find it within hours. Think of it as a house with the address painted on the gate — everyone knows where the front door is. Your job is to make that door hard to get through.
Brute force is exactly what it sounds like: trying username/password combos over and over. Usernames are usually root, admin, oracle. Passwords come straight from leaked databases. Fail2ban stops this far earlier than any password policy ever could — it blocks the attacker’s IP at the firewall level before they even get a real chance to guess.
Before You Start: Three Quick Checks
Do these three things first. All three have locked someone out of their own server before.
- Set up SSH keys first. If you haven’t, run
ssh-copy-id user@serverfrom your laptop. Fail2ban doesn’t care that you’re the admin — if your IP gets banned, you’re locked out too. - Make sure you have root or sudo. Every command here needs privileges.
- Note your office or home IP. You’ll put it in
ignoreipso you never get banned.

Step 1: Install Fail2ban
On Debian/Ubuntu, fail2ban ships in the official repos. No third-party repo needed.
sudo apt update
sudo apt install fail2ban -y
Enable the service so it starts on boot:
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
You should see active (running). If not, check journalctl -u fail2ban -n 50.
Step 2: Back Up the Config First
Never edit jail.conf directly — package updates will overwrite it. Fail2ban gives you the right way to do this:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
jail.local overrides the defaults, so all your changes go there. Package updates won’t touch it. Optional but recommended: wipe it and write fresh so your config only contains what matters.
sudo nano /etc/fail2ban/jail.local
Step 3: Configure the SSH Jail
This is the core part. Put this in jail.local:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
bantime = 1h
findtime = 10m
maxretry = 5
banaction = nftables-multiport
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
Breakdown, so you’re not blindly copy-pasting:
| Parameter | Meaning | Example Value |
|---|---|---|
ignoreip |
IPs that will never be banned. Put your office/home IP here. | 203.0.113.50 |
maxretry |
Max failed attempts before an IP gets banned. | 5 |
findtime |
The window for counting failed attempts. | 10m |
bantime |
Ban duration. 1h, 1d, or -1 for permanent. |
1h |
banaction |
Firewall backend used to enforce the ban. | nftables-multiport |
Translation: any IP that fails login 5 times within 10 minutes gets banned for 1 hour. Simple and sensible. Don’t jump straight to bantime = -1 at the start — if you misconfigure something, you can lock yourself out forever. Get access secured first, then get aggressive.
On CentOS/RHEL, change logpath to /var/log/secure. If you moved SSH off port 22, change port to match.
Step 4: Restart and Verify
jail.local, (2) tested config syntax with sudo fail2ban-client -t, and (3) added your own IP to ignoreip. A bad config can drop live connections.Test the config syntax first so typos don’t kill the service:
sudo fail2ban-client -t
If it prints OK, restart:
sudo systemctl restart fail2ban
Then confirm the sshd jail is active:
sudo fail2ban-client status sshd
Expected output looks like this:
Status for the jail: sshd
|- Filter
| |- Currently failed: 3
| |- Total failed: 47
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 1
|- Total banned: 6
`- Banned IP list: 203.0.113.10
Once you see a banned IP in the list, fail2ban is working.
Step 5: Test the Brute Force Protection
Now let’s actually test it. Never test from the server itself — you’ll ban localhost and cause problems. Test from another machine, your laptop or another VPS.
From the other machine, try SSH with a wrong password six times:
ssh root@SERVER_IP
After the fifth failure, the connection will hang. That’s your IP getting dropped at the firewall. Confirm from the server:
sudo fail2ban-client status sshd
No second machine handy? Ban an IP manually to verify the action works:
sudo fail2ban-client set sshd banip 198.51.100.42
And unban when you’re done:
sudo fail2ban-client set sshd unbanip 198.51.100.42

Troubleshooting Common Fail2ban Issues
Things don’t always go smoothly. Here’s what I run into most:
| Symptom | Cause | Fix |
|---|---|---|
| IP never gets banned | Wrong logpath or mismatched filter |
Verify with sudo fail2ban-client get sshd logpath; run sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf |
| fail2ban service won’t start | Config syntax error | Run sudo fail2ban-client -t and fix the highlighted line |
| You banned your own IP | IP not in ignoreip |
Add it, restart, then unban with fail2ban-client set sshd unbanip YOUR_IP |
| Ban does nothing, IP still logs in | banaction doesn’t match active firewall |
Check your firewall; on modern Debian/Ubuntu use nftables-multiport or ufw |
Field-Tested Tips
Bonus advice from years of doing this. Hopefully you won’t have to learn these the hard way.
- Fail2ban is layer one, not the whole story. Combine it with SSH hardening — key-based auth, password login disabled, and a non-default port if your setup allows.
- Install it before you need it. Don’t wait until your auth.log has 50,000 failed attempts. Five minutes now beats three hours of cleanup later.
- Keep bantime humane. Start at 1 hour. Raise it only if attack intensity grows.
- Monitor it. Glance at fail2ban status during your morning log check, or feed it into Netdata and friends.
- Don’t neglect the main firewall. Fail2ban enforces bans through your firewall, so make sure UFW or nftables is configured right and port 22 (or your SSH port) is allowed.
FAQ: Fail2ban and SSH Security
Q: Is fail2ban safe to run on a production server?
Yes. It’s the standard tool running on millions of servers worldwide. The key is putting your own IP in ignoreip and testing config syntax with fail2ban-client -t before any restart. Never restart blindly.
Q: Why did I get banned from my own server?
Fail2ban doesn’t know you’re the admin — it just reads logs and bans IPs that fail repeatedly. Fix it by adding your IP to ignoreip, restarting, and running sudo fail2ban-client set sshd unbanip YOUR_IP.
Q: Is fail2ban enough if I keep port 22?
It will block 99% of automated brute force. But default port 22 still gets scanned constantly and fills your logs with noise. Best combo: fail2ban + SSH keys + non-default port. Security by obscurity isn’t the whole answer, but it cuts the noise dramatically.
Q: How do I unban an IP?
Run sudo fail2ban-client set sshd unbanip 203.0.113.10, replacing the jail name and IP. To unban everything: sudo fail2ban-client unban --all.
Q: Does fail2ban work on every Linux distro?
Yes. Debian/Ubuntu: apt install fail2ban. CentOS/RHEL: dnf install fail2ban. The only real difference is log location: /var/log/auth.log on Debian/Ubuntu, /var/log/secure on CentOS/RHEL.
Bottom Line
That’s the whole process — five steps, fifteen minutes, and your SSH is dramatically harder to brute force. Do it before you wake up to a crypto miner on a production box. That’s a lesson I’d rather you not learn in person.
Install it now, add your SSH keys, and don’t forget ignoreip. While you’re at it, learn to read auth logs so you can spot attacks on your own. Done. You can close this tab.