Security

Fail2ban False Positive Resolution: Fine-Tuning Jails and Timeouts

Diagnose why Fail2ban banned a legitimate user, then fix it properly by tuning maxretry, findtime, bantime and ignoreip instead of disabling the jail.

IntermediateLinux server6 min read

A Fail2ban false positive locks out someone who did nothing wrong: a developer retyping a password, a monitoring probe, or a mail client reconnecting too fast. This guide walks through identifying which jail fired, confirming the ban was wrong, and tuning the jail so the same address is not banned again.

The fix is almost never "turn Fail2ban off". It is a small change to maxretry, findtime, bantime or ignoreip in jail.local, or a correction to the filter regex that matched the wrong log line.

Before you start

You need:

  • Root or sudo access to the Linux VPS, and the ability to edit files under /etc/fail2ban/.
  • The IP address that was banned, for example 203.0.113.10.
  • Fail2ban already installed and running. If it is not, start with installing Fail2ban to protect SSH.
  • A rough idea of when the ban happened, so you can match it against log timestamps.

Warning: Restarting or reloading Fail2ban clears the current ban list. Any address banned right now will be unbanned. That is usually fine, but do not reload during an active brute-force attack without checking the logs first.

Find which jail banned the address

List the jails and their current state:

Bash
sudo fail2ban-client status

Then inspect the jail you suspect, usually sshd:

Bash
sudo fail2ban-client status sshd

The output shows the filter file, the log path, and the banned IP list:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     47
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   203.0.113.10

If you do not know which jail is responsible, check them all:

Bash
for j in $(sudo fail2ban-client status | grep "Jail list" | cut -d: -f2 | tr -d ' ' | tr ',' ' '); do
  echo "== $j =="
  sudo fail2ban-client status "$j" | grep "Banned IP list"
done

Confirm it is a Fail2ban false positive

Before changing anything, look at the log lines that triggered the ban. For SSH on Debian or Ubuntu:

Bash
sudo journalctl -u ssh --since "2 hours ago" | grep 203.0.113.10

On AlmaLinux or Rocky, SSH logs to /var/log/secure:

Bash
sudo grep 203.0.113.10 /var/log/secure

For Nginx, check the access log:

Bash
sudo grep 203.0.113.10 /var/log/nginx/access.log | tail -20

Read the matched lines and ask one question: did this client actually fail authentication, or did the filter match something harmless? A real user typing a wrong password three times is a tuning problem. A 404 request being counted as an auth failure is a filter problem.

You can also replay the log against the filter to see exactly what matches:

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

Tune maxretry, findtime and bantime

These three settings control how strict a jail is:

  • maxretry — how many failures are allowed inside the window.
  • findtime — the length of that window in seconds.
  • bantime — how long the ban lasts.

Never edit /etc/fail2ban/jail.conf. It is overwritten on package upgrades. Put overrides in /etc/fail2ban/jail.local:

INI
[DEFAULT]
# Allow more mistakes before banning
maxretry = 5
findtime = 10m
bantime  = 1h

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

The full set of options is covered in configuring bantime, findtime and maxretry in jail.local.

Test the configuration before applying it:

Bash
sudo fail2ban-client -t

If it reports OK, reload:

Bash
sudo fail2ban-client reload

Verify the values took effect:

Bash
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd bantime

Whitelist trusted addresses with ignoreip

For known-good sources — your office IP, a monitoring server, a CI runner — whitelisting is cleaner than loosening the jail for everyone. Add them under [DEFAULT] in jail.local:

INI
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10 198.51.100.0/24

ignoreip accepts single addresses and CIDR ranges, separated by spaces. Reload and confirm:

Bash
sudo fail2ban-client reload
sudo fail2ban-client get sshd ignoreip

Tip: Do not whitelist a whole ISP range just to unblock one user. Whitelisting a /16 can exclude thousands of addresses from every jail on the server.

To lift a ban immediately without touching config, use fail2ban-client set sshd unbanip 203.0.113.10. The full procedure is in checking banned IPs and unbanning an address.

Fix the filter instead of loosening the jail

If the log lines were never authentication failures, the filter regex is wrong and tuning will only hide the problem. A common case is a web jail matching a 404 or a health-check probe.

Test a candidate regex against real logs before deploying it:

Bash
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-badbots.conf

Look at the "Lines matched" count. If it matches normal traffic, tighten the pattern. Put custom filters in /etc/fail2ban/filter.d/ and reference them from a jail in jail.local. The workflow is described in writing a custom filter and testing it with fail2ban-regex and in creating filters for specific application log errors.

Warning: A filter with a very broad regex can ban your own users in bulk. Always run fail2ban-regex against a day of production logs and check the match count before enabling the jail.

Check it works

  1. Ask the affected user to connect again and confirm they are not blocked.
  2. Watch the jail while they do it:
Bash
sudo fail2ban-client status sshd
  1. Confirm the failed count rises without a ban, which proves maxretry is now high enough:
|- Currently failed: 2
|- Total failed:     49
`- Banned IP list:
  1. Check the Fail2ban log for filter errors after the reload:
Bash
sudo tail -50 /var/log/fail2ban.log
  1. Run a deliberate wrong-password attempt from a test address you control and confirm the ban still triggers. A jail that never bans is not protection.

Troubleshooting

  • The same user is banned again within minutes. findtime is too long relative to their retry pattern, or maxretry is still too low. Raise maxretry to 5–6 and shorten findtime to 10m.
  • fail2ban-client -t fails after editing jail.local. A duplicate section header or a missing = is the usual cause. Check the reported line number and confirm each jail appears only once.
  • Changes do not apply. You edited jail.conf instead of jail.local, or forgot to reload. Run sudo fail2ban-client reload and re-check with fail2ban-client get.
  • ignoreip has no effect. The address is still banned from a previous run. Unban it manually, then confirm with fail2ban-client get <jail> ignoreip that the value parsed correctly.
  • A jail bans nobody after tuning. The filter regex no longer matches the log format, often after an OS or application upgrade. Re-run fail2ban-regex and compare against the current log lines.
  • Bans disappear after a reboot. The ban database was not persisted. Check the dbfile setting in jail.local and confirm the path is writable.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.