Fail2ban is a free and open source software we can use to mitigate brute force and DoS/DDoS attacks: it scans log files for multiple failed authentication attempts and bans related IP addresses by creating ad-hoc firewall rules.
In this tutorial, we see how to install and configure fail2ban on Linux, and we learn the basic concepts behind its usage.
In this tutorial, you will learn:
- How to install Fail2ban on some of the most used Linux distributions
- How to configure Fail2ban
- How to use the fail2ban-client utility
Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution agnostic |
Software | fail2ban |
Other | Root privileges |
Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
Installation
Fail2ban is available in the official repositories of all the most used Linux distributions. To install it on Debian and Debian-based distribution, we can use the following command:
$ sudo apt install fail2ban
On Fedora we perform the installation with the dnf
package manager:
$ sudo dnf install fail2ban
Before we can perform the installation on RHEL or one of its clones like Rocky Linux, we need to add the EPEL repository (Extra Package for Enterprise Linux) as a software source. In the case of Rocky this is a very simple operation, since the repository is automatically configured when we install the epel-release
package:
$ sudo dnf install epel-release
If using RHEL itself, the package can be download and installed from the EPEL site.
To ensure the fail2ban service is active and started at boot, we launch the following command:
$ sudo systemctl enable --now fail2ban
Fail2ban configuration
Once Fail2ban package is installed, all its configuration files can be found under the /etc/fail2ban
directory. We should avoid modifying files which come as part of the installation (those with the “.conf” extension), and place custom configurations in corresponding files with the “.local” extensions, instead. The main fail2ban configuration file is /etc/fail2ban/fail2ban.conf
. This file contains generic settings, such as the fail2ban loglevel. We place override values in the /etc/fail2ban/fail2ban.local
file, which should be created if it doesn’t exist. To change the loglevel from “INFO” (the default) to “DEBUG”, for example, we would write:
[DEFAULT] loglevel = DEBUG
There are three main “entities” we have to deal with when working with Fail2ban: filters, actions and jails. Let’s take a look at them.
Filters
Fail2ban scans log files and searches for failed authentication attempts. With filters, we basically tell it how to recognize authentication attempts in the log files of specific services. Ready to use filters can be found under the /etc/fail2ban/filter.d
directory:
$ ls /etc/fail2ban/filter.d 3proxy.conf domino-smtp.conf mysqld-auth.conf selinux-ssh.conf apache-auth.conf dovecot.conf nagios.conf sendmail-auth.conf apache-badbots.conf dropbear.conf named-refused.conf sendmail-reject.conf apache-botsearch.conf drupal-auth.conf nginx-botsearch.conf sieve.conf apache-common.conf ejabberd-auth.conf nginx-http-auth.conf slapd.conf apache-fakegooglebot.conf exim-common.conf nginx-limit-req.conf softethervpn.conf apache-modsecurity.conf exim.conf nsd.conf sogo-auth.conf apache-nohome.conf exim-spam.conf openhab.conf solid-pop3d.conf apache-noscript.conf freeswitch.conf openwebmail.conf squid.conf apache-overflows.conf froxlor-auth.conf oracleims.conf squirrelmail.conf apache-pass.conf gitlab.conf pam-generic.conf sshd.conf apache-shellshock.conf grafana.conf perdition.conf stunnel.conf assp.conf groupoffice.conf phpmyadmin-syslog.conf suhosin.conf asterisk.conf gssftpd.conf php-url-fopen.conf tine20.conf bitwarden.conf guacamole.conf portsentry.conf traefik-auth.conf botsearch-common.conf haproxy-http-auth.conf postfix.conf uwimap-auth.conf centreon.conf horde.conf proftpd.conf vsftpd.conf common.conf ignorecommands pure-ftpd.conf webmin-auth.conf counter-strike.conf kerio.conf qmail.conf wuftpd.conf courier-auth.conf lighttpd-auth.conf recidive.conf xinetd-fail.conf courier-smtp.conf mongodb-auth.conf roundcube-auth.conf znc-adminlog.conf cyrus-imap.conf monit.conf screensharingd.conf zoneminder.conf directadmin.conf murmur.conf selinux-common.conf
Actions
Fail2ban actions are defined in the /etc/fail2ban/action.d
directory. Actions are named after the software used to enforce the ban. Let’s see an example. UFW (Uncomplicated Firewall) is a firewall manager designed to be easy to use; this is the content of the /etc/fail2ban/action.d/ufw.conf
file:
# Fail2Ban action configuration file for ufw # # You are required to run "ufw enable" before this will have any effect. # # The insert position should be appropriate to block the required traffic. # A number after an allow rule to the application won't be of much use. [Definition] actionstart = actionstop = actioncheck = actionban = [ -n "<application>" ] && app="app <application>" ufw insert from to $app actionunban = [ -n "<application>" ] && app="app <application>" ufw delete from to $app [Init] # Option: insertpos # Notes.: The position number in the firewall list to insert the block rule insertpos = 1 # Option: blocktype # Notes.: reject or deny blocktype = reject # Option: destination # Notes.: The destination address to block in the ufw rule destination = any # Option: application # Notes.: application from sudo ufw app list application =
An action is composed of two main sections: “Definition” and “Init”. Commands specified in the former are executed in different situations: as a preliminary step (actioncheck), when a jail starts (actionstart), when it stops (actionstop), to ban (actionban) and to unban (actionunban) an IP address.
The “Init” section contains action-specific configurations. In the ufw action we reported above, for example, you can see it contains instructions about the firewall rule position in the rules list (insertpos = 1) and the blocktype to use (reject vs deny).
Jails
Finally, we have jails. A jail basically associates a filter and one or more actions. Fail2ban main configuration file for jails is /etc/fail2ban/jail.conf
; drop-in configuration files can be placed in the /etc/fail2ban/jail.d
directory.
Jails are named after the filter they use: if a jail is named “sshd”, for example, it is associated with the /etc/fail2ban/filter.d/sshd.conf
filter, unless one is explicitly specified via the “filter” option. The name of the jail is specified between square brackets. Debian provides an override for the sshd jail by default. It is defined in the /etc/fail2ban/jail.d/defaults-debian.conf
file:
[sshd] enabled = true
Defaults parameters for the “sshd” jail are in the main jail configuration file. Debian provides this override with the “enabled” parameter set to “true” just to ensure the jail is active. Here are some parameters which can be used when defining a jail, or in the “default” section (effective for all existing jails):
Option | Role | Default value |
---|---|---|
filter | Filter used by the jail | The filter corresponding to the jail name under /etc/fail2ban/filter.d |
logpath | Specifies the path(s) of the logfiles to be monitored | service-dependent |
action | Actions(s) to be used by the jail. Actions are named after the file in which they are defined, without the extension | %(action)s – see below |
ignoreip | List of IP addresses to ignore | None |
bantime | The ban duration expressed in seconds or with explicitly time suffixes | 10m |
findtime | The interval of time during which the specified number of failed authentication attempts must occur for an IP to be banned | 10m |
maxretry | The number of failures which must occur in the specified findtime to trigger a ban | 5 |
How the default action is defined
If you take a look at the main jail configuration file (/etc/fail2ban/jail.conf
), in the “default” section, you can see the action is defined the following way (line 268):
action = %(action_)s
In the definition above the _action
variable is “expanded” and its value is assigned to the “action” parameter. The _action
variable itself is defined a few lines above (line 212 on Debian):
action_ = __ %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
In this expression some other variables are used:
- banaction: this is the “core” ban action, set to iptables-multiport by default
- port: the ports to be banned – set to 0:65535 by default, to be overridden in specific jails
- protocol: the protocol used in the firewall rule to enforce the ban – tcp by default
- chain: the chain in which the jumps should be added in ban-actions which expect this parameter
The port, protocol and chain variables are used between square brackets, separated by commas. With this syntax, they are passed as “arguments” and substitute the respective placeholders contained in the action definition. Here, “action_” is one of the available macros, which just enforces a ban. Other ones are defined below it. Some examples are:
- action_mw – Enforces the ban and send an email containing a whois report to the specified mail
- action_mwl – Same as above, but includes relevant log lines
Let’s be banned!
Let’s verify fail2ban works correctly and let it trigger a ban. As we saw before, the default findtime is 10 minutes, and the default maxretry value is 5: this means that if we fail 5 authentication attempts in 10 minutes, our IP (192.168.122.1 for the sake of this example) will be banned.
I try to connect via SSH to the host with IP 192.168.122.93 providing a wrong password on purpose. This triggers the ban on the remote host. We can verify this by taking a look at the fail2ban log:
$ sudo tail /var/log/fail2ban.log
The relevant lines is:
2023-09-27 15:54:47,028 fail2ban.actions [2829]: NOTICE [sshd] Ban 192.168.122.1
As you can see, the 192.168.122.1 IP has been banned. A more convenient way to check all the active bans, is by using the fail2ban-client utility. To obtain a list of banned IPs, we use it with the “banned” subcommand:
$ fail2ban-client banned [{'sshd': ['192.168.122.1']}]
To unban an IP (from all jails), instead, we pass it as argument to the unban
subcommand:
$ sudo fail2ban-client unban 192.168.122.1
The fail2ban-client utility can also be used to control the server (start, stop, reload it) and perform some runtime configurations.
Conclusions
In this tutorial, we learned how to install and configure fail2ban on Linux. Fail2ban is a service which can automatically create firewall rules to block certain IPs by looking for failed login attempts in the log files of running services. We learned what entities are involved in the workings of fail2ban, and also saw some examples of how to use the fail2ban-client tool to list and modify active bans.