How to Protect Your Server With Fail2Ban in Linux

A peron in front of a computer typing.

Securing a server is a top priority for any business or organization. One of the most important tools in a sysadmin’s toolkit is Fail2Ban. This guide explains what Fail2Ban is and how you can use it to protect your Linux server from attacks.

Tip: in addition to Fail2Ban, check out these open-source tools to secure your server.

What Is Fail2Ban?

Fail2Ban is an intrusion prevention tool that monitors log files and bans IP addresses that show signs of malicious activity. It does this by creating “filters” that match certain patterns in the log files and executing actions, such as banning the offending IP address.

Why Use Fail2Ban?

There are a few reasons to use fail2ban. It can:

  • save you time by automatically banning malicious IP addresses.
  • help to secure your server by reducing the chances of a successful attack.
  • give you peace of mind knowing that your server is being monitored and protected.

Installing Fail2Ban

By default, Fail2Ban is available in the Ubuntu repositories. Install it using apt.

sudo add-apt-repository universe
sudo apt update && sudo apt install fail2ban -y
A terminal window showing the installation process for Fail2ban.

Fail2Ban will set its service in the background, but systemd will disable it by default. You can start and enable it with the following commands:

sudo systemctl start fail2ban
sudo systemctl enable fail2ban

Verify that Fail2Ban is running with the following command:

sudo systemctl status fail2ban

You will see an output similar to the image below.

A terminal window showing the Fail2ban service running.

Configuring Fail2Ban

The “/etc/fail2ban” directory contains the configuration files for Fail2Ban. By default, Fail2Ban comes with a “jail.conf” file that contains settings that will apply to all services.

A terminal window showing the contents of the Fail2ban directory.

However, it is good practice to create a local “jail.local” file and override the settings in “jail.conf,” as you will lose any changes you make to “jail.conf” whenever the program updates.

You can create your “jail.local” file with the following commands:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Open the jail.local file to edit it:

sudo nano /etc/fail2ban/jail.local
A terminal window showing the new jail.local file.

Good to know: learn how to create a SSH honeypot to catch hackers in your server.

Exploring the jail.local File

You will see a similar output as below and may be overwhelmed by the number of options available. But don’t worry, as we are walking you through the most important options.

A section of a terminal showing the comments on the jail.local file.

You will see the “#” symbol at the beginning of a line, indicating that it is a comment. Fail2Ban uses these to explain what a particular setting does. You can enable some of the settings here by removing this symbol.

The “[DEFAULT]” section contains the options applied to all jails. This is the global configuration for Fail2Ban. The following screenshot shows an example of this.

A section of a terminal showing the default bantime length.

There are also other sections that start with the name of a service. This jail applies to a specific service over the top of the global jails.

For example, there is a section for “sshd” jail. This section contains the options that are specific to the sshd service.

A section of a terminal showing the disable sshd service.

Tip: you can also learn more about server hardening by securing your SSH server.

Enabling the Autoban Feature

Navigate to the “bantime = 1h” setting and remove the “#” symbol at the beginning of the line to enable it. This line sets the duration for how long Fail2Ban will disable an IP address. The default unit is one hour. You can also use other units, such as minutes(m), days (d), or even weeks (w).

A section of a terminal showing the enabled default setting.

You can increase or decrease this value as you see fit. For example, you can change this value to 30m to reduce the length of the ban to 30 minutes.

A section of a terminal showing a reduced bantime length.

Changing the Default Login Window Length

The next settings are “maxretry” and “findtime.” They determine how many login attempts an attacker can do before Fail2Ban bans his IP.

The default values for “maxretry” and “findtime” are 5 and 10m. If an IP fails to authenticate five times in ten minutes, Fail2Ban will ban it for the duration specified by the bantime setting.

A section of a terminal showing the default login interval.

You can change these values to whatever you want. For example, you can set “maxretry” to 3 and “findtime” to 5m: Fail2Ban will disable an IP if it fails to authenticate three times in five minutes.

A section of a terminal showing a reduced login interval.

Enabling Fail2Ban’s Notification Feature

The next settings are destemail, sendername and mta. These settings are what Fail2Ban will use to configure email notifications.

  • The destemail setting is the email address where the program will send its notifications.
  • The sendername is the name that will show up in the “From” field of the notification email.
  • The mta is the mail transfer agent that Fail2Ban will use to send emails. The default mta is sendmail, but you can change it to something else like mail.

If you want to receive email notifications, you need to uncomment these lines and enter the appropriate values as shown.

A section of the terminal that shows a customized mail setting.

When a ban occurs, you will receive an email notification with details about the ban as shown.

A terminal window that shows a mail notification from Fail2ban.

Creating Custom Ban Commands

The next setting is “action_ =.” This determines the action that Fail2ban takes when it bans an IP address. The default action is to use iptables to block the IP until the “bantime” has passed.

