How Fail2ban Works to Protect Services on a Linux Server

Any service or application connected to the internet is potentially vulnerable to attacks from malicious parties. Internet admins and web developers are no strangers to hacks and security compromises – regardless of the type of service being hosted.

One common example of this is with Secure Shell, or SSH. SSH is used to access the command line interface for remote servers, but it can also be a target for hackers attempting to gain entry and exploit the system. Once they have access, they can cause endless problems for you and your business!

Often hackers will try to access a server with brute-force attacks – essentially trying many different combinations of usernames and passwords until the right combination is found. By using bot networks, they can cycle through a massive number of combinations in a relatively short period of time.

Thankfully there are a variety of different services that can be used to mitigate attacks such as these. Fail2Ban is one such service, and has become a very popular choice with server administrators.

In this guide we’re going to be looking at exactly what Fail2Ban is, and how it works to protect services on a typical Linux server.

What is Fail2Ban?

In practice, Fail2Ban is a brute force protection service that works by dynamically altering firewall rules to ban internet addresses that have unsuccessfully attempted to login to the server, more than a certain number of times. 

Essentially Fail2Ban constantly monitors common services to spot patterns of authentication failures. Once these patterns are spotted, Fail2Ban performs certain actions against traffic originating from that address. Most often these actions are used to block, or ban, an unauthorised person from attempting to access the system.

Using Fail2Ban can help protect your system against brute force attacks, DDoS attacks, and various similar types of malicious activity. While it certainly isn’t an all-in-one security system, it can be used to provide some level of protection, which can be further added upon with other security software.

graphic depicting fail2ban acting with a firewall on a linux server

How does it work?

If Fail2Ban is configured to monitor the log files of common services on a system, it scans filters that have been created, specific to that service. This filter is designed to identify authentication failures for that service, through the use of complicated regular expressions. These patterns of regular expressions are defined in a variable called failregex.

When a line in the service’s log file matches the failregex defined in the filter, then the defined action is then executed for that service. An action is a variable that can be configured to do a number of different things, depending on the preferences of the system administrator.

The default action is to ban the unauthorised host or IP address from accessing the system, by modifying the firewall iptables rules. This can also be expanded, to send an email with the relevant information to the administrator for example.

You can also modify the target of the action to be something other than iptables, if for example you have a different firewall configuration or notification preference.

By default, Fail2Ban will perform the action once 3 authentication failures have been detected from a single IP address in 10 minutes, and the offending IP address will be banned for 10 minutes. Both of these thresholds are completely customisable in the default configuration file.


System Settings & Configuration Files

Fail2Ban utilises several configuration files to take the defined actions against unauthorized IP addresses. Each of these files are set with default values, but can be modified by the administrator at any time.

The two primary configuration files are:

  • The Fail2Ban configuration file: fail2ban.conf
  • The Jail configuration file: jail.conf
  • The Filter file
  • The Action file

Let’s take a brief look at the purpose of these configuration files.

The Fail2Ban configuration file

The fail2ban.conf file configures some of the basic default operational settings for the service. Many of these can often be left unchanged, depending on your requirements.

Three of the main settings included here are:

  • Maxfailures: how many failed authentication attempts can be made, before the IP address is banned
  • Findtime: the specified period in which the maximum amount of failed authentication attempts can be made, by one IP address
  • Bantime: the amount of time that an IP address will be blocked for 

This file also allows the administrator to configure any email notifications to be sent following IP address bans.

Additionally, this file specified which log files Fail2Ban should monitor for failed authentication attempts. 

Note: these settings only define the default policy, and the jail configuration files will overwrite these. As such, you don’t normally need to modify these.

The Jail configuration file

Now we’re going to look at perhaps the most important configuration file, the jail.conf file. 

This configuration file defines the “jails”, which are combinations of a filter and one or several actions. In other words, they define when IP addresses should be considered suspicious, and what actions should be taken upon them once they have been detected.

Let’s look at each section of this file in detail.

The Default Section

This first portion of the Jail configuration file overwrites the default policy for Fail2Ban, and can be overridden in each individual service’s configuration section.

The full default section uncommented looks like this:

[DEFAULT]
 ignoreip = 127.0.0.1/8
 bantime = 600
 findtime = 600
 maxretry = 3
 backend = auto
 usedns = warn
 destemail = root@localhost
 sendername = Fail2Ban
 banaction = iptables-multiport
 mta = sendmail
 protocol = tcp
 chain = INPUT
 action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
 action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
           %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
 action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
            %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
 action = %(action_)s 

This may seem confusing – but don’t worry! 

We’ll explain exactly what each of these parameters mean below:

  • ignoreip: This identifies IP addresses that should be ignored by Fail2Ban. By default, this is configured to ignore traffic coming from the machine itself.
  • bantime: This defines the length of a ban in seconds. The default is 600 seconds, or 10 minutes.
  • findtime: This defines the window that fail2ban will pay attention to when monitoring for repeated failed authentication attempts. The default is set to 600 seconds, which means that it will count the number of failed attempts in the last 10 minutes.
  • maxretry: This sets the maximum number of failed attempts that will be accepted within the findtime window, before a ban is actioned.
  • backend: This entry specifies how fail2ban will monitor log files. The setting of auto means that fail2ban will try pyinotify, then gamin, and then a polling algorithm based on what’s available.
  • usedns: This determines whether reverse DNS is used to help implement bans. Setting this to “no” will ban IPs themselves, rather than hostnames. The “warn” setting will attempt to use reverse-DNS to look up the hostname and ban using that, but will still log the activity for review.
  • destemail: This is the email address that will be sent notification emails, if configured.
  • sendername: This is used in the email from field, for generated notification emails
  • banaction: This sets the action that will be used when the threshold is reached.
  • mta: This is the mail transfer agent that should be used to send notification emails.
  • protocol: This is the type of traffic that will be dropped when an IP ban is implemented. This is also the type of traffic that is sent to the new iptables chain.
  • chain: This is the chain that will be configured with a jump rule to send traffic to the fail2ban funnel.

