# Filter

[![fail2ban_2.png](https://docs.rakouns.bzh/uploads/images/gallery/2026-06/scaled-1680-/fail2ban-2.png)](https://docs.rakouns.bzh/uploads/images/gallery/2026-06/fail2ban-2.png)

## <span style="color: windowtext;">Principe</span>

Un filter est un fichier <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">.conf</span> dans <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">/etc/fail2ban/filter.d/</span> qui contient une (ou plusieurs) expression(s) régulière(s) capable(s) de repérer, dans une ligne de log, une tentative échouée, et d'en extraire l'adresse IP via le groupe nommé <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">&lt;HOST&gt;</span>.

Structure minimale :

```
[Definition]
failregex = <ta regex avec <HOST>>
ignoreregex =
```

<span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">&lt;HOST&gt;</span> est une macro fail2ban qui correspond à une regex IPv4/IPv6 déjà prête à l'emploi — pas besoin de l'écrire toi-même.

## <span style="color: windowtext;">Méthode générale pour écrire un filter</span>

<span style="mso-list: Ignore;">1.<span style="font: 7.0pt 'Times New Roman';"> </span></span>**Identifier une ligne de log représentative** d'un échec d'authentification.

<span style="mso-list: Ignore;">2.<span style="font: 7.0pt 'Times New Roman';"> </span></span>**Repérer ce qui varie** (timestamp, IP, user) vs ce qui est fixe (le message d'erreur).

<span style="mso-list: Ignore;">3.<span style="font: 7.0pt 'Times New Roman';"> </span></span>**Écrire la regex**, en remplaçant l'IP par <span style="font-size: 10.5pt; line-height: 115%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">&lt;HOST&gt;</span> et en échappant les caractères spéciaux (<span style="font-size: 10.5pt; line-height: 115%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">.</span>, <span style="font-size: 10.5pt; line-height: 115%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">\[</span>, <span style="font-size: 10.5pt; line-height: 115%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">\]</span>, etc.).

<span style="mso-list: Ignore;">4.<span style="font: 7.0pt 'Times New Roman';"> </span></span>**Tester** avec <span style="font-size: 10.5pt; line-height: 115%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">fail2ban-regex</span> avant de créer la jail.

## <span style="color: windowtext;">Exemple générique : filter SSH (fourni par défaut, pour référence)</span>

<span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">/etc/fail2ban/filter.d/sshd.conf</span> (déjà présent, à ne pas modifier) repère une ligne du type :

```
Jun 20 10:15:32 host sshd[1234]: Failed password for invalid user admin from 203.0.113.42 port 51234 ssh2
```

avec une regex de la forme :

```
failregex = ^%(__prefix_line)sFailed \S+ for .* from <HOST>(?: port \d+)?(?: ssh2)?\s*$
```

## <span style="color: windowtext;">Fil rouge : filter Vaultwarden</span>

Vaultwarden journalise les échecs de connexion via Docker (stdout → <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">json-file</span>). Une ligne typique ressemble à :

```
[2026-06-20 10:15:32.123][vaultwarden::api::identity][WARN] Username or password is incorrect. Try again. IP: 203.0.113.42. Username: user@example.com.
```

Créer <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">/etc/fail2ban/filter.d/rakouns-vaultwarden.conf</span> :

```
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\..*$
            ^.*Username or password is incorrect\. IP: <HOST>\..*$
ignoreregex =
datepattern = ^\[%%Y-%%m-%%d %%H:%%M:%%S
```

<p class="callout info">**<span style="font-size: 10.5pt; line-height: 115%; color: black; mso-color-alt: windowtext;">Note — </span>**<span style="font-size: 10.5pt; line-height: 115%; color: black; mso-color-alt: windowtext;">Plusieurs lignes dans failregex (une par ligne) sont évaluées en OU logique — utile quand le message d'erreur varie légèrement selon la version du service.</span></p>

## <span style="color: windowtext;">Tester un filter avant de créer la jail</span>

**Toujours** valider un filter sur un vrai log (ou un extrait) avant de l'attacher à une jail, pour éviter de générer un faux sentiment de sécurité avec un filter qui ne matche jamais — ou pire, qui matche trop large.

### <span style="color: windowtext;">Test sur un fichier de log classique</span>

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

### <span style="color: windowtext;">Test sur les logs Docker (cas Vaultwarden)</span>

Les logs Docker ne sont pas dans un fichier classique par défaut, il faut soit extraire un échantillon, soit pointer directement sur le fichier json-file du conteneur :

```
# Trouver le chemin du log JSON du conteneur
docker inspect --format='{{.LogPath}}' vaultwarden
 
# Tester le filter contre ce fichier
sudo fail2ban-regex /var/lib/docker/containers/<container_id>/<container_id>-json.log /etc/fail2ban/filter.d/rakouns-vaultwarden.conf
```

### <span style="color: windowtext;">Lecture du résultat</span>

fail2ban-regex affiche un résumé du type :

```
Results
=======
 
Failregex: 3 total
|-  #) [# of hits] regular expression
|   1) [3] ^.*Username or password is incorrect\. Try again\. IP: <HOST>\..*$
`-
 
Ignoreregex: 0 total
 
Lines: 150 lines, 0 ignored, 3 matched, 147 missed
```

<span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">3 matched</span> confirme que le filter fonctionne. Si tu obtiens <span style="font-size: 10.5pt; line-height: 120%; font-family: Consolas; color: black; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">0 matched</span> alors que tu sais qu'il y a des échecs dans le log, retravaille la regex (espace en trop, caractère spécial non échappé, format de date différent, etc.).