// Engineering Log

Securing a Linux Server: Part 2 — Fail2ban Against Password Brute-Force Attacks

Published on 2026-09-22

// Fast route

This article belongs to the topic Security and protection.

Any server with SSH open gets scanned by bots within minutes after startup: they try common usernames and passwords, making thousands of attempts per hour. A firewall won’t help here — the SSH port must be open. You need a tool that notices brute-force attempts and blocks the attacker’s address. The classic solution is Fail2ban.

How Fail2ban works

Fail2ban is a Python program released under an open-source license. It reads service logs, finds repeated failed login attempts, and temporarily blocks the address via the firewall. The current version is 1.1.1 (15.08.2026).

Fail2ban consists of three parts:

  1. Filters — regular expressions that find lines about failed logins in the log, for example Failed password for ... for SSH.
  2. Jails — a combination of “which log to read, which filter to use, how many attempts within what time are allowed, and what to do”.
  3. Actions — commands that perform the blocking: nftables, iptables or firewalld rules.

Main jail parameters:

  • maxretry — how many failed attempts are allowed (default 5);
  • findtime — the time window to count them (default 10 minutes);
  • bantime — how long to ban the address (default 10 minutes).

Installation and where to store configuration

bash
sudo apt install fail2ban

Do not edit /etc/fail2ban/jail.conf: its header explicitly states it will be overwritten on package upgrade. Put your settings in /etc/fail2ban/jail.local or in separate files /etc/fail2ban/jail.d/*.local — they override the defaults.

On Debian the package already includes a jail.d/defaults-debian.conf file, which has the sshd jail enabled, blocking set up via nftables, and SSH logging read from systemd (backend = systemd). So on a fresh Debian SSH is protected immediately after installation.

Minimal working configuration

ini
# /etc/fail2ban/jail.local
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
banaction = nftables
banaction_allports = nftables[type=allports]
# addresses that should not be banned
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

# increasing ban time for repeat offenders
bantime.increment = true
bantime.factor = 1
bantime.maxtime = 1w

[sshd]
enabled = true
port = ssh
backend = systemd

ignoreip protects you from locking yourself out: if you mistype your password five times in a row from the office, without this line your office will lose access to the server.

bantime.increment enables an increasing ban period. Fail2ban remembers addresses in its database and makes each subsequent ban for the same address longer: 1, 2, 4, 8, 16 base periods — up to the limit bantime.maxtime. Bots that return after an hour quickly receive a ban for a week.

The recidive jail

For the most persistent attackers there is a separate recidive jail. It reads Fail2ban’s own log and bans addresses across all ports that have already been repeatedly caught by other jails. By default — a one-week ban if an address accumulates the required number of bans within a day:

ini
[recidive]
enabled = true

Documentation recommends increasing dbpurgeage in fail2ban.local (for example, to 648000 seconds, 7.5 days) so the database remembers addresses long enough.

Firewalld and nftables

The blocking action is chosen based on which firewall is installed on the server:

  • nftables — actions nftables-multiport, nftables-allports or the general nftables with a type parameter; the default on Debian;
  • firewalld (RHEL, AlmaLinux, Rocky) — actions firewallcmd-ipset, firewallcmd-rich-rules and others;
  • iptables — classic iptables-multiport and iptables-allports, if the server still uses iptables-legacy.

If you choose an action that doesn’t match the firewall, Fail2ban will dutifully “ban” addresses in the log, but nothing will actually be blocked.

Checking

bash
sudo fail2ban-client status              # list of active jails
sudo fail2ban-client status sshd         # how many addresses are banned
sudo fail2ban-client set sshd unbanip 203.0.113.10   # remove a ban
sudo nft list ruleset | grep -A3 f2b     # rules created by Fail2ban

fail2ban-regex helps test a filter against logs without performing bans: it shows how many lines the filter matched.

Strengths and limitations

Fail2ban is simple, uses almost no resources, and can protect any service that writes a readable log: SSH, mail servers, control panels, Asterisk. For most popular services filters are already included.

You should also understand the limitations:

  • Fail2ban reacts to log entries, not to traffic itself: the ban happens after attempts have already occurred;
  • it barely notices distributed brute-force attempts where each address makes one or two tries;
  • each server protects itself independently and knows nothing about attacks on neighboring servers.

The last two limitations are addressed by CrowdSec. But the main protection for SSH against brute-force is not Fail2ban, it’s using key-based logins with password authentication disabled: then there’s nothing to brute-force.

Common mistakes

  • Settings placed in jail.conf and lost after a package upgrade.
  • ignoreip not specified, and the administrator bans themselves.
  • The action does not match the firewall: bans are recorded in logs but not present in rules.
  • On Debian 12 and newer the jail is configured to read /var/log/auth.log, which doesn’t exist: SSH is logged by systemd, you need backend = systemd.
  • SSH moved to a different port, but the jail still has port = ssh, and the wrong port gets blocked.

What else to do to secure a new server is collected in the checklist “Bought a VPS — what’s next?”.

// Similar task

If you are dealing with something similar

This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.

Article topic

Security and protection

SSL, hardening, access control, service protection, and secure configurations.

Typical tasks behind this topic

  • Set up SSL, certificates, and secure connections
  • Restrict access and close unnecessary entry points
  • Harden server and service configuration

// Next step

If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.

Open services

// Reviews

Related reviews

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler, more affordable solution. In the end I saved time and money. Mikhail — a true expert who works for the client's result, not for the fee. I recommend him!

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler and more cost-effective solution. In the end I saved budget and time. Mikhail — a true expert who …

kfhzasorin

VPS setup, server setup

2026-05-12 · ★ 5/5

// Contact

Need help?

Get in touch with me and I'll help solve the problem

I reply within one business day (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirm that you are not a bot.

Write and get a quick reply