The other parameters here define different actions that can be specified. For a simple Fail2Ban setup, you shouldn’t need to worry about these.

Service Specific Sections

Under the default section, there are sections for specific services, that are used for overwriting the default policies. 

Each section header looks like this:

<pre>
 [<span class=“highlight”>service_name</span>]
</pre> 

However, the section will only be read if it includes the following line:

enabled = true

Within each section the parameters are configured, including the location of the log file that should be monitored, and the filter file that should be used to parse the logs.

As an example, the section that defines the actions for the SSH service reads as follows:

[SSH]
enabled     = true
 port        = ssh
 filter      = sshd
 logpath     = /var/log/auth.log
 maxretry    = 6 

Line by line, it does the following:

  1. Enables the section
  2. Sets the port to the “ssh” port (22 by default)
  3. Fail2Ban reads the filtering mechanisms from the sshd.conf file
  4. It then parses the log files located at /var/log/auth.log, using these filtering mechanisms
  5. Finally, it sets the maximum number of failed authentication attempts for the SSH service to 6

Everything else that Fail2Ban needs is taken from the default section of the jail configuration file, which helps to streamline the setup and simplify things.

The Filter File

The filter file determines the lines that Fail2Ban will look for in the log files to identify suspicious characteristics from users attempting to gain access.

Now we’re going to take a look at the filter file (sshd.conf) that our SSH service has called for in the above configuration file:

[INCLUDES]
 before = common.conf
 [Definition]
 _daemon = sshd
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from ( via \S+)?\s$ ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for . from \s$ ^%(__prefix_line)sFailed \S+ for .? from (?: port \d)?(?: ssh\d)?(: (ruser .|(\S+ ID \S+ (serial \d+) CA )?\S+ %(__md5hex)s(, client user ".", client host ".")?))?\s$
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM \s$ ^%(__prefix_line)siI user . from \s$ ^%(__prefix_line)sUser .+ from not allowed because not listed in AllowUsers\s$
^%(__prefix_line)sUser .+ from not allowed because listed in DenyUsers\s$ ^%(__prefix_line)sUser .+ from not allowed because not in any group\s$
^%(__prefix_line)srefused connect from \S+ ()\s$ ^%(__prefix_line)sUser .+ from not allowed because a group is listed in DenyGroups\s$
^%(__prefix_line)sUser .+ from not allowed because none of user's groups are listed in AllowGroups\s*$

The syntax of the filter file makes it fairly complicated and difficult to understand. But we will try to break it down!

First off, the [INCLUDES] section header specifies other filter files that are read in, either before or after this file. In this example, the common.conf file is read in, and placed before other lines in this file. This configures some parameters that can be used later.

Next, the [DEFINITION] section defines the actual rules to be used, for our filter matches. First we need to set the name of the daemon, or service, that we are monitoring by using the _daemon parameter.

Now we move to the failregex definition, which sets the patterns that will be triggered one a matching line in the log file is identified. In other words, these are regular expressions that match based on different errors or failures that are produced when a user fails authentication.

Some parts of the lines like ^%(__prefix_line) will be substituted with the values of a parameter which is setup in the common.conf file, in our example. This is used to further identify information that operating systems write to log files.

The Action File

The final configuration file we’re going to be looking at is the Action file. This file is responsible for setting up the firewall rules that take the necessary actions against suspicious IP addresses or hosts, which is usually banning them.

In this post, the action file that the SSH service invokes is the iptables-multiport file.

With all comments removed, the file looks like this:

[INCLUDES]
before = iptables-blocktype.conf

[Definition]
actionstart = iptables -N fail2ban-
iptables -A fail2ban- -j RETURN
iptables -I -p -m multiport --dports -j fail2ban-
actionstop = iptables -D -p -m multiport --dports -j fail2ban-
actioncheck = iptables -n -L | grep -a 'fail2ban-[ \t]'
actionban = iptables -I fail2ban- 1 -s -j
actionunban = iptables -D fail2ban- -s -j

[Init]
name = default
port = ssh
protocol = tcp
chain = INPUT 

The [INCLUDES] section calls a different action file, iptables-blocktype.conf, which defines the blocktype parameter. This parameter configures the restriction that will be actioned when a client is banned.

Next, we get to the definitions of the rules themselves. The actionstart action sets up the iptables firewall for when the Fail2Ban service is started. This creates a new chain, adds a rule that returns to the calling chain, and then inputs a rule at the start of the INPUT chain. This rule passes traffic that matches the correct port numbers and protocols, to the new chain.

To do this, it uses the value passed in with the action that was defined in the jail.local file.

Moving down to the actionstop line, you can see that these firewall commands are simply a reversal of the actionstart commands.

Next the actioncheck line verifies that the proper chain has been created, before attempting to add any ban rules.

Now we move on to the actual banning rule, called actionban. This rule works by adding a new rule to the newly created chain. It matches the source IP address of the suspicious client and then applies the block, defined by the earlier blocktype parameter.

The actionunban line simply removes the banning rule, which is done automatically when the ban time has elapsed.

Finally, the [INIT] section contains some default settings that are used in case the appropriate values aren’t passed in to the action file, when called.


In Conclusion

We hope to have provided an overview of how Fail2Ban works in this article. This only covers some of the basics, and there is plenty more to learn!

At UKHost4u we offer a range of dedicated servers to suit any kind of business. Take a look on our website to see what we can do for you!

Leave a Reply

Your email address will not be published.