AI Chat

Setting Up Fail2Ban to Block Brute-Force SSH Attacks on a Dedicated Server

Fail2Ban Block SSH Brute Force Attacks Dedicated Server
Ask AI to extract steps & commands from this tutorial:

Within minutes of a dedicated server getting a public IP, automated bots start knocking on SSH. Not targeted attacks — mass scans, working through credential lists, trying root/admin with thousands of common passwords, all day, every day. SSH key authentication stops them from getting in, but it doesn't stop them from trying, and a server can end up processing hundreds of failed login attempts a day just sitting there.

Fail2Ban is the standard answer to this. It watches your authentication logs, and once an IP crosses a threshold of failed attempts, it automatically bans that IP at the firewall level — no manual intervention needed. This guide covers installing it, setting up the SSH jail properly, and confirming it's actually banning IPs before you rely on it.

Who This Guide Is For

This is for anyone running a dedicated server or VPS with SSH exposed to the internet who wants automated protection against brute-force login attempts, on top of (not instead of) SSH key authentication.

Prerequisites

  • A Linux server running Ubuntu 24.04 (or a recent Debian-based distro — the package and config paths are the same).

  • Root or sudo access.

  • SSH already working normally, ideally with key-based authentication already set up.

  • A second way to reach the server — console access, a hosting provider's KVM/IPMI panel, or a second SSH session kept open — before you start changing firewall behavior.

That last point matters more than it sounds like. A misconfigured jail can ban your own IP, and if SSH is your only way in, that's a support ticket instead of a 30-second fix. Keep a fallback session open while you test.

Step 1: Install Fail2Ban

Update your package index and install Fail2Ban from Ubuntu's repository:

bash

sudo apt update
sudo apt install -y fail2ban
                            

Enable and start the service:

bash

sudo systemctl enable --now fail2ban
                            

Confirm it's running:

bash

sudo systemctl status fail2ban
                            

You should see active (running). Out of the box, Fail2Ban ships with the SSH jail already defined but check its actual status in Step 4 — "installed" isn't the same as "actively watching."

Step 2: Create a Local Configuration File

Fail2Ban's main config file is /etc/fail2ban/jail.conf. Don't edit it directly — package updates overwrite it, and you'll lose your changes. Instead, copy it to jail.local, which Fail2Ban reads as an override:

bash

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

From here on, all your edits go in jail.local, never jail.conf.

Step 3: Configure the SSH Jail

Open the local config file:

bash

sudo nano /etc/fail2ban/jail.local
                            

First, find the [DEFAULT] section near the top and set ignoreip to include your own IP address, so you can never accidentally ban yourself:

ini

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_OWN_IP_HERE
                            

Replace YOUR_OWN_IP_HERE with your actual current public IP (check it with curl ifconfig.me from your own machine, not the server). If you manage this server from more than one location — home and office, for example — add all of those IPs here, space-separated.

Next, find the [sshd] section and set the ban behavior:

ini

[sshd]
enabled = true
port = ssh
maxretry = 5
findtime = 10m
bantime = 1h
                            

What these actually control:

  • maxretry — how many failed attempts are allowed before a ban.

  • findtime — the time window those failures have to happen within to count. Five failures spread across three days won't trigger a ban; five failures in ten minutes will.

  • bantime — how long the ban lasts. 1h means one hour; you can also use 1d for a day, or -1 for a permanent ban.

If your server uses a non-standard SSH port instead of the default 22, set that explicitly instead of relying on port = ssh:


port = 2222
                            

Save the file and exit.

Step 4: Restart Fail2Ban and Verify the Jail Is Active

Apply your changes:

bash

sudo systemctl restart fail2ban
                            

Check that the SSH jail is actually enabled and running:

bash

sudo fail2ban-client status
                            

This lists active jails — you should see sshd in the list. For details on that specific jail, including current bans:

bash

sudo fail2ban-client status sshd
                            

This shows the number of failed attempts, currently banned IPs, and total bans since the jail started.

Step 5: Test That It Actually Works

Don't assume it's working — confirm it. From a different machine (not your whitelisted IP), attempt to SSH into the server with an intentionally wrong password, repeating past your maxretry threshold:

bash

ssh [email protected]
                            

After the number of failed attempts set in maxretry, that IP should be refused entirely — the connection will hang or get actively rejected. Back on the server, confirm the ban registered:

