Fail2Ban is a security tool that helps protect your server from unauthorized access attempts and brute force attacks by monitoring logs for suspicious activities and blocking the IP addresses of attackers.

This will allow your server to harden itself against these access attempts without intervention from you.

In this guide, I’ll walk you through installing and configuring Fail2Ban.

Preparation

To make the most of this guide, ensure you have a properly set up Ubuntu server.

👉
Check out my guide on preparing Ubuntu servers to ensure your server is properly set up.

If you don’t have one, consider getting a free VPS server to follow along.

Considerations

Before we dive into the technical details, I want to highlight a few important considerations regarding Fail2ban.

Firstly, it's crucial to understand that Fail2ban should not be your sole security measure. Some may mistakenly believe it can replace firewall rules, but that is not the case.

Additionally, disabling password authentication and relying solely on SSH key authentication may lessen the need for Fail2ban.

However, I still advocate for its use as an additional layer of security.

Installation

Fail2ban is available in Ubuntu’s repositories.

To install it, use this command:

sudo apt install fail2ban

I noticed that Fail2ban disables its service upon installation on Ubuntu 22.04 due to some default settings that may cause unexpected behavior. In contrast, it is activated by default on Ubuntu 24.04.

You can verify this by using the following command:

sudo systemctl status fail2ban

That's it for the installation.

Pre-Configuration

Fail2ban's configuration files are located in the /etc/fail2ban/ directory.

If you list the contents of this directory, you will find two important configuration files: fail2ban.conf and jail.conf.

The fail2ban.conf file contains Fail2Ban's global settings, which I don't recommend modifying.

The jail.conf file contains jails, filters with actions.

We shouldn't directly modify these files, as an update may override our changes.

That's why Fail2Ban recommends creating two local copies of these configuration files for us to modify.

Use the following commands to create a local copy of these two files:

sudo cp jail.conf jail.local
sudo cp fail2ban.conf fail2ban.local

Now you can safely modify Fail2Ban's configuration.

Configuration

Open the jail.local file with your preferred editor and examine its settings.

Under the [DEFAULT] section, you will find settings that apply to all services protected by Fail2Ban.

Elsewhere in the file, there are sections like the [sshd] section, which contains service-specific settings (or individual jails) that will override the defaults.

Under the [DEFAULT] section, there are some variables that you may want to modify.

bantime

The bantime variable sets the duration for which an IP will be blocked from accessing the server after failing to authenticate correctly.

By default, this is set to 10 minutes.

You can change its value as you prefer, for instance, to 60m for one hour.

findtime
maxretry

The findtime and maxretry variables function together to determine the conditions under which an IP should be blocked from accessing the server.

The maxretry variable defines the number of authentication attempts an IP is allowed to make within a time period defined by findtime before being blocked.

With the default settings, Fail2Ban will block an IP that unsuccessfully attempts to access the server more than 5 times within a 10-minute interval.

#ignoreip = 127.0.0.1/8 ::1

The ignoreip variable contains a list of IP addresses, CIDR masks, or DNS hosts that Fail2ban won't block.

By default, this variable is commented out.

I strongly advise uncommenting this line and appending your own IP address to the list. This ensures that you won't inadvertently block yourself from accessing the server.

Email Alerts

Receiving email alerts is a practice I consistently advocate for in all of my guides.

If you want to receive email alerts whenever Fail2ban blocks an IP, you should adjust these two variables inside the jail.local file:

destemail
sender

The destemail variable defines the email address to which the alerts should be sent.

The sender variable defines the email address from which the alerts will be sent.

But there is something to pay attention to.

The sender variable should look like this:

sender = root@example.com

Don't use your hostname. This won't work:

sender = root@host.example.com

Lastly, there is the mta variable, which specifies the mail agent that will be used to send the emails.

By default, Fail2ban uses Sendmail as its mail agent.

If you prefer to use Postfix, you can do so without changing the mta variable, as Fail2ban will automatically use it if it is installed.

💡
Your server needs to be configured to send emails, and this can be done by setting up Postfix for external SMTP relay to ensure you receive alerts.

Now, there is one more step to take in order to receive alerts. Keep reading.

Default Action

If you scroll down a bit inside the jail.local file, you'll see the action variable:

action = %(action_)s

This variable dictates the action Fail2ban should take when blocking an IP address.

The default action is to add a firewall rule that rejects traffic from the IP address, removing it after the specified bantime elapses.

Aha, the default action doesn't send alerts, which is why I asked you to keep reading.

Above the action variable, you'll find various actions you can switch between.

For example, action_mw sends an email when taking action, action_mwl sends an email and includes logging, and action_cf_mwl does all of the above, plus sends an update to the Cloudflare API associated with your account to ban the attacker there as well.

I always prefer using the action_mwl action.

If you want to use it too, your action variable should be set as follows:

action = %(action_mwl)s

Now, whenever Fail2ban blocks an IP address, you'll receive an email alert, and Fail2ban logs the block.

Individual Jails

Now, it is time to examine the service-specific sections, also known as individual jails, such as the [sshd] jail, which protects our server from unauthorized access attempts.

Each of these jails needs to be individually enabled by adding an enabled = true line under the header, along with their other settings.

By default, only the [sshd] jail is enabled, and all others are disabled.

You can verify this by opening the /etc/fail2ban/jail.d/defaults-debian.conf file, which contains the line enabled = true for the [sshd] jail.

Scroll down the jail.conf file until you find the [sshd] jail, which should look similar to this:

port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

If you've changed the SSH port, ensure to update the value of the port variable accordingly.

You can include variables defined in the [DEFAULT] section, such as the bantimemaxretry, and findtime variables, which will only apply to this jail.

If you scroll down further, you'll find other jails that are disabled, such as the [nginx-http-auth] or [apache-auth] jails.

If you're running NGINX and want to protect a page of your site using a password, you could enable the [nginx-http-auth] jail to secure that page from unauthorized access attempts.

Starting Fail2ban

Since the [sshd] jail, which protects SSH, is enabled, we can proceed to start and enable the fail2ban service if it is disabled, depending on the version of Ubuntu you are using.

Use the following commands to start and enable Fail2ban:

sudo systemctl start fail2ban
sudo systemctl enable fail2ban

You can use the fail2ban-client command to check the active jails:

sudo fail2ban-client status

Output:

Status
|- Number of jail:	1
`- Jail list:	sshd

To view the status and information regarding a specific jail like the sshd jail, you can use the following command:

sudo fail2ban-client status sshd

Output:

Status for the jail: sshd
|- Filter
|  |- Currently failed:	5
|  |- Total failed:	21
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	1
   |- Total banned:	2
   `- Banned IP list:	218.92.0.29
If you have disabled password authentication for SSH, you may notice zero failed attempts.

Conclusion and Final Thoughts

Great job reaching the end!

There are many more things you can do with Fail2Ban, but for now, protecting SSH is the most important.

🙆‍♂️
There's more to securing Linux servers. I’ve created a comprehensive guide on server security and hardening, where I share the exact security measures I implement on my own servers.

If you found value in this guide or have any questions or feedback, please don't hesitate to share your thoughts in the discussion section.

Your input is greatly appreciated, and you can also contact me directly if you prefer.