Fail2ban is an open-source log-based intrusion prevention daemon for Linux and other Unix-like systems. It watches service logs for repeated signs of abuse, such as failed SSH logins or rejected web authentication, and temporarily blocks the offending IP addresses by adding rules to the host firewall.
In Linux security, Fail2ban is a classic layer of SSH hardening and service protection. It does not fix weak passwords or vulnerable software, but it sharply reduces the noise and success rate of automated brute-force attacks against any service that writes useful log entries.
How Fail2ban detects and blocks attackers
Fail2ban works as a loop of read, match, count and act. A Python daemon follows log files or the systemd journal, applies regular expressions to each new line, extracts the client address from matching lines and counts failures per address. When an address exceeds a threshold within a time window, Fail2ban runs a ban action, usually inserting a firewall rule, and later runs an unban action when the ban expires.
The configuration is built from three kinds of objects. A filter defines what a failure looks like in the logs. An action defines what to do about it. A jail binds a filter to one or more actions and to a log source, with its own thresholds. Typical jails exist for sshd, Postfix, Dovecot, Apache, nginx and many other services.
The table below lists the core components and where they live on a typical installation.
| Component | Role | Typical location |
|---|---|---|
| Jail | Combines a filter, actions and thresholds | jail.local or jail.d/*.local |
| Filter | Regular expressions for failure lines | filter.d/*.conf |
| Action | Commands for ban and unban | action.d/*.conf |
| Backend | Method of reading logs | systemd journal, pyinotify or polling |
| fail2ban-server | Daemon that runs jails | Started by the init system |
| fail2ban-client | Command-line control and status | Used by administrators and scripts |
Key parameters and typical values
Three parameters define the behavior of every jail: maxretry, findtime and bantime. An address is banned when it produces maxretry failures within findtime seconds, and the ban lasts for bantime. Upstream defaults are commonly five failures within ten minutes leading to a ten-minute ban, but distributions and administrators often choose stricter values.
| Parameter | Meaning | Common range | Effect of a higher value |
|---|---|---|---|
| maxretry | Failures allowed before a ban | 3 to 10 | More tolerant of user mistakes |
| findtime | Window for counting failures | 10 minutes to 1 day | Catches slower attacks |
| bantime | Duration of the ban | 10 minutes to several days | Longer protection, more lockout risk |
| ignoreip | Addresses never banned | Localhost and admin networks | Prevents self-lockout |
| bantime.increment | Grows the ban for repeat offenders | Factor or exponential growth | Punishes persistent sources |
| banaction | Firewall backend used | nftables, iptables, firewalld, ufw | Must match the host firewall |
The special recidive jail reads Fail2ban’s own log and bans addresses that were banned repeatedly, for example several times in a day, for a much longer period such as a week. This combination of short initial bans and long repeat bans balances user forgiveness against persistent attackers.
Fail2ban compared with other protective controls
Fail2ban is a reactive, host-level control. It complements, but never replaces, preventive measures such as key-only SSH authentication and network filtering.
| Control | How it protects | Relationship to Fail2ban |
|---|---|---|
| SSH key authentication | Removes password guessing entirely | Makes brute force futile; Fail2ban reduces noise |
| Firewall allowlisting | Exposes services only to known networks | Stronger where feasible |
| Rate limiting in the service or firewall | Limits connection rates per address | Works without log parsing |
| PAM account lockout | Locks the targeted account | Protects accounts, not the host |
| Web application firewall | Inspects HTTP requests | Covers attacks that leave no log failures |
| Network intrusion prevention | Analyzes traffic patterns | Broader scope, more complexity |
A useful distinction is account-centric versus source-centric protection. PAM lockout punishes the targeted user, which an attacker can abuse to lock out legitimate accounts. Fail2ban punishes the source address, which keeps users working but is weaker against attacks spread across many addresses.
Configuring Fail2ban safely
Safe configuration starts with never editing the shipped jail.conf. Local changes go into jail.local or files in jail.d, which survive package upgrades. Each jail should be enabled explicitly, with thresholds suited to the service it protects.
- Add administrator networks to ignoreip before enabling strict jails, so a mistyped password does not lock out the team.
- Match the backend to the logging setup: on systems that log only to the journal, use the systemd backend.
- Choose the right banaction for the active firewall, such as nftables on modern distributions.
- Test filters with
fail2ban-regexagainst real log samples before relying on them. - Check jail status with
fail2ban-client status sshdand unban withfail2ban-client set sshd unbanip.
When services sit behind a reverse proxy or load balancer, logs may show the proxy address instead of the client. In that case the service must log the real client address, and bans must be applied where the traffic actually enters, otherwise Fail2ban may ban the proxy itself.
Limitations and common mistakes
Fail2ban can only react to what appears in the logs, after the attempt has already happened. It offers little against distributed attacks from thousands of addresses, each staying below the threshold, and it is not a defense against volumetric denial of service.
| Symptom | Likely cause | Fix |
|---|---|---|
| No bans despite attacks | Wrong log path or backend | Point the jail to the actual log source |
| Filter never matches | Log format changed after an update | Update the filter and retest with fail2ban-regex |
| Administrators locked out | Missing ignoreip entries | Add trusted networks and use console access to recover |
| Bans have no effect | Action does not match the firewall in use | Select the correct banaction |
| IPv6 attackers ignored | Old version or IPv4-only action | Use a recent release with IPv6 support |
The idea in brief
Fail2ban is like a doorman who keeps a notebook. Every time someone tries a wrong key at the door, the doorman writes down who it was. After a few failed tries in a short time, that person is not allowed near the door for a while.
Honest visitors who mistype once are not affected. Automated burglars who try thousands of keys are turned away quickly, which keeps the building quieter and safer.
A practical scenario
A small company runs a public Linux server for its customer portal. The authentication log shows thousands of failed SSH logins every day from automated scanners, which fills the disk with log entries and hides genuine events.
The administrator first switches SSH to key-only authentication. Then Fail2ban is installed with an sshd jail using the systemd backend and the nftables banaction: three failures within ten minutes lead to a one-hour ban, the office network is listed in ignoreip, and the recidive jail bans repeat offenders for a week.
Within a day, failed attempts in the logs drop to a small fraction of their previous volume, and remaining entries are easier to review. The server was already safe thanks to keys, but Fail2ban removes most of the noise and adds another layer of protection.