Jul 20, 2023 9 min read

How to Protect SSH with Fail2Ban on Ubuntu 22.04

Protect SSH with Fail2Ban on Ubuntu 22.04 with our step-by-step tutorial. It is designed to protect your systems from malicious attacks.

Protect SSH with Fail2Ban on Ubuntu 22.04
Table of Contents

Choose a different version or distribution

Introduction

Before we begin talking about how to protect SSH with Fail2Ban on Ubuntu 22.04, let's briefly understand – What is Fail2Ban?

Fail2Ban is a powerful security tool designed to protect your systems from malicious attacks. It automatically detects and blocks suspicious activities by analyzing log files, such as repeated login failures or unauthorized access attempts.

With Fail2Ban, you can safeguard your servers, websites, and applications, reducing the risk of successful cyberattacks. Its proactive approach enhances security and ensures peace of mind for system administrators.

In this tutorial, you will learn how to install and use Fail2ban on an Ubuntu 22.04 server. We will also address a few FAQs on how to install Fail2Ban on Ubuntu 22.04.

Advantages of Fail2Ban

  1. Enhanced Security: Fail2Ban adds an extra layer of protection by blocking malicious IPs attempting unauthorized access.
  2. Automation: It automatically detects and responds to suspicious activities, saving time and effort for system administrators.
  3. Versatility: Fail2Ban works across various systems and applications, securing servers, websites, and more.
  4. Customizability: It allows fine-tuning of rules and actions to suit specific security requirements.
  5. Proactive Defense: Fail2Ban actively monitors log files, preventing potential attacks before they can compromise your systems.

Prerequisites to Protect SSH with Fail2Ban on Ubuntu 22.04

To complete this guide, you'll need:

  • A server running Ubuntu 22.04 with a non-root user with sudo privileges. Our Initial Server Setup with Ubuntu 22.04 tutorial contains more information on how to set up a user with these permissions.
  • Optionally, a second server from which you can connect to your first server and test getting intentionally banned.

Step 1 - Installing Fail2ban

Fail2ban can be found in Ubuntu's software repositories. Run the following commands as a non-root user to upgrade your package listings and install Fail2ban:

sudo apt update
sudo apt install fail2ban

After installation, Fail2ban will immediately start a background service. Since some of its default settings might have undesirable impacts, it is disabled by default. In order to confirm this, use the systemctl command:

systemctl status fail2ban.service
Output
○ fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; disabled; vendor preset: enabled
     Active: inactive (dead)
       Docs: man:fail2ban(1)

Fail2ban is immediately enabled, however you should first review some of its features.

Step 2 – Configuring Fail2ban

The /etc/fail2ban directory stores the configuration files for the fail2ban service. The defaults are stored in a file named jail.conf. Navigate to that directory and use head -20 to print the file's first 20 lines:

cd /etc/fail2ban
head -20 jail.conf
Output
#
# WARNING: heavily refactored in 0.9.0 release.  Please review and
#          customize settings for your setup.
#
# Changes:  in most of the cases you should not modify this
#           file, but provide customizations in jail.local file,
#           or separate .conf files under jail.d/ directory, e.g.:
#
# HOW TO ACTIVATE JAILS:
#
# YOU SHOULD NOT MODIFY THIS FILE.
#
# It will probably be overwritten or improved in a distribution update.
#
# Provide customizations in a jail.local file or a jail.d/customisation.local.
# For example to change the default bantime for all jails and to enable the
# ssh-iptables jail the following (uncommented) would appear in the .local file.
# See man 5 jail.conf for details.
#
# [DEFAULT]

The first few lines of this file are commented out, as you can see; they start with # characters to indicate that they should be viewed as documentation rather than settings. As you'll see, these comments are guiding you not to modify this file directly. Instead, you have two choices: establish distinct Fail2ban profiles in different files in the jail.d/ directory, or create and gather all of your local settings in a jail.local file. The jail.conf file will be updated on a regular basis as Fail2ban is updated, and it will be used a source of default settings for which you have not defined overrides.

You'll develop jail.local in this tutorial. You can accomplish this by copying jail.conf:

sudo cp jail.conf jail.local

You may now start making configuration changes. Open the document in nano or another text editor of your choice:

sudo nano jail.local

This guide will discuss several options that you may want to review as you browse through the file. The settings in the [DEFAULT] section near the top of the file will be applied to all the services supported by Fail2ban. Other headers in the file contain service-specific settings that will take precedence over the defaults and apply to [sshd] and other services as well.

[DEFAULT]
. . .
bantime = 10m
. . .

The bantime parameter specifies how long a client will be barred after failing to authenticate correctly. This unit of measurement is seconds. This is set by default to 10 minutes.

[DEFAULT]
. . .
findtime = 10m
maxretry = 5
. . .

The other two parameters are findtime and maxretry. They operate together to determine the circumstances under which a client is determined to be an illegitimate user who should be banned.

The maxretry variable controls the maximum number of attempts a client has to authenticate within the findtime defined time window before being blocked. By default, the fail2ban service will block a client who tries to log in 5 times in a 10-minute period without success.

[DEFAULT]
. . .
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
. . .

Examine the destemail, sendername, and mta settings if you require email notifications when Fail2ban takes action. The destemail option specifies the email address to which ban messages should be sent. The sendername determines the value of the "From" field in the email. The mail service that will be used to send mail is configured using the mta parameter. sendmail is used by default, but you can choose Postfix or another mail service.

[DEFAULT]
. . .
action = $(action_)s
. . .

When Fail2ban wants to impose a ban, this option configures the action it will take. The value action_ is defined immediately before this parameter in the file. Your firewall configuration should be updated by default to reject traffic from the offending host until the ban time has passed.

You can use one of the following action_ scripts in place of $(action_) above:

