Configuration
Incremental ban time with bantime.increment
Give first-time offenders a short ban and repeat attackers a long one, automatically. This page explains every bantime.* option, shows the exact ban lengths you get, and the database setting most guides forget.
To make fail2ban ban repeat offenders for longer, set bantime.increment = true in /etc/fail2ban/jail.local. The first ban of an IP lasts bantime; each later ban of the same IP doubles it (2×, 4×, 8×…) until it reaches bantime.maxtime. fail2ban counts previous bans in its SQLite database, so the database must be enabled (it is by default), and dbpurgeage decides how long an IP is remembered.
[DEFAULT]
bantime = 1h ; first ban
bantime.increment = true ; repeat bans grow: 1h, 2h, 4h, 8h…
bantime.factor = 1
bantime.maxtime = 1w ; never longer than a week[Definition]
dbpurgeage = 30d ; remember previous bans for a monthsudo fail2ban-client reloadAll bantime.* options#
These options are commented out in the stock jail.conf. Set them in [DEFAULT] for every jail or inside a single jail.
| Option | Default | Meaning |
|---|---|---|
bantime.increment |
off | Turn incremental bans on (true). |
bantime |
10m |
The first ban and the base for every increase. |
bantime.factor |
1 |
Coefficient in the formula, or multiplier applied to bantime.multipliers. |
bantime.formula |
ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor |
Python expression for the next ban time. Ignored when bantime.multipliers is set. |
bantime.multipliers |
unset | Space-separated multipliers used instead of the formula, e.g. 1 2 4 8 16 32 64. |
bantime.maxtime |
unset (no cap) | Maximum length of an increased ban. |
bantime.rndtime |
unset | Adds a random 0…N seconds to each increased ban, so bots can't predict the exact unban time. |
bantime.overalljails |
false |
true counts the IP's previous bans in all jails, not only the current one. |
Time values accept the usual format (1h, 1d, 1w, 5w); see time format.
How the next ban time is calculated#
When a jail bans an IP, fail2ban looks it up in the database (bips table) to find how many times it was banned before. That number is ban.Count.
- First ban (no previous ban recorded): the ban lasts exactly
bantime. No factor, formula or multiplier is applied. - Repeat ban (
ban.Count≥ 1): - Without multipliers:bantime × 2^ban.Count × factor(the exponent stops growing at 20), and never less thanbantime. - Withbantime.multipliers:bantime × factor × multipliers[ban.Count]. When the count runs past the end of the list, the last multiplier is used. - The result is capped at
bantime.maxtime, if set. - A random 0…
bantime.rndtimeseconds is added, if set.
Because the list is indexed by the count of previous bans, the first multiplier is never used for a repeat ban. Keep it at 1 so the list reads naturally.
Previously banned IPs are also banned faster. While an IP has ban history, each new failure from it counts more than once (2× after one ban, 3× after two, 5× after three, and so on, up to maxretry). A known attacker coming back is often banned on its first or second failure.
Worked examples#
The bantime calculator does these calculations for any values. Here are the common setups.
Default formula, bantime = 1h, factor = 1, maxtime = 1w#
| Ban # | ban.Count | Calculation | Ban length |
|---|---|---|---|
| 1 | — | bantime | 1h |
| 2 | 1 | 1h × 2 | 2h |
| 3 | 2 | 1h × 4 | 4h |
| 4 | 3 | 1h × 8 | 8h |
| 5 | 4 | 1h × 16 | 16h |
| 6 | 5 | 1h × 32 | 1d 8h |
| 7 | 6 | 1h × 64 | 2d 16h |
| 8 | 7 | 1h × 128 | 5d 8h |
| 9+ | 8+ | 1h × 256 → capped | 1w |
Same, with factor = 2#
bantime.factor multiplies every repeat ban, so the growth starts one step ahead:
| Ban # | Ban length (bantime = 1h) |
|---|---|
| 1 | 1h |
| 2 | 4h |
| 3 | 8h |
| 4 | 16h |
| 5 | 1d 8h |
| 6 | 2d 16h |
Multipliers 1 2 4 8 16 32 64, bantime = 10m#
This is the example from jail.conf. It grows like the formula, but stops at the last multiplier (64 × 10m = 10h 40m) without needing maxtime:
| Ban # | Multiplier | Ban length |
|---|---|---|
| 1 | — | 10m |
| 2 | 2 | 20m |
| 3 | 4 | 40m |
| 4 | 8 | 1h 20m |
| 5 | 16 | 2h 40m |
| 6 | 32 | 5h 20m |
| 7+ | 64 | 10h 40m |
Aggressive multipliers for a short first ban#
The second example in jail.conf, intended for bantime = 1m:
bantime = 1m
bantime.multipliers = 1 5 30 60 300 720 1440 2880Bans run 1 min, 5 min, 30 min, 1 h, 5 h, 12 h, 1 day, then 2 days for every further ban.
How long fail2ban remembers an IP (dbpurgeage)#
This is where most incremental setups quietly fail. Ban history lives in /var/lib/fail2ban/fail2ban.sqlite3, and a purge runs every hour. An IP's last ban record is deleted once dbpurgeage plus three times that ban's length has passed since the ban started. Permanent bans (-1) are never purged.
With the stock dbpurgeage = 1d:
| Last ban length | IP forgotten after |
|---|---|
| 1h | 1d 3h |
| 8h | 2d |
| 1d | 4d |
So a bot that comes back a week later starts again at ban #1. To remember repeat offenders for longer, raise dbpurgeage in fail2ban.local (details on the fail2ban.conf page):
[Definition]
dbpurgeage = 30dA larger value makes the database bigger, but it holds one row per banned IP per jail, which is small even on busy servers. Check the current value:
$ sudo fail2ban-client get dbpurgeage
Current database purge age is:
`- 86400secondsTwo more things reset the history:
- Unbanning by hand (
fail2ban-client unban <IP>orset <jail> unbanip <IP>) deletes the IP's records from the database, so its next ban counts as the first. See unban an IP. - No database. With
dbfile = :memory:the history is lost at every restart; withdbfile = Noneincremental bans don't work at all and fail2ban logsban time increment is not available as long jail database is not set.
bantime.overalljails: count bans across jails#
By default an IP banned by sshd and later by postfix-sasl starts at ban #1 in each jail. With bantime.overalljails = true, fail2ban adds up the IP's bans in every jail, so an attacker probing several services escalates faster:
[DEFAULT]
bantime.increment = true
bantime.overalljails = trueThe ban itself is still per jail: each jail blocks its own ports. For an all-ports ban of repeat offenders, use recidive.
bantime.increment vs recidive#
Both punish repeat offenders; they work differently and combine well.
| Feature | bantime.increment | recidive jail |
|---|---|---|
| Trigger | Same IP banned again by the same jail (or any jail with overalljails) |
IP banned maxretry times within findtime across jails, read from fail2ban's log |
| Effect | Longer ban in the original jail, on its ports | Separate ban on all ports |
| Needs | The database (default) | fail2ban's own log in a file or the journal |
| Tuning | factor, multipliers, maxtime, dbpurgeage |
bantime, findtime, maxretry of [recidive] |
A common setup is increment in [DEFAULT] with a cap of one week, plus recidive for an all-ports ban. Remember that bantime.maxtime in [DEFAULT] also caps recidive's repeat bans; give [recidive] its own bantime.maxtime if you want them to exceed it. The jail.local example shows the full combination.
Permanent bans for repeat offenders#
To ban an IP forever after a certain number of bans, use multipliers and make the last step huge, or rely on a permanent recidive jail. There's no "-1" multiplier, but a very large one has the same practical effect:
[sshd]
enabled = true
bantime = 1h
bantime.increment = true
# 1h, 1d, 1w, then about 10 years
bantime.multipliers = 1 24 168 87600For a true -1 ban, enable [recidive] with bantime = -1. That's simpler to reason about and survives dbpurgeage, because permanent bans are never purged.
Check that it works#
fail2ban logs the increase when it extends a ban. Watch for Increase Ban lines in /var/log/fail2ban.log:
sudo grep -E "Increase Ban|is bad" /var/log/fail2ban.log | tailAnd the effective ban length of each banned IP:
sudo fail2ban-client get sshd banip --with-timeThe + <seconds> part of each line is that ban's individual length, which grows for repeat offenders.
FAQ#
How do I enable incremental ban time in fail2ban?#
Add bantime.increment = true to [DEFAULT] (or one jail) in /etc/fail2ban/jail.local, optionally with bantime.factor, bantime.maxtime and bantime.multipliers, then run sudo fail2ban-client reload. The database must be enabled (dbfile in fail2ban.conf, on by default).
What does bantime.factor do?#
It multiplies repeat bans. With the default formula, the second ban is bantime × 2 × factor, the third bantime × 4 × factor, and so on. factor = 1 doubles each time; factor = 2 starts at 4×. The first ban is always the plain bantime.
Why does bantime.increment not work?#
The usual causes: it isn't enabled in the jail that bans (check sudo fail2ban-client -d | grep increment), the database is disabled (dbfile = :memory: or None), the IP was forgotten because dbpurgeage (default 1 day) expired, or it was unbanned manually, which deletes its history.
What is the maximum ban time with bantime.increment?#
Whatever bantime.maxtime is set to. Without it, the default formula keeps doubling until the exponent reaches 20 (about a million times bantime), and multipliers stop at the last value in the list. Always set bantime.maxtime unless your multipliers already end where you want.
Does bantime.increment work across jails?#
Only with bantime.overalljails = true. By default an IP's previous bans are counted per jail. With overalljails, bans from every jail are added together, but the resulting ban still applies only to the jail that triggered it.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.