# fail2ban: SSH Jail Configuration

LLMS index: [llms.txt](/en/llms.txt)

---

Securing SSH against brute-force attacks is one of the first steps in hardening any server. fail2ban scans logs, detects repeated failed login attempts, and blocks the source via iptables or nftables. This note covers the sshd jail — from installation to fine-tuning ban durations.

## Installation and Basic Configuration

Install from the standard repository:

```bash
# Debian/Ubuntu
apt install fail2ban

# RHEL/CentOS
yum install fail2ban
```

Enable and start the service:

```bash
systemctl enable --now fail2ban
systemctl status fail2ban
```

> [!WARNING]
> Do not edit `/etc/fail2ban/jail.conf` directly — package updates will overwrite your changes. All local overrides go in `jail.local`.

Create a local overrides file:

```bash
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
```

Or, preferably, create a minimal `jail.local` with only the parameters you need — fail2ban stacks `jail.local` on top of `jail.conf`, so overriding specific keys is sufficient.

## Filter for sshd

A ready-made filter ships with the package: `/etc/fail2ban/filter.d/sshd.conf`. It scans `/var/log/auth.log` (or `/var/log/secure` on RHEL) for patterns like `Failed password for invalid user` and `Connection closed by authenticating user`.

Verify the filter parses your logs correctly:

```bash
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
```

If the output shows a high match rate, the filter works. If not, check the `logpath` parameter in the jail and the `logpath` value inside the `[Definition]` section of the filter.

> [!TIP]
> For additional protection against brute-force via ddos-style attacks, there is a separate filter `sshd-ddos`. It catches rapid repeated connections from a single IP. Enable it by adding `mode = ddos` to the jail parameters.

## bantime and findtime Parameters

Three keys define the blocking logic:

| Parameter | Description | Default |
|-----------|-------------|---------|
| `bantime` | Ban duration in seconds (negative = permanent) | 600 |
| `findtime` | Observation window for counting failed attempts | 600 |
| `maxretry` | Failed attempts before ban | 5 |

A typical production configuration:

```ini
[sshd]
bantime  = 3600
findtime = 600
maxretry = 3
```

This means: three failed logins within ten minutes triggers a one-hour ban. For critical servers, set `bantime = -1` (permanent ban) and unblock manually with `fail2ban-client set sshd unbanip <IP>`.

> [!NOTE]
> `bantime` and `findtime` accept suffixes: `d` (days), `h` (hours), `m` (minutes), `s` (seconds). For example, `bantime = 1d`.

## Activating the Jail

By default, the `[sshd]` section is commented out in `jail.local`. Enable it:

```ini
[sshd]
enabled = true
port    = ssh
filter  = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime  = 3600
findtime = 600
```

On RHEL/CentOS, `logpath` is typically `/var/log/secure`. Verify the log path on your distribution.

Restart fail2ban and check the status:

```bash
systemctl restart fail2ban
fail2ban-client status
fail2ban-client status sshd
```

The output of `fail2ban-client status sshd` shows the current number of banned IPs and active filters.

Manual block and unblock:

```bash
fail2ban-client set sshd banip 203.0.113.50
fail2ban-client set sshd unbanip 203.0.113.50
```

> [!WARNING]
> fail2ban is not a WAF and not a replacement for key-based authentication. Use keys instead of passwords, restrict access with `AllowUsers`, and change the port where feasible. fail2ban complements these measures — it does not replace them.

Check fail2ban logs (`/var/log/fail2ban.log`) on first startup — they show whether the jail picked up the log file and whether filters are firing.