…
# ban & send an e-mail with whois report to the destemail.
action_mw = %(action_)s
            %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(action_)s
             %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(action_)s
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]

# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
…

action_cf_mwl does all of the above in addition to sending an update to the Cloudflare API connected to your account to ban the offender there as well, for instance, while action_mw takes action and sends an email, action_mwl takes action, sends an email, and includes logging.

Individual Jail Settings

The following section of the configuration file deals with individual services. The section headers, such as [sshd], specify this.

By adding an enabled = true line under the header and configuring the other settings, each of these parts must be enabled separately.

[jail_to_enable]
. . .
enabled = true
. . .

The other services are deactivated by default, but SSH is enabled. Other choices made here include the logpath, which instructs fail2ban where to find the service's logs, and the filter, which will be used to determine whether a line in a log signals a failed authentication.

The filter value is actually a reference to a file with the .conf extension that is present in the /etc/fail2ban/filter.d directory. Regular expressions, which are a popular abbreviation for text parsing, are used in these files to assess whether a line in the log represents a failed login attempt. Due to their complexity and the fact that the predetermined values match the appropriate lines well, we won't be going into great detail about these files in this article.

Nevertheless, by looking at that directory, you can see what kinds of filters are offered:

ls /etc/fail2ban/filter.d

You should use a text editor to open a file if it appears to be related to a service you are using. You should be able to at least tell what kind of condition the script was created to protect against because most of the files are reasonably well-commented. The jail.conf file has the necessary (disabled) portions for the majority of these filters, which we can enable in the jail.local file if needed.

Consider the scenario where you are using Nginx to serve a website and you notice that a password-protected area of your site is experiencing a surge in login attempts. The nginx-http-auth.conf file can be instructed to be used by fail2ban to check for this condition within the /var/log/nginx/error.log file.

Actually, this is already configured in the [nginx-http-auth] area of your /etc/fail2ban/jail.conf file. It would only be necessary to include the enabled parameter:

. . .
[nginx-http-auth]

enabled = true
. . .

Save your work and then exit the file. You can now make your Fail2ban service automated moving forward by enabling it. Run systemctl enable first.

sudo systemctl enable fail2ban

Start it manually by using systemctl start after that:

sudo systemctl start fail2ban

You may check its status with systemctl status:

sudo systemctl status fail2ban
Output
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enab>
     Active: active (running) since Mon 2022-06-27 19:25:15 UTC; 3s ago
       Docs: man:fail2ban(1)
   Main PID: 39396 (fail2ban-server)
      Tasks: 5 (limit: 1119)
     Memory: 12.9M
        CPU: 278ms
     CGroup: /system.slice/fail2ban.service
             └─39396 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Jun 27 19:25:15 fail2ban22 systemd[1]: Started Fail2Ban Service.
Jun 27 19:25:15 fail2ban22 fail2ban-server[39396]: Server ready

You will show Fail2ban in action in the next step.

💡
If you are facing a problem with nginx-http-auth because of the log file, you can fix it by adding this line backend = systemd below logpath under nginx-http-auth.

Step 3 - Testing the Banning Policies (Optional)

You can test the rules by having the second server banned from another server, one that won't need to connect to your Fail2ban server in the future. Try to SSH into the Fail2ban server after logging into your second server. You can attempt to join using a name that doesn't exist:

ssh blah@your_server

Fill up the password prompt with random characters. Do this several times. At some time, the error you're receiving should change from Permission denied to Connection refused. This indicates that the Fail2ban server has banned your second server.

You can view the new rule on your Fail2ban server by looking at the iptables output. With the iptables command, you can interact with the server's low-level firewall and port rules. You will be using ufw to control firewall rules at a higher level if you followed DigitalOcean's instructions for initial server setup. You may view all the firewall rules that ufw has already created by running iptables -S:

sudo iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N f2b-sshd
-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
…

You can view the rules that fail2ban added if you pipe the output of iptables -S to grep and search within those rules for the string f2b:

sudo iptables -S | grep f2b
Output
-N f2b-sshd
-A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd
-A f2b-sshd -s 134.209.165.184/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN

Fail2ban will have inserted a line containing REJECT --reject-with icmp-port-unreachable, and it should represent the IP address of your second server.

FAQs to Protect SSH with Fail2Ban on Ubuntu 22.04

How does Fail2Ban protect SSH?

Fail2Ban monitors SSH logs and blocks IP addresses that exhibit suspicious behavior, such as excessive login failures, protecting your SSH service from brute-force attacks.

How do I configure Fail2Ban for SSH protection?

The configuration file for Fail2Ban is located at /etc/fail2ban/jail.conf. You can customize the SSH protection settings by modifying this file.

How long are IP addresses blocked by Fail2Ban?

By default, IP addresses are blocked for a specific duration, usually defined in the Fail2Ban configuration file. The default duration is typically a few minutes.

Can I whitelist specific IP addresses with Fail2Ban?

Yes, you can whitelist specific IP addresses by adding them to the ignoreip section in the Fail2Ban configuration file.

How can I check if Fail2Ban is running correctly?

You can check Fail2Ban's status by running the command: sudo fail2ban-client status. It will display the jails and their respective status.

Can I receive email notifications for blocked IP addresses?

Yes, Fail2Ban can send email notifications when an IP address is blocked. You can configure the email settings in the Fail2Ban configuration file.

How can I unban an IP address blocked by Fail2Ban?

You can manually unban an IP address by running the command: sudo fail2ban-client unban <IP_ADDRESS>.

Conclusion

We hope this detailed tutorial helped you understand how to protect SSH with Fail2ban on Ubuntu 22.04.

If you have any suggestions or queries, kindly leave them in the comments section.

Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to DevOps Blog - VegaStack.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.