How to install and configure Fail2ban on Linux

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

How to install and configure fail2ban on linux
How to install and configure fail2ban on linux
How to install and configure Fail2ban on Linux- Original image by Pete Linforth from Pixabay
 Software Requirements and Linux Command Line Conventions
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.



Comments and Discussions
Linux Forum