# bantime, findtime and maxretry explained

> How fail2ban's bantime, findtime and maxretry interact, the default ban time, the bantime format (1d, 1w, 1y, -1 permanent) and recommended values per service.
>
> Source: https://fail2ban.dev/config/bantime-findtime-maxretry/ · Updated 2026-10-25 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

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`.

```ini
[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  = 1d
```

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](/tools/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:

```text
$ sudo fail2ban-client get sshd bantime
3600
$ sudo fail2ban-client get sshd findtime
600
$ sudo fail2ban-client get sshd maxretry
3
```

## 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`.
- **`m` is minutes, not months.** `1m` is 60 seconds; a month is `1mo`.
- **Plain numbers are seconds**: `bantime = 3600` is the same as `1h`.

Check a value before you use it:

```bash
```

### 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](/unban-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](/config/bantime-increment/)**: every new ban of the same IP is longer (1h, 2h, 4h…), up to a cap.
- **[The recidive jail](/config/recidive/)**: 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 = 0`** does **not** disable banning. The check is "failures ≥ maxretry", so the first matching line bans the IP, exactly like `maxretry = 1`. To stop a jail from banning, disable the jail (`enabled = false`) or [whitelist](/config/whitelist/) the addresses.
- **`bantime = 0`** is not permanent: the ban expires at once and the IP is unbanned within seconds. Use `-1` for permanent.
- **`maxretry = 1`** is 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 = 1h` with `maxretry = 5` catches them where `10m` doesn't. A longer window also keeps more IPs in memory, which is rarely an issue.
- **Pair a moderate `bantime` with [bantime.increment](/config/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:

```ini
[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 = 1h
```

```text
$ sudo fail2ban-client set sshd bantime 86400
86400
```

```text
$ 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:14
```

## 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`.
