Developers

fail2ban Basics: Automatically Block Brute-Force Attacks on Your Server

fail2ban reads your logs and bans addresses that keep failing to log in. Learn how jails work, how to install it safely and how to check who was banned.

By Zebra Hosting Cloud

Open the authentication log of almost any public server and you will see the same story: repeated failed logins from addresses all over the world. fail2ban is a small, long-established tool that watches logs for such patterns and temporarily bans the offending addresses in the firewall. It is not a complete security system, but it is cheap to set up and removes a lot of noise.

How fail2ban works

fail2ban is built from three ideas:

  • A filter is a set of regular expressions that recognises a failure in a log file, such as "Failed password for ... from 198.51.100.7".
  • An action is what happens when a threshold is exceeded, usually adding a firewall rule that blocks the address.
  • A jail ties a filter, a log source and an action together with settings for how many failures are allowed, over what time window, and for how long the ban lasts.

When one address produces more failures than allowed within the window, fail2ban bans it for the configured time and then lifts the ban automatically.

Installing it

On Debian or Ubuntu:

sudo apt install fail2ban

On AlmaLinux or Rocky Linux the package comes from the EPEL repository: install epel-release first, then fail2ban with dnf. The package normally enables the SSH jail on Debian-based systems; on Red Hat style systems you configure it yourself.

Configure with jail.local, not jail.conf

The default file is /etc/fail2ban/jail.conf, and package upgrades may overwrite it. Put your changes in /etc/fail2ban/jail.local, which takes precedence. A sensible minimal file looks like this:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true

This means: five failures within ten minutes earns a one-hour ban. Add your own static IP to ignoreip (separated by spaces) if you have one, so a typo cannot lock you out of your own server. Then enable and start the service:

sudo systemctl enable --now fail2ban

If your SSH daemon uses a non-standard port, add port = 2222 (your actual number) to the [sshd] section so the firewall rule blocks the correct port.

Checking what it is doing

sudo fail2ban-client status
sudo fail2ban-client status sshd

The second command shows the number of current and total failures and the list of banned addresses. To remove a ban, for example because you banned yourself, use:

sudo fail2ban-client set sshd unbanip 198.51.100.7

Logs of fail2ban's own activity are in /var/log/fail2ban.log.

To prove that a jail works without banning yourself, test from a different connection, such as a phone on mobile data, using deliberately wrong credentials a few times. Then check the status command above and look at the firewall itself (sudo iptables -L -n or sudo nft list ruleset, depending on your system) to see the ban in place. Unban the test address afterwards.

Beyond SSH and repeat offenders

fail2ban ships filters for many services, including Nginx and Apache authentication failures, mail servers and more. The recidive jail goes further: it watches fail2ban's own log and applies a much longer ban to addresses that keep coming back after each short ban. Enable jails the same way, with enabled = true under the matching jail name, but only for services you actually run. For WordPress, a common approach is a custom filter that matches repeated requests to wp-login.php; that requires your web server to log in a format the filter can read, so test it with fail2ban-regex before relying on it:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

This replays a log against a filter and tells you how many lines matched, which is the safest way to check a new rule.

Limits you should know about

  • It is reactive. The first failed attempts still happen. If SSH uses key-only login, those attempts cannot succeed anyway, which is why fail2ban is an extra layer, not the main defence.
  • Distributed attacks. If attempts come from thousands of addresses, each staying under the threshold, per-address banning helps little.
  • Self-lockout risk. Keep a second way in, such as a provider console, and use ignoreip sensibly.
  • Behind a proxy or CDN. If web traffic arrives through a service like Cloudflare, the log may show the proxy's address rather than the visitor's. Banning that address would block everyone, so configure your web server to log the real client IP before using web-based jails.
  • Log location. Some minimal systems do not write /var/log/auth.log at all and keep logs only in the systemd journal. In that case add backend = systemd to the jail so fail2ban reads the journal instead.
  • Cost and noise. Very long ban lists can slow down some setups; moderate ban times are usually enough.

Layers. Think of the stack in layers: a firewall with minimal open ports, key-only SSH, regular updates, and fail2ban to cut down automated noise. Each layer catches what the others miss.

Where to go from here

Review your ban list every so often. A pattern of repeated bans from a single network, or from one application, can point to a misconfigured integration or an attacker targeting a particular login page. Keep fail2ban itself updated, and back up your jail.local so a rebuilt server comes up with the same protection. Read more about layered protection on the security page.

Protecting your server with Zebra Hosting

On a self-managed server you decide which layers to apply, and tools like fail2ban are easy to add. If you want to run your own, start with a Zebra Hosting VPS.