You can also use other actions, as shown below. This tutorial sticks with the default for the sake of simplicity.

  • action_mw: sends an email notification when an IP is banned, attached with relevant WHOIS information.
  • action_mwl: sends an email notification when an IP is banned, attached with relevant WHOIS information and the log file entries that triggered the ban.
  • action_xarf: sends an email notification in the X-ARF format when an IP is banned with the log file entries that triggered the ban.

Many other actions are available, but it’s impossible to cover them all in this tutorial. You can read about all of the available actions in the Fail2ban documentation.

A section of a terminal that shows the default actions for Fail2ban.

Enabling Service-Specific Configuration

Aside from configuring Fail2ban’s default behavior, it is also possible to use pre-made “filter files” for some of the common Internet services. These are small files that the developers wrote to look for specific log output of a particular server daemon.

For example, the “apache-shellshock.conf” file contains all of the necessary settings to allow Fail2ban to check for any malicious attempts to create the shellshock bug.

A terminal window showing a sample filter file.

You can find all the available filter files for your system by listing the “/etc/fail2ban/filter.d” directory:

ls /etc/fail2ban/filter.d
A terminal window showing the filter files available for Fail2ban.

Once you know the filters that you want to use, tell Fail2ban to load them during startup by opening your “jail.local” file:

sudo nano /etc/fail2ban/jail.local

Create a space in “jail.local” where you can activate your new filters. I am creating mine between the comment header and the [INCLUDES] block.

A section of a terminal that shows new space for configuring Fail2ban.

Add the filters that you want to activate. For example, the following is an excerpt that I use in my configuration:

# Comments: use '#' for comment lines and ';' (following a space) for inline comments
 
[sshd]
enabled = true
 
[nginx-bad-request]
enabled = true
 
[bitwarden]
enabled = true
 
[INCLUDES]
A terminal section that shows all the enabled filter services.

Once done, save and close the file. Restart fail2ban to apply the changes.

sudo systemctl restart fail2ban

Testing Your Configuration

Now that you have configured fail2ban, it’s time to test it.

The simplest way to test your configuration is to try to log in with an incorrect password multiple times in quick succession. You can use an SSH connection to do this.

On a disposal machine, try to SSH into your Fail2ban server using an “admin” username. Replace “your_server_ip_address” with the actual IP address of your Fail2ban server.

ssh admin@your_server_ip_address

Enter a random password when prompted and repeat it a few times. After a few attempts, you will see a message that the server refused your connection attempt.

A terminal window showing Fail2ban in action.

Aside from using ssh, you can also test the other filter files in Fail2ban by triggering their “fail state.” In my case, I am using the “nginx-bad-request” filter that detects whether there is a host that’s flooding the server with invalid requests.

A terminal window showing the bad request filter.

Knowing that, you can test this feature by deliberately sending empty requests to your web server using curl:

curl -H "User-Agent:" -H "Host:" https://yourwebsite.com -v
A terminal window showing a simple bad request.

Good to know: while Fail2ban works brilliantly with Nginx, you can also use this program to protect your Apache server.

Verifying Fail2ban’s Actions

Finally, run the below command on your Fail2ban server to verify that fail2ban has added the necessary rules to iptables.

The grep command filters the output of the iptables command. The -S option tells iptables to print the rules in a format that can be easily parsed.

sudo iptables -S | grep f2b

You will see an output similar to the one pictured below. The “–reject-with icmp-port-unreachable” argument tells iptables to send an ICMP port unreachable message back to the client when it tries to connect. You can also see the IP addresses of the machines that server has banned.

A terminal window showing a rejected IP address in iptables.

Tip: you should also make use of SELinux to secure your Linux server.

Frequently Asked Questions

Why do I get an empty email notification when Fail2ban bans an IP address?

If you get an empty email notification, it’s likely that you have not configured your mail server correctly. Check the configuration of your mail server and make sure that it’s able to send email.

How do I unban an IP address?

First, find the jail where the IP address is currently banned: sudo fail2ban-client status <jail_name>, then unban the IP address by running the following: sudo fail2ban-client set <jail_name> unbanip <ip_address>.

How do I view the fail2ban log file?

You may want to view the fail2ban log file to troubleshoot issues or to see why an IP was banned. The “/var/log/fail2ban.log” file contains all of the logs generated by fail2ban. Use the cat command to view the fail2ban log file: cat /var/log/fail2ban.log.

I enabled multiple filter files. Why are all of them not working?

This issue is most likely caused by a filter overwriting a different file that came before it. One way to fix this is to create your own filter file by combining multiple filters together.

Will Fail2ban protect my server from a DoS attack?

Yes and no. For the most part, Fail2ban will be able to prevent any IP address that is spamming invalid requests to your server. However, one of the biggest limitations of this program is that it cannot act on events that do not produce a log entry. As such, it is still important to secure your Linux server using other tools for these forms of attacks.

Image credit: Unsplash. All alterations and screenshots by Ramces Red.

Subscribe to our newsletter!

Our latest tutorials delivered straight to your inbox

Ramces Red
Ramces Red - Staff Writer

Ramces is a technology writer that lived with computers all his life. A prolific reader and a student of Anthropology, he is an eccentric character that writes articles about Linux and anything *nix.