On this page
fail2ban watches log files, and when one source produces the same failure too many times in a row it adds a firewall rule that drops that address for a while. It is a good answer to somebody grinding through passwords on your SSH port, and it is not an answer to anything larger than that.
What it does, and what it does not
It reads what a service has already written to a log. Everything follows from that:
- The attempt reached your service before fail2ban knew about it. Banning is after the fact, by design.
- It counts per source address. Credential attempts spread across thousands of addresses never reach the threshold from any one of them, and nothing is banned.
- A packet flood aimed at a game port writes nothing to any log, so fail2ban never sees it. That traffic is handled before it reaches your operating system; see How protection works, and use Blocking and allowing IPs when you want one source gone.
If your concern is specifically people guessing SSH passwords, turning password sign-in off removes the problem outright rather than rate-limiting it. See Hardening SSH on Linux. fail2ban is still worth running after that, mostly for services that must accept a password and for keeping the logs readable.
Installing it
On Debian and Ubuntu:
apt update
apt install -y fail2banOn RHEL, Alma, and Rocky, fail2ban comes from EPEL:
dnf install -y epel-release
dnf install -y fail2banThen, on either family:
systemctl enable --now fail2banConfiguring the sshd jail
Never edit /etc/fail2ban/jail.conf. It is replaced when the package updates and
your changes go with it. Put your settings in /etc/fail2ban/jail.local, which
overrides it and is left alone:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
[sshd]
enabled = true
port = 22What those four values mean together: an address that fails maxretry times
within findtime is banned for bantime.
Sizing them is a judgement about your own users, not a fixed answer. A few notes on the edges:
bantime = -1bans permanently. The list only grows, so prefer a finite ban unless you are curating the list by hand.bantime.increment = truein[DEFAULT]makes each repeat ban for the same address longer than the last, which is usually better than one long ban.ignoreipis never banned. Put your own fixed address there, space separated. It is worth doing before you have to, not after.portaccepts a number or a name from/etc/services. If you moved SSH, set the number here as well, or the jail keeps watching port 22.
Apply the file:
fail2ban-client reloadIf your server has no /var/log/auth.log
Some images log only to the journal, and the jail then has nothing to read. Check:
ls -l /var/log/auth.logIf the file is not there, tell the jail to read the journal instead by adding one
line to the [sshd] section of jail.local:
[sshd]
enabled = true
backend = systemdThen reload.
Check that it is actually running
A jail that cannot find its log takes the whole service down at startup, and the message that explains why is only in the service status:
systemctl status fail2banA failure reads like "Failed during configuration: Have not found any log file
for sshd jail". The full history is in /var/log/fail2ban.log, or:
journalctl -u fail2ban -n 50 --no-pagerReading the status
List the jails that are up:
fail2ban-client statusThen look at one:
fail2ban-client status sshdThat prints two blocks. The filter block gives currently failed and total failed attempts, and names the log file it is reading, which is the quickest way to confirm the jail found its source. The actions block gives currently banned, total banned, and the list of banned addresses. A jail that is up but shows zero of everything after a day on a public address is usually reading the wrong log.
Unbanning an address
Remove one address from one jail:
fail2ban-client set sshd unbanip 203.0.113.10Remove it from every jail, or clear the lot:
fail2ban-client unban 203.0.113.10
fail2ban-client unban --allYou can also ban by hand, which is useful for testing the mechanism:
fail2ban-client set sshd banip 203.0.113.10If you banned yourself
You will not be able to SSH in to fix it, because the ban is what is refusing you. Open Console access in the panel, which reaches the machine without going through the ban, then:
fail2ban-client set sshd unbanip 203.0.113.10Add the address to ignoreip in jail.local and reload, so the same mistake
cannot repeat. If you connect from an address that changes, ignore a fixed one
you control instead, and rely on the console for the rest.
Writing a jail for another service
A jail needs a filter, which is a pattern that matches one failure line, and a
few settings that say where to read and when to act. fail2ban ships filters for
common software in /etc/fail2ban/filter.d/, so check there before writing one.
Enabling a shipped filter takes only the jail:
[nginx-http-auth]
enabled = trueFor your own application, write the filter first. Create
/etc/fail2ban/filter.d/myapp.conf:
[Definition]
failregex = ^.*authentication failed for user .* from <HOST>.*$
ignoreregex =<HOST> is the placeholder for the address to ban, and every failregex needs
exactly one. Test the pattern against real log lines before enabling anything:
fail2ban-regex /var/log/myapp/app.log /etc/fail2ban/filter.d/myapp.confIt reports how many lines matched. Zero matches means the jail would do nothing, which is the failure mode you want to find now rather than during an attack. For a service that logs to the journal, point the same command at it:
fail2ban-regex systemd-journal /etc/fail2ban/filter.d/myapp.confThen add the jail to jail.local:
[myapp]
enabled = true
port = 8080
filter = myapp
logpath = /var/log/myapp/app.log
maxretry = 5
bantime = 1hReload, confirm the service is still up, and check the new jail appears:
fail2ban-client reload
systemctl status fail2ban
fail2ban-client status myapp