An internet-connected server’s SSH port may be subjected to automated login attempts every minute, using common usernames and passwords. Fail2ban monitors the log files and, if too many failed login attempts are received from a single IP address within a short period of time, it blocks that IP address at the firewall for a period of time.
Fail2ban is no substitute for a strong password and key-based authentication (see: SSH server security settings), but it significantly reduces the number of attempts and log noise.
This article is intended for those operating their own VPS or dedicated server. Do not install it on a cPanel server: cPHulk and CSF/LFD perform the same function there, and the two systems would conflict with one another.
Installation
AlmaLinux, Rocky Linux (from the EPEL repository):
sudo dnf install epel-release
sudo dnf install fail2ban fail2ban-firewalld
The fail2ban-firewalld package configures Fail2ban to block users via firewalld (banaction = firewallcmd-rich-rules) and also installs firewalld as a dependency. However, it does not actually start it. During testing on the AlmaLinux 10 cloud image, firewalld was not running: Fail2ban still logged the ban (Ban 10.0.2.15), but the banned address was still able to access SSH. Therefore, after installation, enable the firewall and, before doing so, allow the relevant ports through it (the ssh service, i.e. port 22, is enabled by default):
sudo firewall-offline-cmd --add-port=2255/tcp # ha az SSH más porton fut
sudo firewall-offline-cmd --add-service=http --add-service=https # ha webszerver is fut
sudo systemctl enable --now firewalld
sudo firewall-cmd --list-all
Whilst firewalld is not running, firewall-cmd cannot be used (as shown in the test: FirewallD is not running); therefore, the rules must be added using the firewall-offline-cmd command before startup; after startup, the usual firewall-cmd --permanent … and firewall-cmd --reload commands will work. For more details on configuring the firewall, see the article ‘How do I set up a firewall on my VPS?’.
Ubuntu, Debian:
sudo apt update
sudo apt install fail2ban
Settings
Fail2ban’s default settings are contained in the file /etc/fail2ban/jail.conf, but you should not modify this file as it may be overwritten during an update. Write your own settings to a new file:
sudo nano /etc/fail2ban/jail.local
A useful starting point:
[DEFAULT]
# Ennyi ideig marad kitiltva az IP-cím
bantime = 1h
# Ennyi időn belül...
findtime = 10m
# ...ennyi sikertelen próbálkozás után
maxretry = 5
# Ezeket a címeket soha nem tiltja ki (szóközzel elválasztva)
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
[sshd]
enabled = true
Enter your own static IP address (203.0.113.10 in the example) into the ignoreip line to prevent yourself from being locked out due to a mistyped password. By default, Fail2ban never blocks the server’s own addresses (ignoreself = true), so it does not count attempts initiated from the server itself; in the test, the log showed Ignore 10.0.2.15 by ignoreself rule in such cases.
If SSH is not running on the default port 22, please also specify the port in the [sshd] section (multiple ports can be separated by commas):
[sshd]
enabled = true
port = 22,2255
In the test, this block applied to both ports: two rich rules appeared in firewalld (source address="…" port port="22" and port="2255", reject).
Debian 12 and later: as the /var/log/auth.log file is not present by default on these systems, Fail2ban will not even start with the default settings. In our test, after installation, the service remained in a failed state, with the following message in the log: ERROR Failed during configuration: Have not found any log file for sshd jail. The solution is to have Fail2ban read from the systemd log (the required python3-systemd package is installed alongside Fail2ban). Add the following to the [sshd] section:
[sshd]
enabled = true
backend = systemd
In testing, this also worked on Debian 12 and detected incorrect login attempts. On AlmaLinux 10, no such action is required: there, Fail2ban reads the systemd log by default (in the status sshd output: Journal matches: _SYSTEMD_UNIT=sshd.service …).
Recurring addresses
By enabling the [recidive] section, IP addresses that have had to be blocked several times within a single day will be blocked for a longer period (one week by default):
[recidive]
enabled = true
Getting started
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
After changing the settings, please reload the service:
sudo fail2ban-client reload
Monitoring and management
# A működő szabálycsoportok (jail-ek)
sudo fail2ban-client status
# Az SSH jail részletei: hibás próbálkozások és kitiltott címek
sudo fail2ban-client status sshd
# Egy IP-cím kitiltásának feloldása
sudo fail2ban-client set sshd unbanip 198.51.100.25
# Egy IP-cím kézi kitiltása
sudo fail2ban-client set sshd banip 198.51.100.25
After a ban, the output of the status sshd test is:
Status for the jail: sshd
|- Filter
| |- Currently failed: 1
| |- Total failed: 6
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 10.0.2.15
Fail2ban’s own log is located in the file /var/log/fail2ban.log; here you can see when and which IP address was banned (NOTICE [sshd] Ban …, then Unban … once the bantime has expired). On AlmaLinux, the actual firewall rules are displayed by the command sudo firewall-cmd --list-rich-rules; if there is no entry here for the banned IP address, the ban is not working.
Have you locked yourself out?
If your own IP address has been blacklisted and you are unable to log in via SSH:
- wait for the
bantimeto expire, or - Log in from a different IP address (e.g. via mobile data) and lift the ban using the
unbanipcommand above, or - Log in to the server using a method other than SSH, such as a VNC console.
Protection of other services
Fail2ban also includes pre-configured filters for a number of other services, such as the [nginx-http-auth], [apache-auth], [postfix] and [dovecot] jails. You can enable these in the jail.local file by adding a line stating enabled = true, similar to the [sshd] section. The available filters can be found in the /etc/fail2ban/filter.d/ directory.