Skip to content
Serverküche
Search

Loading search … (only available on the published site).

Security Difficulty: Intermediate

Setting up Fail2ban: block brute-force attacks automatically

Fail2ban watches your logs and bans IPs after too many failed attempts – with a safe whitelist for your own address so you don't lock yourself out.

· 6 min read ·Duration: approx. 40 minutes
Table of contents

After a few days on the internet, take a look at journalctl -u ssh: hundreds of login attempts from foreign IPs, one every second. As long as your SSH is switched to key login, none of them gets in – but it clutters the log and eats resources. Fail2ban reads along with these logs and bans automatically whoever tries too often without success.

What are we building?

By the end, Fail2ban 1.1 on your Debian 13 monitors the SSH logins and, after too many failed attempts, bans the attacking IP for a defined time – via a firewall rule. Your own IP is on a whitelist so this never hits you. You can view bans, set them manually and lift them again.

Prerequisites

Step by step

Before we configure, three terms that explain the whole tool:

  • Filter – a pattern that detects a “failed login” in the log (for SSH, Fail2ban brings this ready-made).
  • Jail – connects a filter with a log source and the rules “how often in what time frame”. The sshd jail monitors the SSH logins.
  • Action – what happens when it’s exceeded: by default a firewall rule that blocks the IP for bantime.

In short: filter detects failed attempts → jail counts them → action bans. Everything you configure below is one of these three knobs.

Step 1: Install Fail2ban

Terminal
sudo apt update
sudo apt install -y fail2ban

Check the version:

Terminal
fail2ban-client --version
Ausgabe
Fail2Ban v1.1.0

Step 2: Your own configuration in jail.local

Never edit jail.conf

The shipped /etc/fail2ban/jail.conf is overwritten on updates. Your own settings always belong in /etc/fail2ban/jail.local – this file is preserved and overrides the defaults.

Create the file:

Terminal
sudo nano /etc/fail2ban/jail.local
INI
[DEFAULT]
# How long the ban lasts
bantime = 1h
# Time window in which the failed attempts count
findtime = 10m
# This many failed attempts are allowed, then a ban
maxretry = 5
# Your own IP(s) – will NEVER be banned
ignoreip = 127.0.0.1/8 ::1 YOUR_OWN_IP

[sshd]
enabled = true

Line by line:

  • bantime = 1h – ban duration. For stubborn cases, see the escalation in step 5.
  • findtime + maxretry – “5 failed attempts within 10 minutes → ban”.
  • ignoreip – the most important line: enter your own IP here so you don’t lock yourself out. If you have a changing IP at home, better use access via a fixed point (a VPN later) instead of a broad allowance.
  • [sshd] enabled = true – activates the SSH jail.

Enter your own IP first

Set your own IP in ignoreip before you start Fail2ban – otherwise even your own typo on login could lock you out. The address you’re currently connected from is shown by the first field of echo "$SSH_CLIENT".

Debian 13 reads the systemd journal

On Debian 13, Fail2ban uses the systemd journal as its source by default – you don’t need to specify a logpath (like /var/log/auth.log). On modern systems that file often no longer exists at all; the journal is the right source and works without extra configuration.

Step 3: Start and enable the service

Terminal
sudo systemctl enable --now fail2ban

enable --now starts the service immediately and ensures it runs again automatically after a reboot. Check that it runs cleanly:

Terminal
sudo systemctl status fail2ban

You should see active (running). After every change to jail.local, reload the configuration with sudo systemctl reload fail2ban.

Step 4: Check the status

This is how you see which jails are active:

Terminal
sudo fail2ban-client status
Ausgabe
Status
|- Number of jail:	1
`- Jail list:	sshd

And the details of the SSH jail:

Terminal
sudo fail2ban-client status sshd
Ausgabe
Status for the jail: sshd
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	0
|  `- Journal matches:	_SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:

The Journal matches line confirms that Fail2ban reads the systemd journal. Currently banned rises as soon as someone gets it wrong too often.

Step 5: Manage bans – and escalate them

Manually unban an IP (e.g. when a colleague mistyped):

Terminal
sudo fail2ban-client set sshd unbanip 203.0.113.45

Ban an IP immediately:

Terminal
sudo fail2ban-client set sshd banip 203.0.113.45

Against especially stubborn attackers, an escalating ban time pays off: whoever comes back is banned for longer. Add to the [DEFAULT] block:

INI
bantime.increment = true
bantime.maxtime = 1w

With that, Fail2ban doubles the ban time each time the same IP reoffends – up to a maximum of one week. After the change, sudo systemctl reload fail2ban.

When things go wrong

You locked yourself out. ignoreip was missing or contained the wrong IP. Connect via the console in the netcup SCP (independent of SSH) and unban yourself with sudo fail2ban-client set sshd unbanip YOUR_OWN_IP. Then enter your IP in ignoreip and reload. That’s why the whitelist comes first in step 2.

fail2ban.service won’t start (systemctl status shows “failed”). Almost always a typo in jail.local. Check the syntax with sudo fail2ban-client -t (test mode) – the command names the faulty line.

No one is ever banned, even though the log is full of failed attempts. Check with sudo fail2ban-client status sshd whether Total failed rises at all. If it stays at 0, the filter isn’t finding the entries – usually because an outdated guide set a logpath to a non-existent file. On Debian 13, remove the logpath from jail.local and use the journal (step 2).

Bans “don’t work” – the IP keeps connecting. Fail2ban writes its block rules into the same firewall (nftables/iptables) as UFW. Check with sudo nft list ruleset | grep f2b (or sudo iptables -L -n | grep f2b) whether the f2b chains exist. If they’re missing, the interplay with the firewall is stuck – restart the service and look at the logs.

Maintenance & backups

  • Keep an eye on bans: sudo fail2ban-client status sshd shows at any time how many IPs are currently banned. A look at the journal (journalctl -u fail2ban) shows the history.
  • More jails: as soon as services with their own login are added (e.g. a web app), you can activate matching jails – following the same pattern as [sshd].
  • Back up jail.local: your configuration is quickly restored but belongs in the backup of your server configuration.
  • Outlook CrowdSec: Fail2ban protects your host based on your logs. The modern successor CrowdSec later adds collaborative intrusion prevention (shared block lists) to this – we build it in a dedicated recipe once the reverse proxy is up. To get started, Fail2ban is exactly right.

With that, the security foundation is complete: key login, two firewall layers (UFW + netcup firewall), automatic updates and active brute-force protection. Your server is now not just set up, but solidly secured.

Last updated: Jul 19, 2026

What's next?

You might also like

Restic backups: encrypted and off-site
Security Intermediate

Restic backups: encrypted and off-site

Off-site backups with Restic: set up encrypted, restore snapshots, prune with retention and automate via a systemd …

· 11 min read
First steps with a netcup VPS
Basics Beginner

First steps with a netcup VPS

From a freshly ordered netcup server to a ready-to-use system: SSH login, system updates, a sudo user and the most …

· 4 min read