Configuration
bantime, findtime and maxretry explained
Three numbers decide when fail2ban bans and for how long. Here is how they interact, what the defaults are, how to write times like 1d12h, and what to set for SSH, web and mail jails.
fail2ban bans an IP when it produces maxretry failures within findtime, and the ban lasts bantime. The stock defaults are maxretry = 5, findtime = 10m and bantime = 10m: five failed logins within ten minutes earn a ten-minute ban. Times accept seconds or abbreviations (30m, 1h, 1d, 1w, 1mo, 1y), and bantime = -1 bans permanently. Set them in /etc/fail2ban/jail.local.
[DEFAULT]
bantime = 1h ; how long the ban lasts
findtime = 10m ; the window in which failures are counted
maxretry = 5 ; failures in that window that trigger a ban
[sshd]
enabled = true
maxretry = 3 ; stricter for SSH
bantime = 1dHow bantime, findtime and maxretry interact#
Think of findtime as a window that slides along with time. For each IP, fail2ban counts the failures its filter matched in the last findtime. When the count reaches maxretry, the IP is banned for bantime, and its failure counter is cleared.
Example with maxretry = 5, findtime = 10m, bantime = 1h:
| Time | Event | Failures counted | Result |
|---|---|---|---|
| 12:00 | 1st failed login from 203.0.113.42 | 1 | — |
| 12:02 | 2nd | 2 | — |
| 12:05 | 3rd | 3 | — |
| 12:07 | 4th | 4 | — |
| 12:08 | 5th | 5 | Banned until 13:08 |
| 13:08 | ban expires | 0 | Unbanned automatically |
A slow attacker who makes 4 attempts, waits 15 minutes and tries again never reaches 5 within 10 minutes, so findtime is what you raise to catch low-and-slow brute force. A practical detail: fail2ban doesn't store a timestamp for every failure. It keeps a counter per IP and forgets the IP once its last failure is older than findtime; if failures keep trickling in over a longer span, it scales the count down to the rate per findtime. The result behaves like a sliding window, which is what you need to reason about values.
findtime is measured against the timestamps in the log lines, not the time fail2ban reads them. When fail2ban starts and reads an existing log, failures older than findtime are ignored.
The bantime calculator converts values to seconds and shows when a ban ends, including incremental bans.
Default values#
| Option | Stock default (jail.conf) |
Notes |
|---|---|---|
bantime |
10m (600 s) |
The "default ban time". Some jails override it, e.g. apache-badbots uses 48h, recidive uses 1w. |
findtime |
10m (600 s) |
recidive uses 1d. |
maxretry |
5 |
Several jails use 1 or 2 (bad bots, shellshock, postfix-rbl). |
Distro packages usually keep these, but check /etc/fail2ban/jail.d/ and ask the running server:
$ sudo fail2ban-client get sshd bantime
3600
$ sudo fail2ban-client get sshd findtime
600
$ sudo fail2ban-client get sshd maxretry
3get always prints seconds. This server overrides bantime to 1 hour and maxretry to 3 for sshd.
bantime format: seconds, minutes, days, weeks#
Every time option (bantime, findtime, bantime.maxtime, dbpurgeage…) accepts plain seconds or abbreviations:
| Unit | Write | Example | Seconds |
|---|---|---|---|
| seconds | s, sec, second(s) |
30s |
30 |
| minutes | m, mm, min, minute(s) |
10m |
600 |
| hours | h, hh, hour(s) |
1h |
3600 |
| days | d, dd, day(s) |
1d |
86400 |
| weeks | w, ww, week(s) |
1w |
604800 |
| months | mo, mon, month(s) |
1mo |
2629800 (30.44 days) |
| years | y, yy, year(s) |
1y |
31557600 (365.25 days) |
- Combine units:
1d12h= 129600,1h30m= 5400,1y 6mo= 1.5 years. Expressions work too:1hour+30min. mis minutes, not months.1mis 60 seconds; a month is1mo.- Plain numbers are seconds:
bantime = 3600is the same as1h.
Check a value before you use it:
fail2ban-client --str2sec 1d12hIt prints the number of seconds (129600 here).
Common bantime values#
| You want | Write |
|---|---|
| 1 hour | bantime = 1h |
| 1 day | bantime = 1d (or 86400) |
| 1 week | bantime = 1w |
| 1 month | bantime = 1mo |
| 1 year | bantime = 1y |
| Permanent | bantime = -1 |
Permanent bans: bantime = -1#
bantime = -1 means the ban never expires. Only exactly -1 is treated as permanent; other negative numbers are not. Permanent bans survive restarts (they're stored in /var/lib/fail2ban/fail2ban.sqlite3) and stay until you unban the IP by hand.
Think twice before making a busy jail permanent: botnet IPs are reused and reassigned, the ban list grows forever, and a legitimate user who mistyped a password five times is locked out for good. Two better ways to be harsh on repeat offenders:
- Incremental bans: every new ban of the same IP is longer (1h, 2h, 4h…), up to a cap.
- The recidive jail: IPs banned again and again by other jails get a long, all-ports ban.
If you do want permanent bans, use them where false positives are near impossible, such as a recidive jail or a honeypot port.
What do maxretry = 0 and bantime = 0 do?#
maxretry = 0does not disable banning. The check is "failures ≥ maxretry", so the first matching line bans the IP, exactly likemaxretry = 1. To stop a jail from banning, disable the jail (enabled = false) or whitelist the addresses.bantime = 0is not permanent: the ban expires at once and the IP is unbanned within seconds. Use-1for permanent.maxretry = 1is legitimate for filters where a single match is unambiguous (exploit attempts, honeypots,postfix-rbl).
Recommended values per service#
Starting points, not rules. Tighten them if your logs show attacks getting through, loosen them if real users get banned.
| Jail | maxretry | findtime | bantime | Why |
|---|---|---|---|---|
sshd (keys only, passwords disabled) |
3 | 10m | 1h + increment | Legitimate users don't fail key auth repeatedly |
sshd (passwords allowed) |
5 | 10m | 1h + increment | Leave room for typos |
nginx-http-auth, apache-auth |
5 | 10m | 1h | Humans mistype; browsers retry |
nginx-botsearch, apache-botsearch |
2 | 10m | 1d | Scanners, no human hits these paths |
postfix-sasl, dovecot |
5 | 10m | 1h | Mail clients retry saved wrong passwords |
| Web app logins (WordPress, Nextcloud…) | 5 | 10m | 1h | Shared office IPs: don't be too strict |
recidive |
5 | 1d | 1w | Stock values; catches repeat offenders |
Two rules of thumb:
findtime≥ the interval between attempts you want to catch. Many botnets space attempts minutes apart;findtime = 1hwithmaxretry = 5catches them where10mdoesn't. A longer window also keeps more IPs in memory, which is rarely an issue.- Pair a moderate
bantimewith bantime.increment instead of one very long ban. First-time offenders (often your own users) are released quickly; persistent attackers escalate to days.
Set values per jail#
Values in [DEFAULT] apply to every jail; a value in a jail section replaces it for that jail only:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
maxretry = 3
[nginx-botsearch]
enabled = true
maxretry = 2
bantime = 1d
[postfix-sasl]
enabled = true
findtime = 1hApply with sudo fail2ban-client reload. You can also change values on the running server for testing (lost at the next reload or restart):
$ sudo fail2ban-client set sshd bantime 86400
86400Current bans that weren't individually extended by bantime.increment follow the jail's bantime, so raising or lowering it also moves their expiry. Check when each current ban ends:
$ sudo fail2ban-client get sshd banip --with-time
203.0.113.42 2026-10-25 18:36:10 + 3600 = 2026-10-25 19:36:10
192.0.2.15 2026-10-25 18:36:14 + 3600 = 2026-10-25 19:36:14
192.0.2.16 2026-10-25 18:36:14 + 3600 = 2026-10-25 19:36:14Each line reads: banned at 18:36:10, for 3600 seconds, released at 19:36:10.
FAQ#
What is findtime in fail2ban?#
findtime is the time window in which failures are counted. An IP is banned when it reaches maxretry failures within the last findtime. With the defaults (findtime = 10m, maxretry = 5), five failures in ten minutes cause a ban; failures spread over a longer period don't.
What is the default ban time in fail2ban?#
bantime = 10m (600 seconds) in the stock jail.conf. Some predefined jails override it, for example recidive bans for 1w. Check your effective value with sudo fail2ban-client get sshd bantime, which prints seconds.
How do I set bantime to 1 day, 1 week or 1 year?#
Use abbreviations in jail.local: bantime = 1d, bantime = 1w, bantime = 1y (or the seconds: 86400, 604800). For months write 1mo, because 1m means one minute. Units combine, e.g. 1d12h. Reload with sudo fail2ban-client reload.
What does maxretry = 0 do?#
It bans on the first failure, exactly like maxretry = 1, because fail2ban bans when the failure count is greater than or equal to maxretry. It does not disable the jail. To stop a jail from banning, set enabled = false.
Does changing bantime affect IPs that are already banned?#
Usually yes. In the running server, a ban without its own ban time (one not extended by bantime.increment) expires at ban start plus the jail's current bantime. Verify with sudo fail2ban-client get <jail> banip --with-time. To end bans immediately, use fail2ban-client unban <IP> or unban --all.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.