bash

sudo fail2ban-client status sshd
                            

The test IP should now appear under "Banned IP list." You can also check the raw log directly:

bash

sudo tail -f /var/log/fail2ban.log
                            

Step 6: Manage Bans Manually When Needed

To unban a specific IP — useful if you test-banned yourself or a legitimate user got caught:

bash

sudo fail2ban-client set sshd unbanip 203.0.113.89
                            

To clear every ban across all jails at once:

bash

sudo fail2ban-client unban --all
                            

Step 7: Confirm the Firewall Integration

Fail2Ban doesn't block traffic itself — it works by dynamically inserting rules into your existing firewall (UFW, iptables, or nftables, depending on your setup). If you're running UFW, confirm the ban action is actually configured to use it rather than a default that bypasses your existing firewall rules. Check the banaction setting in jail.local:


banaction = ufw
                            

If this is missing or set to something else while you're running UFW as your primary firewall, Fail2Ban may be creating rules through a different backend that don't align with your existing setup. Match banaction to whatever firewall you're actually running.

Going Further: Protecting Other Services

SSH is usually the priority, but Fail2Ban ships with filters for plenty of other services out of the box — Nginx, Apache, Postfix, and more. Enabling a jail for any of them follows the same pattern: find the relevant section in jail.local, set enabled = true, and adjust maxretry/bantime as needed.

For repeat offenders — an IP that keeps coming back after its ban expires — the built-in recidive jail escalates the punishment automatically by watching Fail2Ban's own log for IPs that get banned repeatedly, and applying a longer ban the second time around. This is usually a better long-term approach than setting a permanent ban on every jail by default.

Common Errors and How to Fix Them

Error Symptom How to Fix It
You've locked yourself out If you still have console/KVM access through your hosting provider, log in that way and run sudo fail2ban-client set sshd unbanip YOUR_IP. This is exactly why keeping a fallback access method before starting was step one.
The jail shows enabled but never bans anything Usually a log path or backend mismatch. Check sudo fail2ban-client status sshd for the log path being monitored. On systemd-based systems, this is sometimes the journal rather than a flat file, which needs backend = systemd set in the jail.
Failed logins aren't triggering a ban fast enough Double check findtime and maxretry are set correctly. A large findtime window with a high maxretry count will tolerate far more failed attempts than you might assume before banning.
Fail2Ban service won't start after editing jail.local This is almost always a syntax error in the config file. Check the service logs for the specific line: sudo journalctl -u fail2ban -n 50.

Next Steps

Fail2Ban is one layer of server security, not the whole picture. If you haven't already, make sure SSH key authentication is enforced and password login is disabled, and confirm your firewall (UFW or otherwise) is configured with only the ports you actually need open. Once SSH is locked down, the same jail pattern here extends naturally to protecting any other public-facing service on the server, like Nginx or Apache, using the same jail.local file.

Frequently Asked Questions

Does Fail2Ban replace the need for SSH key authentication? +

No. Fail2Ban reduces the noise and risk from brute-force attempts, but it's a second layer, not a replacement. Disabling password authentication entirely and relying on SSH keys remains the stronger underlying protection — Fail2Ban is what catches everything that gets past or around that.

Does changing my SSH port help? +

It reduces the volume of automated scanning noise your logs pick up, since most bots only probe the default port 22. It's not a real security measure on its own though — a determined attacker running a full port scan will still find a moved SSH port. Treat it as noise reduction, not protection.

Will Fail2Ban ban legitimate users who mistype their password a few times? +

It can, if maxretry is set too aggressively low. A maxretry of 5 within a 10-minute findtime is a reasonable starting point that tolerates normal typos while still catching automated attempts, which typically fire far more than 5 attempts in that window.

How do I know if Fail2Ban is actually stopping real attacks, not just installed and idle? +

Check sudo fail2ban-client status sshd periodically — the "Total banned" counter climbing over time confirms it's actively catching and blocking attempts, not just sitting there enabled and unused.

Our Bandwidth providers

We are Partners with 15 +

At eServers , we proudly partner with 15+ leading global tech providers to deliver secure, high-performance hosting solutions. These trusted alliances with top hardware, software, and network innovators ensure our clients benefit from modern technology and enterprise-grade reliability.

Hosting Solutions