SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-07

Install Fail2ban Ubuntu 24.04 Stop SSH Bots

For Ubuntu 24.04, plain apt install already bans SSH brute force. Check fail2ban-client status sshd, then fix am if Total failed stays at 0.

Wetín Fail2ban actually dey do

Fail2ban na daemon wey dey read logs. E dey monitor your SSH authentication messages. After e see several failed attempts from one address inside short time, e go run firewall command wey block that address for some time. Na the whole idea be that. Na about thirty lines of config for one file. For Ubuntu 24.04, installation na one apt command, and e go protect you before you edit anything.

Make you understand wetín e be and wetín e no be. Fail2ban no dey authenticate anybody. E no dey encrypt anything. E no dey stop one determined login attempt either. E only dey stop repeated attempts from the same source. Na noise filter and rate limiter e be, no be lock. E job na to stop the constant background scanning of port 22 from wasting your CPU, your bandwidth, and your log space. E also dey slow attacker wey must come from one address at a time.

Wetin Fail2ban no replace

Fail2ban na the third layer, e no be the first. If your server still dey accept SSH passwords, botnet wey spread across thousands of addresses fit continue to guess, because each address dey below your ban threshold and e never trigger am. The real defence against this na key-only authentication, wey make password guessing impossible no matter how many attempts anybody make. Fail2ban on top of key-only auth dey do two useful things: e remove brute-force noise from your logs, and e evict scanners early so dem stop hammering the port. Treat am as defence in depth. E dey behind key authentication and behind firewall; e no dey in front of dem.

Prerequisites, and Ubuntu 24.04 reality

You need VPS wey dey run Ubuntu 24.04, plus root or sudo access, and SSH wey don dey work already. E better make you dey use key authentication. Fail2ban no dey use plenty resource: na few tens of megabytes RAM, and you no need tune any limits.

Now, na here older guides dey commonly make mistake. For many years, standard advice be say, "install Fail2ban, then add backend = systemd, because Ubuntu stop writing /var/log/auth.log." That advice describe one real change. Modern server and cloud images dey ship without rsyslog, so SSH logs only go systemd journal, and that text file no dey again. But for Ubuntu 24.04, Fail2ban package don already handle this case. The package add /etc/fail2ban/jail.d/defaults-debian.conf, and na that file, no be upstream defaults, your server actually dey run:

[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd

[sshd]
enabled = true

Read this part well, because e answer two questions before you change anything. backend = systemd mean say SSH jail dey read the journal, so missing auth.log no be problem. banaction = nftables mean say bans dey enforce through nftables, wey be the firewall Ubuntu 24.04 actually dey use, instead of legacy iptables. And [sshd] enabled = true mean say the jail dey enabled from first boot. The main point be say: default apt install fail2ban for Ubuntu 24.04 go block SSH brute-force attacks out of the box. Most of your work na to confirm this, tune the policy, and make sure say you no lock yourself out.

The old auth.log problem still dey happen for three situations, and e good make you recognise dem: you install Fail2ban with pip instead of apt, so defaults-debian.conf no dey; you dey inside unprivileged container wey no get systemd journal to read; or you follow old tutorial and paste backend = auto inside your own jail.local, overriding the default wey dey work. The failure-modes section go show exactly how each one dey look.

Step 1: Install am confirm say e don dey ban already

sudo apt update
sudo apt install -y fail2ban

Ubuntu 24.04 release Fail2ban 1.0.2, and the package dey pull in python3-systemd as hard dependency, so journal backend get everything wey e need. The service enable and start by itself:

sudo systemctl status fail2ban

You want active (running). Then check the jail wey don already dey do im work:

sudo fail2ban-client status sshd

For public VPS wey don dey reachable even for some minutes, you go often see failures wey dem don count and addresses wey dem don ban, because internet scans port 22 continuously. Na this dey prove say stock config dey work. From here, you dey refine am, no be say you dey build am from zero.

Step 2: Edit jail.local, no be jail.conf

Fail2ban dey keep the upstream default settings for /etc/fail2ban/jail.conf. No edit that file. Any apt upgrade wey the package release fit replace am, and your changes go disappear without warning. Fail2ban dey read files for fixed order: jail.conf first, then everything inside jail.d/, then jail.local, and the last value na the one wey go apply. The .local file na your own, and package upgrades no dey touch am. The same rule apply to filters too, where *.local file dey override the shipped filter.d/*.conf.

So you go write small jail.local wey dey override only the few settings wey you need, and leave both jail.conf and the packaged jail.d/defaults-debian.conf untouched as reference.

Step 3: Write /etc/fail2ban/jail.local

sudo nano /etc/fail2ban/jail.local

Put this one inside, change the address for the ignoreip line to your own public IP:

[DEFAULT]
# Ubuntu 24.04 already sets these two in jail.d/defaults-debian.conf.
# Pinning them here documents the dependency and survives if that
# file is ever removed or changed by an upgrade.
backend   = systemd
banaction = nftables

# Ban for one hour ...
bantime  = 1h
# ... if an address fails ...
maxretry = 5
# ... 5 times within 10 minutes.
findtime = 10m

# Never ban these. PUT YOUR OWN IP HERE.
ignoreip = 127.0.0.1/8 ::1 10.0.0.24

# Longer bans for repeat offenders: 1h, 2h, 4h ... up to a week.
bantime.increment = true
bantime.maxtime   = 1w

[sshd]
enabled = true

Every line get im place for here:

  • bantime, findtime, maxretry na the policy. The shipped default bantime na only ten minutes; one hour dey more reasonable as minimum. If one address fail five times within ten minutes, e go earn ban. Real people fit type password wrong once or twice; five failures within ten minutes mean say na script.
  • ignoreip na your safety belt. Put the public address wey you dey connect from here, so Fail2ban no go ever lock you out from your own server. If your home connection dey change IP, na reason to prefer the VPN approach for the end, no be reason to skip this line.
  • bantime.increment = true make every repeat ban longer pass the last one: one hour, then two, then four, reach bantime.maxtime. Addresses wey keep coming back go progressively get locked out.

Find the address to whitelist from the machine wey you dey SSH from, no be from the server:

curl -s ifconfig.me

You fit generate a jail.local wey match your ports and ban policy here, then paste am inside the file:

ToolFail2ban jail generator

Step 4: Restart and verify say e dey read the journal

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

The -t dey run config test first, so typo for jail.local go fail clearly here instead of leaving the service dead. Healthy jail status dey look like this:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     14
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   10.0.0.66

The number wey prove say Fail2ban genuinely dey read your logins na Total failed. If e pass zero, or e increase when you deliberately fail login from another machine, journal dey read and you don finish. If e remain for 0 no matter how many times you fail, and you sure say you no dey test from the address for ignoreip, jump go the failure modes below.

Notice say the Journal matches line still name sshd.service. For Ubuntu, the SSH unit actually na ssh.service, but the shipped filter still match _COMM=sshd, and OpenSSH for 24.04 dey log its failures from process wey dem name sshd, so the match dey work. This detail only matter if you dey use newer OpenSSH (9.8 or later, where the per-connection worker na sshd-session); the failure modes cover that case.

Step 5: Watch real ban land, or force one test

Real bans dey happen by themselves within minutes for any public VPS. To watch one, tail the log:

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

Ban dey look like this:

2026-07-15 10:31:40,502 fail2ban.filter  [812]: INFO    [sshd] Found 10.0.0.66 - 2026-07-15 10:31:40
2026-07-15 10:31:44,118 fail2ban.actions [812]: NOTICE  [sshd] Ban 10.0.0.66

To prove say the whole process dey work without waiting, ban one documentation address by hand. Never use your own:

sudo fail2ban-client set sshd banip 10.0.0.66

E go print 1, and the address go appear under Banned IP list for fail2ban-client status sshd. Now confirm say the block really dey for firewall. For Ubuntu 24.04, na nftables, no be iptables:

sudo nft list table inet f2b-table

You go see one set wey dem name addr-set-sshd and e hold 10.0.0.66. You go also see chain f2b-chain wey rejects any source wey dey inside that set. If fail2ban-client talk say dem ban one address but nothing appear for nft list, your ban action no match your firewall. Check the nftables/iptables note for the failure modes.

Step 6: Unban yourself, and recover if you are locked out

If you ban address wey you suppose no ban, including your own address, remove am:

sudo fail2ban-client set sshd unbanip 10.0.0.66

E go return 1 when e work. To clear every ban for every jail:

sudo fail2ban-client unban --all

No trust existing SSH session to save you: nftables ban dey reject every packet from the banned address go port 22, including packets for established connections, so existing session go freeze immediately the ban enter. If you ban yourself and you no get ignoreip entry, you don lock yourself out until the ban expire. Recover through your provider's web console (VNC or serial), wey no pass through SSH, then either wait for bantime to expire or run the unban command there.

Step 7: Make bans dey persist and increase

Fail2ban dey keep active bans for small SQLite database at /var/lib/fail2ban/fail2ban.sqlite3, so dem go survive service restart or reboot; you no go lose dem. The bantime.increment lines wey you don add turn every repeat offender into bigger problem for demself, as the ban time dey roughly double from one hour reach about one week.

For system-wide "three strikes" policy on top this one, Fail2ban ship with recidive jail wey dey monitor its own /var/log/fail2ban.log and give long bans to any address wey dem don ban repeatedly across all jails. Since your [DEFAULT] now dey use systemd backend, pin this jail back to the log file wey e dey designed to read:

[recidive]
enabled  = true
backend  = auto
logpath  = /var/log/fail2ban.log
bantime  = 1w
findtime = 1d
maxretry = 5

backend = auto with the explicit logpath make recidive continue reading the plain fail2ban.log, na there the Ban lines wey e dey count dey appear. The systemd default wey you set globally for this jail go point am to the journal, but those lines no dey there.

8: Amala am na key-only SSH, VPN dey even better

Fail2ban dey useful only when you combine am with key authentication. For one drop-in file inside /etc/ssh/sshd_config.d/, like /etc/ssh/sshd_config.d/00-hardening.conf, set:

PasswordAuthentication no
KbdInteractiveAuthentication no

Then sudo systemctl restart ssh. Once password authentication off, brute force no fit succeed at all. Fail2ban then dey reduce log noise and remove scanners early. Better pass that one na to keep SSH completely away from public internet: put SSH behind self-hosted WireGuard VPN and firewall port 22 so e only answer through the tunnel. Nobody fit brute-force port wey dem no fit reach, and Fail2ban go become backup protection instead of the first line.

Fail2ban no be only for SSH. Any service wey dey log failed logins fit get jail, whether na mail server, nginx site, or self-hosted Vaultwarden password manager wey you no wan leave open to credential stuffing. Once web app dey behind nginx site with a Let's Encrypt certificate, point Fail2ban filter to the access log the same way SSH jail dey point to the journal.

Wahala wey fit happen, with the exact strings wey you go see

"Have not found any log file for sshd jail", and Fail2ban no go start. Dis na di old auth.log problem, and for Ubuntu 24.04 you go only meet am if something don override di packaged default, a pip install wey no get defaults-debian.conf, a container wey no get journal, or stray backend = auto wey you paste inside jail.local. For file backend wey no get /var/log/auth.log, sshd jail no fit find im log, so di whole daemon go stop. fail2ban.log go show:

ERROR   Failed during configuration: Have not found any log file for sshd jail

Because dis error dey fatal, di service no go ever come up, and fail2ban-client status go then report di downstream symptom:

ERROR  Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?

Dat "socket path" line no mean say Fail2ban spoil. E mean say e no start because one jail no fit find im log. If you set backend = systemd inside [DEFAULT], wey Ubuntu package don already set for you, e go fix both messages at once.

Jail dey active but Total failed no ever move. Di daemon dey run and e dey read journal, but real failures dey pile up inside journalctl -u ssh while di counter remain for 0. First rule out di obvious one: you dey test from address wey dey listed for ignoreip, so your own failures no count by design. If no be dat, you dey use OpenSSH build where di per-connection worker na sshd-session (9.8 and later). Im journal _COMM na sshd-session, no be sshd, so di match wey dem ship no catch am. Make di match wider inside di [sshd] block:

[sshd]
enabled      = true
backend      = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd + _COMM=sshd-session

Restart am, deliberately fail one login from address wey no dey inside ignoreip, then confirm say Total failed don finally rise.

You ban yourself: Connection refused. You no put your own address inside ignoreip, you test some bad logins, and now:

ssh: connect to host 10.0.0.10 port 22: Connection refused

Di refusal, instead of silent timeout, na di nftables action default reject verdict dey do im work against you. Fix am as Step 6 talk: unban from session wey dey use another address wey no dey banned, or use provider console. Session wey you already open from di banned address go freeze too. Then add your address to ignoreip so dis no go happen again.

Fail2ban talk say address don ban, but e still fit connect. Di counter for status sshd dey rise, but di address still dey reach port 22. Dis na mismatch between ban action and firewall. For Ubuntu 24.04, e almost always mean say you override di working banaction = nftables with banaction = iptables-multiport wey you copy from old guide, for machine wey no get iptables layer. fail2ban.log go show:

fail2ban.actions [812]: ERROR  Failed to execute ban jail 'sshd' action 'iptables-multiport'

Delete dat override and allow di packaged nftables action remain. Or, if na ufw you dey use manage di whole firewall and you want bans to show there, set banaction = ufw inside [DEFAULT]. Restart, then confirm say di rule dey appear with sudo nft list ruleset | grep f2b.

Fail2ban no go start after you edit jail.local. Typo, stray heading, or bad time value fit make di service refuse to come up. Ask Fail2ban to check di config before e run:

sudo fail2ban-client -t

E go name di file and jail wey get di problem, for example Errors in jail 'sshd'. Skipping..., so you fit fix di source instead of guessing.

FAQ

Fail2ban install wey Ubuntu 24.04 provide dey really ban SSH attacks?

Yes. The package get /etc/fail2ban/jail.d/defaults-debian.conf, wey enable sshd jail, set backend = systemd so e go read systemd journal instead of the missing /var/log/auth.log, and set banaction = nftables so bans go apply through Ubuntu real firewall. Plain apt install fail2ban dey protect SSH from first boot. Confirm am with sudo fail2ban-client status sshd and check for non-zero Total failed.

Why Fail2ban no dey ban anything for my box?

Rule out the three common causes one after another. You fit dey test from address wey dey inside ignoreip, and design exempt am. You fit don override the working default by pasting backend = auto inside jail.local from old guide. This one dey break journal reading for image wey no get auth.log. Or you fit dey inside container wey no get systemd journal to read at all. Check Total failed inside fail2ban-client status sshd: if e no ever increase while journalctl -u ssh dey show real failures, the jail dey read wrong place.

How I fit unban my own IP address?

Run sudo fail2ban-client set sshd unbanip YOUR.IP.HERE. E go return 1 when e succeed. You fit also run sudo fail2ban-client unban --all to clear every ban. If SSH lock you out, use your provider web or VNC console to run the same command. The ban dey reject every packet from your address to port 22, so even session wey already open go stop to work. Then add your address to ignoreip so the ban no go happen again.

Wetin be the difference between jail.conf and jail.local?

jail.conf hold Fail2ban upstream defaults, and every package upgrade dey overwrite am. Any edit wey you make there go eventually disappear. Debian/Ubuntu package dey add its own settings on top through jail.d/defaults-debian.conf. Put your changes inside jail.local. Fail2ban dey read am last, so e override both files, and upgrades no dey touch am. Leave jail.conf as read-only reference.

Fail2ban dey replace key-based SSH authentication?

No. Fail2ban dey rate-limit repeated failures from one address. E no dey stop slow, distributed guessing wey each address stay below the threshold. Key-only authentication (PasswordAuthentication no) dey make password guessing impossible outright. Fail2ban then reduce log noise and remove scanners early. Use both, and if possible keep SSH completely off public internet.