> For the complete documentation index, see [llms.txt](https://docs.glesys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.glesys.com/products/compute/guides-for-server-management/protect-ssh-with-fail2ban-in-debian-11-or-newer.md).

# Protect SSH with Fail2ban in Debian 11 or newer

***

Fail2Ban is a tool that protects Linux‑based machines from various types of attacks and malicious behavior. The tool can safeguard several services, including SSH, HTTP, and FTP.

Fail2Ban monitors log files in real time and looks for signs of automated attacks against your server. It provides effective protection against brute‑force attacks by automatically blacklisting attackers’ IP addresses in the firewall.

In this guide, you’ll see examples of some of **Fail2Ban’s** most basic features, and we’ll show you how to configure the tool to protect SSH on a virtual machine running Debian 11 in Glesys Cloud.

## Prerequiste

* Create a Cloud virtual machine with Debian 11 or newer as the operating system. The procedure is the same for Ubuntu 22.04 or newer—except for the final step concerning restarting the firewall.
* You need access to a user with root privileges. Log in as `root` or use the `sudo` prefix with your own user.

## Install Fail2ban

Start by updating the package repository:

{% code title="Command" %}

```
sudo apt update
```

{% endcode %}

Then, install Fail2ban:

{% code title="Command" %}

```
sudo apt install fail2ban
```

{% endcode %}

Once the installation is complete, we need to enable Fail2Ban so that it starts automatically whenever the server is rebooted:

{% code title="Command" %}

```
sudo systemctl enable fail2ban.service
```

{% endcode %}

## Configure Fail2ban

By default, the settings are located in `/etc/fail2ban/jail.conf`, but this file gets overwritten during a Fail2Ban upgrade. Therefore, we create a new file called `jail.local` instead. Settings placed in `jail.local` take precedence over those in `jail.conf`.

Create and open the file using the following command:

{% code title="Command" %}

```
sudo nano /etc/fail2ban/jail.local
```

{% endcode %}

Paste the section below and replace `<YOUR IP ADDRESS>` with your computer’s public IP address. This prevents you from temporarily locking yourself out. Fail2Ban supports both IPv4 and IPv6 addresses.

{% code title="/etc/fail2ban/jail.local" %}

```
[sshd]
ignoreip = 127.0.0.1 <YOUR IP ADDRESS>
enabled = true
port = 22
filter = sshd
banaction = nftables-allports
logpath = /var/log/auth.log
maxretry = 3
bantime  = 600
findtime = 600
```

{% endcode %}

These settings provide you with solid basic protection, but you can configure them to suit your needs.&#x20;

### Explanation of configuration options

Below you can see what each of the settings means:

{% code title="Snippet from /etc/fail2ban/jail.local" %}

```
ignoreip = 127.0.0.1 <YOUR IP ADDRESS>
```

{% endcode %}

Fail2Ban will not block the IP addresses listed in `ignoreip`. Replace with your own IP address to avoid being temporarily locked out.

{% code title="Snippet from /etc/fail2ban/jail.local" %}

```
banaction = nftables-allports
```

{% endcode %}

The `banaction` setting determines how the attacker’s IP address will be blocked. By default, Fail2Ban uses `iptables`, but since Debian 11, `nftables` has replaced `iptables`. Using `nftables-allports` blocks all of the server’s ports for the attacker. If you prefer to block only the SSH port for the attacker, replace `banaction = nftables-allports` with `banaction = nftables`.

{% code title="Snippet from /etc/fail2ban/jail.local" %}

```
maxretry = 3
```

{% endcode %}

`maxretry` specifies the number of login attempts allowed before an IP address is blacklisted within the `findtime` period.

{% code title="Snippet from /etc/fail2ban/jail.local" %}

```
bantime  = 600
```

{% endcode %}

`bantime` specifies the total duration in seconds that an IP address remains blacklisted. The default value of `600` means the IP address will be blocked for 10 minutes.

{% code title="Snippet from /etc/fail2ban/jail.local" %}

```
findtime = 600
```

{% endcode %}

`findtime` specifies the time window in which the allowed number of `maxretry` attempts must occur before the IP address is blacklisted.

### Restarting Fail2ban after modifying the configuration

After you have adjusted the configuration to suit your needs, save and close the file. Then restart Fail2Ban by running:

{% code title="Command" %}

```
sudo systemctl restart fail2ban
```

{% endcode %}

## Test Fail2ban with SSH

Login attempts via SSH are recorded in the file `/var/log/auth.log`. If Fail2Ban detects repeated SSH login attempts from the same IP address, it will eventually—according to the settings you configured above—blacklist that IP address in the firewall.

You can test this by repeatedly trying to SSH into your server with incorrect credentials from another computer.

Then check Fail2Ban’s log file by running:

{% code title="Command" %}

```
sudo cat /var/log/fail2ban.log
```

{% endcode %}

This will produce an output similar to this:

{% code title="Output" %}

```
2023-01-27 11:02:44,128 fail2ban.filter     [3066]: INFO    [sshd] Found 192.0.2.56 - 2023-01-27 11:02:44
2023-01-27 11:02:46,144 fail2ban.filter     [3066]: INFO    [sshd] Found 192.0.2.56 - 2023-01-27 11:02:46
2023-01-27 11:02:46,876 fail2ban.filter     [3066]: INFO    [sshd] Found 192.0.2.56 - 2023-01-27 11:02:46
2023-01-27 11:02:47,472 fail2ban.actions    [3066]: NOTICE  [sshd] Ban 192.0.2.56
```

{% endcode %}

Here, Fail2Ban has logged three login attempts from the IP address `192.0.2.56`, which it then blocked in the firewall.

You can verify that Fail2Ban has added the firewall rules by running:

{% code title="Command" %}

```
sudo nft list table inet f2b-table.
```

{% endcode %}

You should now see something similar to this:

{% code title="Output" %}

```
table inet f2b-table {
        set addr-set-sshd {
                type ipv4_addr
                elements = { 192.0.2.56 }
        }

        chain f2b-chain {
                type filter hook input priority filter - 1; policy accept;
                meta l4proto { tcp } ip saddr @addr-set-sshd reject
        }
}
```

{% endcode %}

Fail2Ban has created a firewall rule that blacklists all inbound traffic from `192.0.2.56`. If you have changed `banaction = nftables-allports` to `banaction = nftables` in the configuration file `/etc/fail2ban/jail.local`, only port 22 will be blocked instead.

Keep in mind that Fail2Ban is meant to work alongside other security measures on your server; it should not replace firewall rules.

## Restart Fail2ban together with the firewall (optional)

If you restart the firewall with `systemctl restart nftables`, the blacklisted IP addresses will disappear. This happens because Fail2Ban is the component that adds the rules to the firewall, and the rules are not stored permanently in the firewall itself.

To work around this, add a dependency to the `systemd` service for Fail2Ban. This tells `systemd` that the `nftables` firewall and Fail2Ban are linked, so a restart of the firewall should also trigger a restart of Fail2Ban. Because Fail2Ban will be restarted *after* the firewall starts, the rules will be reapplied.

Run the following command:

{% code title="Command" %}

```
sudo systemctl edit fail2ban.service
```

{% endcode %}

The default editor—most likely `nano`—will now open. The file already contains many comments. Edit the file so that the first eleven lines look like the example below (the lines that start with `###` are already present in the file):

{% code title="Beginning of /etc/systemd/system/fail2ban.service.d/override.conf" %}

```
### Editing /etc/systemd/system/fail2ban.service.d/override.conf  
### Anything between here and the comment below will become the new contents of the file  

[Unit]
Requires=nftables.service
PartOf=nftables.service

[Install]
WantedBy=multi-user.target nftables.service

### Lines below this comment will be discarded
```

{% endcode %}

Save the file and exit the editor.

Now you need to restart the `systemd` daemon so that the dependencies are updated. Do this with:

{% code title="Command" %}

```
sudo systemctl daemon-reload
```

{% endcode %}

Now we can restart the firewall without the rules for the blacklisted IP addresses disappearing.

## Summary

Fail2Ban is a good way to protect any service that uses authentication. You should now be better prepared to configure and use Fail2Ban to protect the specific services you run.

For more information about nftables, see [Set up a firewall on Debian 11 using nftables](/products/compute/guides-for-server-management/set-up-a-firewall-on-debian-11-or-newer-using-nftables.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.glesys.com/products/compute/guides-for-server-management/protect-ssh-with-fail2ban-in-debian-11-or-newer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
