Securing Your Linux Server with Fail2ban
Guide to installing and configuring Fail2ban to protect your server from unauthorized access and brute force attacks.
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.
I assume you're working on a properly set-up Ubuntu server. If not, check out my guide on preparing Ubuntu servers to get started.
Author's Note
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.
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 bantime
, maxretry
, 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
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.
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.
Discussion