18
0
Fork 0
wiki/HowtoFail2Ban.md

841 lines
26 KiB
Markdown
Raw Permalink Normal View History

2017-05-20 18:24:23 +02:00
---
categories: web security
title: Howto Fail2Ban
...
* Documentation : <https://www.fail2ban.org/wiki/index.php/MANUAL_0_8>
* Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/show/fail2ban>
2016-12-29 11:25:39 +01:00
# Howto Fail2Ban
2017-05-24 14:42:52 +02:00
[Fail2Ban](https://www.fail2ban.org) est un outil pour limiter les attaques par brute force : il scanne en permanence des journaux pour détecter des anomalies répétitives et bannir les adresses IP coupables via [IPTables](HowtoIPTables). Nous l'utilisons souvent pour les erreurs d'authentification répétées sur des services publics comme SMTP, POP, IMAP ou FTP. On peut également être amené à l'utiliser pour SSH mais c'est plus rare car il est évidemment préférable de limiter directement l'accès via [IPTables](HowtoIPTables).
2017-05-20 18:24:23 +02:00
2016-12-29 11:25:39 +01:00
## Installation
~~~
2017-05-20 18:24:23 +02:00
# apt install fail2ban
2022-09-08 08:57:54 +02:00
# fail2ban-client -V
0.11.2
2016-12-29 11:25:39 +01:00
~~~
## Configuration
2017-05-20 18:24:23 +02:00
Fichiers de configuration :
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
~~~
/etc/fail2ban
├── fail2ban.conf
├── jail.conf
├── jail.local
├── jail.d
│ └── defaults-debian.conf
2017-05-20 18:24:23 +02:00
├── action.d
│ ├── apf.conf
│ ├── badips.conf
│ ├── blocklist_de.conf
│ […]
├── fail2ban.d
├── filter.d
│ ├── 3proxy.conf
│ ├── apache-auth.conf
│ ├── apache-badbots.conf
│ […]
├── paths-common.conf
├── paths-debian.conf
└── paths-opensuse.conf
2017-05-20 18:24:23 +02:00
~~~
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
Fail2Ban repose sur des règles de filtrage définies dans `/etc/fail2ban/filter.d/` et des actions dans `/etc/fail2ban/action.d/`.
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
On définit ensuite des **jails**, combinaisons d'une règle de filtrage et d'une ou plusieurs actions.
2016-12-29 11:25:39 +01:00
Voici la jail nommée _sshd_ (attention, en Debian 8 elle se nommait _ssh_) :
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
~~~{.ini}
[sshd]
2017-01-03 11:20:35 +01:00
enabled = true
port = ssh
filter = sshd
2017-01-03 11:20:35 +01:00
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 600
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
Cette jail va surveiller le fichier `/var/log/auth.log` via la règle de filtrage `/etc/fail2ban/filter.d/sshd.conf` :
s'il détecte la correspondance 5 fois en 10 minutes, il va utiliser l'action par défaut,
2017-05-20 18:24:23 +02:00
à savoir l'action `/etc/fail2ban/action.d/iptables-multiport.conf` qui va ajouter une règle _iptables_ pour bannir le port concerné pendant 10 minutes.
2016-12-29 11:25:39 +01:00
**Attention, cette jail _sshd_ est activée par défaut à l'installation via le fichier `jail.d/defaults-debian.conf`**
2017-05-20 18:24:23 +02:00
Les paramètres par défaut sont :
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
~~~{.ini}
maxretry = 5
2017-05-20 18:24:23 +02:00
findtime = 600
banaction = iptables-multiport
bantime = 600
ignoreip = 127.0.0.1/8
~~~
> *Note* : en Debian 8, le paramètre par défaut de *maxretry* est `maxretry = 3`
Les paramètres par défaut et un certain nombre de jails (non activées à part _sshd_) sont définies dans `/etc/fail2ban/jail.conf`,
si l'on veut ajouter ou modifier des paramètres ou des jails, il faut utiliser le fichier `/etc/fail2ban/jail.local` ou des fichiers `/etc/fail2ban/jail.d/*.conf`
2017-05-20 18:24:23 +02:00
Pour dumper la configuration courante :
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
# fail2ban-client -d
['set', 'loglevel', 3]
['set', 'logtarget', '/var/log/fail2ban.log']
[...]
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
2016-12-29 11:25:39 +01:00
## Administration
2017-05-20 18:24:23 +02:00
Fail2Ban est un démon en Python, on peut s'assurer qu'il tourne bien sur un système :
~~~
$ ps auwx | grep fail2ban
root 24173 0.00.2 185048 12176 ? Sl 16:16 0:03 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid
~~~
On peut lister les jails actives :
2016-12-29 11:25:39 +01:00
~~~
# fail2ban-client status
2017-05-20 18:24:23 +02:00
Status
|- Number of jail: 1
`- Jail list: ssh
~~~
Et l'on doit les retrouver au niveau d'iptables :
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
# iptables -L -n
~~~
### fail2ban-client
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
De nombreuses commandes sont possibles avec `fail2ban-client` pour lister des informations ou modifier des paramètres.
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
Pour lister l'état de la jail _ssh_ :
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
# fail2ban-client status ssh
Status for the jail: ssh
|- filter
| |- File list: /var/log/auth.log
| |- Currently failed: 0
| `- Total failed: 6
`- action
|- Currently banned: 1
| `- IP list: 192.0.2.42
`- Total banned: 1
2016-12-29 11:25:39 +01:00
~~~
2017-05-23 20:13:42 +02:00
Pour dé-bannir l'adresse IP 192.0.2.42 de la jail _ssh_ :
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
~~~
# fail2ban-client set ssh unbanip 192.0.2.42
~~~
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
Pour lister les informations de la jail _ssh_ :
~~~
# fail2ban-client get ssh maxretry
6
# fail2ban-client get ssh findtime
600
# fail2ban-client get ssh bantime
600
# fail2ban-client get ssh ignoreip
These IP addresses/networks are ignored:
`- 127.0.0.1/8
# fail2ban-client get ssh addaction
iptables-multiport
# fail2ban-client get ssh failregex
The following regular expression are defined:
[...]
~~~
2016-12-29 11:25:39 +01:00
On pourra mettre à jour les paramètres d'une jail à chaud avec `set`. Ça évite un couteux redémarrage de Fail2ban.
~~~
# fail2ban-client set ssh bantime 300
~~~
## Ajouter ses propres jails
2016-12-29 11:25:39 +01:00
On peut bien sûr ajouter ses propres _jails_ en ajoutant dans le fichier `jail.local`, un exemple :
2017-05-20 18:24:23 +02:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
[custom-1234]
enabled = true
port = http,https
filter = accesslog-custom-1234
logpath = /var/log/access.log
maxretry = 5
findtime = 180
bantime = 86400
ignoreip = 127.0.0.1/8 192.0.2.42
2017-07-04 23:32:03 +02:00
action = iptables-multiport
sendmail[dest=jdoe@example.com]
~~~~
> *Attention* : en cas d'action liée à iptables (ce qui est le défaut), le nom de la jail ne doit pas excéder 20 caractères !
### Règles de filtrage
Les règles de filtrage sont définies dans `/etc/fail2ban/filter.d/` :
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
3proxy.conf apache-noscript.conf couriersmtp.conf exim.conf lighttpd-auth.conf openwebmail.conf proftpd.conf selinux-ssh.conf squid.conf webmin-auth.conf
apache-auth.conf apache-overflows.conf cyrus-imap.conf exim-spam.conf mysqld-auth.conf pam-generic.conf pure-ftpd.conf sendmail-auth.conf sshd.conf wuftpd.conf
apache-badbots.conf assp.conf dovecot.conf freeswitch.conf nagios.conf perdition.conf qmail.conf sendmail-reject.conf sshd-ddos.conf xinetd-fail.conf
apache-common.conf asterisk.conf dropbear.conf groupoffice.conf named-refused.conf php-url-fopen.conf recidive.conf sieve.conf suhosin.conf
apache-modsecurity.conf common.conf ejabberd-auth.conf gssftpd.conf nginx-http-auth.conf postfix.conf roundcube-auth.conf sogo-auth.conf uwimap-auth.conf
apache-nohome.conf courierlogin.conf exim-common.conf horde.conf nsd.conf postfix-sasl.conf selinux-common.conf solid-pop3d.conf vsftpd.conf
2016-12-29 11:25:39 +01:00
~~~
On peut écrire ses propres règles de filtrage en s'appuyant sur [les expressions régulières Python](https://docs.python.org/3/library/re.html) pour détecter la variable _<HOST>_.
2017-05-20 18:24:23 +02:00
Exemple d'une règle :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2017-05-20 18:24:23 +02:00
[Definition]
failregex = warning: \[<HOST>\]: authentication failed:
ignoreregex =
~~~
Pour tester une règle :
~~~
$ fail2ban-regex auth.log /etc/fail2ban/filter.d/evolix-test.conf
~~~
Afin d'obtenir des informations supplémentaires - dans le cas où on cherche les heures de connexion d'une adresse IP particulière - on peut utiliser les options `-v` et/ou `--print-all-matched`.
On peut aussi tester avec une date :
2017-05-20 18:24:23 +02:00
~~~
$ fail2ban-regex '2017-05-20 10:10:10 foo' 'warning: \[<HOST>\]: authentication failed:'
[...]
Failregex: 0 total
[...]
$ fail2ban-regex '2017-05-20 10:10:10 [192.0.2.42]: authentication failed:' '\[<HOST>\]: authentication failed:'
[...]
Failregex: 1 total
|- #) [# of hits] regular expression
| 1) [1] \[<HOST>\]: authentication failed:
[...]
~~~
2018-03-22 16:19:20 +01:00
### Actions
2017-05-31 00:33:39 +02:00
Les actions sont définies dans `/etc/fail2ban/action.d/` :
2017-05-31 00:33:39 +02:00
~~~
apf.conf firewallcmd-ipset.conf iptables.conf iptables-xt_recent-echo.conf osx-ipfw.conf sendmail-whois-lines.conf
badips.conf firewallcmd-new.conf iptables-ipset-proto4.conf mail-buffered.conf pf.conf shorewall.conf
blocklist_de.conf hostsdeny.conf iptables-ipset-proto6-allports.conf mail.conf route.conf ufw.conf
bsd-ipfw.conf ipfilter.conf iptables-ipset-proto6.conf mail-whois.conf sendmail-buffered.conf
complain.conf ipfw.conf iptables-multiport.conf mail-whois-lines.conf sendmail-common.conf
dshield.conf iptables-allports.conf iptables-multiport-log.conf mynetwatchman.conf sendmail.conf
dummy.conf iptables-blocktype.conf iptables-new.conf osx-afctl.conf sendmail-whois.conf
~~~
Si l'on ne précise pas d'action, l'action sera par défaut _iptables-multiport_ (définie dans `jail.conf`) :
2017-05-31 00:33:39 +02:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
2017-05-31 00:33:39 +02:00
banaction = iptables-multiport
~~~
Exemple pour bannir et déclencher l'envoi d'un email :
2017-06-07 15:38:04 +02:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
2017-07-04 23:32:03 +02:00
action = iptables-multiport
sendmail[dest=jdoe@example.com]
2017-05-31 00:33:39 +02:00
~~~
2017-05-20 18:24:23 +02:00
## Exemples
2020-08-14 04:34:31 +02:00
### SSH invalid user
Le but de cette règle est de bannir immédiatement si une connexion SSH a lieu sur un utilisateur invalide. Très efficace contre les robots qui font des bruteforce massivement distribués.
On ajoute la règle `filter.d/sshd-invaliduser.conf` :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 04:34:31 +02:00
[INCLUDES]
before = common.conf
[Definition]
_daemon = sshd
failregex = ^%(__prefix_line)s[iI](?:llegal|nvalid) user .*? from <HOST>(?: port \d+)?\s*$
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd
~~~
> **Note** : Par fois la regex ne matche pas, on pourra mettre une regex moins rigide :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 04:34:31 +02:00
failregex = (I|i)nvalid user \S+ from <HOST> .*$
~~~
puis on définit une jail ainsi :
~~~{.ini}
[sshd-invaliduser]
enabled = true
maxretry = 1
port = ssh,2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s
~~~
2020-08-14 04:35:54 +02:00
> **Note** : Il est conseillé de mettre dans la configuration SSH `UseDNS no`.
2017-05-20 18:24:23 +02:00
### Dovecot
2022-09-15 09:37:32 +02:00
On ajoute la règle `filter.d/dovecot-evolix.conf` :
2016-12-29 11:25:39 +01:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
2022-09-14 18:10:40 +02:00
[Definition]
2022-09-15 09:37:32 +02:00
failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=<HOST>,.*
2017-01-03 11:20:35 +01:00
ignoreregex =
2016-12-29 11:25:39 +01:00
~~~
2017-05-20 18:24:23 +02:00
puis on définit une jail ainsi :
~~~{.ini}
2022-09-15 09:37:32 +02:00
[dovecot-evolix]
2017-05-20 18:24:23 +02:00
enabled = true
2022-09-15 09:37:32 +02:00
filter = dovecot-evolix
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
2017-05-20 18:24:23 +02:00
logpath = /var/log/mail.log
~~~
2020-08-14 04:34:31 +02:00
### Courier
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
On utilise la règle _courierlogin_ prédéfinie pour la jail :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[courierauth]
enabled = true
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = courierlogin
logpath = /var/log/mail.log
~~~
2020-08-14 04:34:31 +02:00
### Postfix SASL
2016-12-29 11:25:39 +01:00
2017-05-20 18:24:23 +02:00
La règle SASL ne convient pas, il faut la modifier via une nouvelle règle `filter.d/evolix-sasl.conf` :
~~~
[Definition]
failregex = (?i): warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:
ignoreregex =
~~~
puis l'on définit une jail ainsi :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[sasl]
enabled = true
2017-05-20 18:24:23 +02:00
port = smtp,ssmtp,submissions,imap2,imap3,imaps,pop3,pop3s
filter = evolix-sasl
2016-12-29 11:25:39 +01:00
logpath = /var/log/mail.log
~~~
2020-08-14 04:34:31 +02:00
### Apache / Nginx
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
Grâce aux journaux *access_log* générés par Apache / Nginx, on peut utiliser Fail2Ban comme protection sur certaines URLs ou l'ensemble des requêtes.
Cela peut être des règles activées en permanence ou des règles spécifiques pour répondre à une attaque DOS ou « brute force » en cours.
Voici un exemple avec un filtre `/etc/fail2ban/filter.d/dos-http.conf` qui va contrôler l'ensemble des requêtes avec la méthode HTTP GET :
2016-12-29 11:25:39 +01:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
2017-05-23 19:01:01 +02:00
[Definition]
2020-06-19 05:39:41 +02:00
failregex = <HOST> -.*"GET.*HTTP.*
2016-12-29 11:25:39 +01:00
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/dos-http.conf` :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2017-05-23 19:01:01 +02:00
[dos-http]
2016-12-29 11:25:39 +01:00
enabled = true
2017-05-20 16:27:32 +02:00
port = http,https
2017-05-23 19:01:01 +02:00
filter = dos-http
logpath = access.log
2016-12-29 11:25:39 +01:00
maxretry = 300
findtime = 300
~~~
2024-02-19 11:25:07 +01:00
ATTENTION, cet exemple ne doit absolument pas être mis en place pour un cas général, cela va faire dysfonctionner la plupart des sites qui ont souvent plein d'éléments statiques (CSS, JS, images, etc.).
2020-08-14 10:24:11 +02:00
### 401
/etc/fail2ban/filter.d/nginx-401.conf :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:24:11 +02:00
[Definition]
failregex = <HOST> -.*"GET.*HTTP.* 401 .*
~~~
Jail :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:24:11 +02:00
[nginx-401-allvhosts]
enabled = true
port = http,https
filter = nginx-401
logpath = /home/*/log/access.log tail
maxretry = 30
findtime = 3600
~~~
### 403
/etc/fail2ban/filter.d/nginx-403.conf :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:24:11 +02:00
[Definition]
failregex = <HOST> -.*"GET.*HTTP.* 403 .*
~~~
Jail :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:24:11 +02:00
[nginx-403-allvhosts]
enabled = true
port = http,https
filter = nginx-403
logpath = /home/*/log/access.log tail
maxretry = 30
findtime = 3600
~~~
2017-05-23 19:05:39 +02:00
## webapps
2016-12-29 11:25:39 +01:00
2017-05-23 19:05:39 +02:00
### Wordpress sans plugin
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
L'option la plus simple pour utiliser Fail2Ban avec Wordpress consiste à détecter un trop grand nombre de tentatives de login dans les journaux *access_log*.
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
On ajoute un filtre dans `/etc/fail2ban/filter.d/apache-wp.conf` :
2016-12-29 11:25:39 +01:00
2020-08-14 10:27:30 +02:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[Definition]
failregex = <HOST> -.*"POST.*/wp-login.php HTTP.* 200
<HOST> -.*"POST.*/xmlrpc.php.*
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/apache-wp.conf` :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[apache-wp]
enabled = true
2017-05-20 16:27:32 +02:00
port = http,https
2016-12-29 11:25:39 +01:00
filter = apache-wp
logpath = /var/log/apache2/access.log
2017-05-23 19:01:01 +02:00
maxretry = 10
findtime = 300
2016-12-29 11:25:39 +01:00
~~~
2017-05-23 20:13:42 +02:00
Cette méthode a le défaut de ne pas distinguer les tentatives réussies et échouées, car la page d'authentification ne renvoie pas d'erreur HTTP particulière ([Une proposition à cet effet a été faite, à suivre](https://core.trac.wordpress.org/ticket/25446)). Pour utiliser une méthode plus avancée (permettant notamment d'avoir un _maxretry_ plus strict) voir ci-dessous.
2016-12-29 11:25:39 +01:00
2017-05-23 19:05:39 +02:00
### Wordpress avec plugin simple
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
Une deuxième option est d'utiliser un plugin Wordpress pour envoyer une erreur HTTP 401 en cas d'erreur d'authentification. Cette méthode est plus fine mais nécessite de toucher à l'installation Wordpress : il faut installer le plugin dans [wp-content/mu-plugins](https://codex.wordpress.org/Must_Use_Plugins), un dossier spécial qui ne sera pas vu à travers l'interface d'administration web. Il suffit de créer `wp-content/mu-plugins/401-on-login-fail.php` :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.php}
2016-12-29 11:25:39 +01:00
<?php
function my_login_failed_401() {
status_header( 401 );
}
add_action( 'wp_login_failed', 'my_login_failed_401' );
~~~
2017-05-23 19:01:01 +02:00
On ajoute ensuite un filtre dans `/etc/fail2ban/filter.d/apache-wp.conf`:
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[Definition]
failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 401
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/apache-wp.conf` :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[apache-wp]
enabled = true
2017-05-20 16:27:32 +02:00
port = http,https
2016-12-29 11:25:39 +01:00
filter = apache-wp
logpath = /var/log/apache2/access.log
/home/user/log/access.log
maxretry = 5
2017-05-23 19:01:01 +02:00
findtime = 300
2016-12-29 11:25:39 +01:00
~~~
2017-05-23 19:05:39 +02:00
### Wordpress avec plugin Fail2Ban
2016-12-29 11:25:39 +01:00
2017-05-23 20:13:42 +02:00
La dernière solution utilise le [plugin Wordpress fail2ban](https://wordpress.org/plugins/wp-fail2ban/) pour enregistrer les authentifications dans un fichier de log. Elle nécessite l'installation et la mise à jour régulière du plugin.
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
Le plugin est disponible sur <https://wordpress.org/plugins/wp-fail2ban/>.
2016-12-29 11:25:39 +01:00
On ajoute ensuite deux filtres dans `/etc/fail2ban/filter.d/wordpress-hard.conf` et `/etc/fail2ban/filter.d/wordpress-soft.conf` :
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
~~~
2016-12-29 11:25:39 +01:00
# Fail2Ban configuration file hard
#
# Author: Charles Lecklider
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = (?:wordpress|wp)
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = ^%(__prefix_line)sAuthentication attempt for unknown user .* from <HOST>( via XML-RPC)?$
^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>( via XML-RPC)?$
^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
^%(__prefix_line)sPingback error .* generated from <HOST>$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
~~~
2017-01-03 11:20:35 +01:00
2017-05-23 19:01:01 +02:00
~~~
2016-12-29 11:25:39 +01:00
# Fail2Ban configuration file soft
#
# Author: Charles Lecklider
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = (?:wordpress|wp)
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
^%(__prefix_line)sXML-RPC authentication failure from <HOST>$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
~~~
2017-05-23 19:01:01 +02:00
puis on définit deux jails du type :
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[wordpress-hard]
2017-05-23 19:01:01 +02:00
enabled = true
port = http,https
filter = wordpress-hard
logpath = /var/log/auth.log
maxretry = 1
findtime = 300
2016-12-29 11:25:39 +01:00
[wordpress-soft]
2017-05-23 19:01:01 +02:00
enabled = true
port = http,https
filter = wordpress-soft
logpath = /var/log/auth.log
maxretry = 5
findtime = 300
2016-12-29 11:25:39 +01:00
~~~
2017-05-23 19:05:39 +02:00
### ownCloud
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
Pour faire fonctionner ownCloud avec Fail2Ban, il faut tout d'abord modifier le fichier `config.php` pour enregistrer les informations d'authentification :
2016-12-29 11:25:39 +01:00
~~~
'loglevel' => '2',
'log_authfailip' => true,
2017-05-23 19:01:01 +02:00
'logfile' => 'owncloud.log',
2016-12-29 11:25:39 +01:00
~~~
2017-05-23 19:01:01 +02:00
On ajoute un filtre dans `/etc/fail2ban/filter.d/owncloud.conf` :
2016-12-29 11:25:39 +01:00
~~~
[Definition]
failregex={"app":"core","message":"Login failed: user '.*' , wrong password, IP:<HOST>","level":2,"time":".*"}
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/owncloud.conf`:
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[owncloud]
2017-05-23 19:01:01 +02:00
enabled = true
port = http,https
filter = owncloud
logpath = owncloud.log
maxrety = 5
findtime = 300
2016-12-29 11:25:39 +01:00
~~~
### Joomla via les logs apache
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
On va simplement détecter un trop grand nombre de tentatives de login dans les journaux *access_log*.
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
On ajoute un filtre dans `/etc/fail2ban/filter.d/apache-joomla.conf` :
~~~
2016-12-29 11:25:39 +01:00
[Definition]
2018-07-23 11:45:50 +02:00
failregex = <HOST> -.*"POST.*/administrator/index.php HTTP
2016-12-29 11:25:39 +01:00
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/apache-joomla.conf`:
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[apache-joomla]
2017-05-23 19:01:01 +02:00
enabled = true
port = http,https
filter = apache-joomla
logpath = /var/log/apache2/access.log
maxretry = 10
findtime = 300
2016-12-29 11:25:39 +01:00
~~~
### Joomla via le log applicatif
On peut aussi utiliser les logs applicatifs de joomla et notamment, son log/error.php qui contient les erreurs de connexions.
Note: Ce log semble suivre la langue par défaut de l'installation. Il faut donc adapter ces regex
~~~
# Fail2Ban configuration file for joomla
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*INFO\s<HOST>\sjoomlafailure\sLe nom d\'utilisateur ne correspond pas au mot de passe, ou vous n\'avez pas encore de compte.$
ignoreregex =
~~~
puis, pour l'activer :
~~~
[joomla-monsite]
enabled = true
port = http,https
filter = joomla
logpath = /home/monsite/www/log/error.php
maxretry = 10
~~~
2017-05-23 19:05:39 +02:00
### Prestashop
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
On va simplement détecter un trop grand nombre de tentatives de login dans les journaux *access_log*.
2016-12-29 11:25:39 +01:00
2017-05-23 19:01:01 +02:00
On ajoute un filtre dans `/etc/fail2ban/filter.d/apache-prestashop.conf` :
~~~
2016-12-29 11:25:39 +01:00
[Definition]
failregex = <HOST> -.*"POST.*/login.*
~~~
2023-10-25 11:34:55 +02:00
puis on définit une jail du type `/etc/fail2ban/jail.d/apache-prestashop.conf`:
2016-12-29 11:25:39 +01:00
2017-01-03 11:20:35 +01:00
~~~{.ini}
2016-12-29 11:25:39 +01:00
[apache-prestashop]
2017-05-23 19:01:01 +02:00
enabled = true
port = http,https
filter = apache-prestashop
logpath = /var/log/apache2/access.log
maxretry = 10
findtime = 300
2017-01-03 11:20:35 +01:00
~~~
2017-05-20 18:24:23 +02:00
2020-08-14 10:20:21 +02:00
### pm2 / nodejs
/etc/fail2ban/filter.d/pm2-auth-failure.conf :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:20:21 +02:00
[Definition]
failregex = .*Auth failure, WRONG_HASH for IP <HOST> .*
[Init]
datepattern = ^%%Y-%%m-%%d %%H:%%M
~~~
Définition de la jail :
2020-08-14 10:27:30 +02:00
~~~{.ini}
2020-08-14 10:20:21 +02:00
[pm2-auth-failure]
enabled = true
port = http,https
filter = pm2-auth-failure
logpath = /home/APPPATH/.pm2/logs/api-error.log tail
maxretry = 30
findtime = 3600
~~~
2020-11-19 12:03:06 +01:00
### haproxy-badbots
Inspiré du filtre de Debian apache-badbots.
/etc/fail2ban/filter.d/haproxy-badbots.conf :
~~~{.ini}
[Definition]
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|ezooms.bot|BLEXBot|MJ12bot|AhrefsBot|Yandex|EvilRobot|360Spider|Yeti|Baiduspider
badbots = Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots&#44; \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
failregex = ^.* <HOST>:\d{1,5} .*\{.*\|.*(?:%(badbots)s|%(badbotscustom)s).*\}.*$
ignoreregex =
~~~
Définition de la jail :
~~~{.ini}
[haproxy-badbots]
enabled = true
port = http,https
filter = haproxy-badbots
logpath = /var/log/haproxy.log
maxretry = 10
bantime = 300
~~~
2017-07-22 12:39:54 +02:00
## Munin
Pour activer les plugins Munin pour Fail2Ban :
~~~
# cd /etc/munin/plugins
# ln -s /usr/share/munin/plugins/fail2ban
~~~
2017-05-20 18:24:23 +02:00
## FAQ
### Fail2Ban supporte l'IPv6 ?
2019-10-24 11:19:27 +02:00
Le support de l'IPv6 est arrivé dans la version 0.10. Dans Debian, cette version est disponible qu'à partir de la version 10 (Buster) (et aussi dans les backports pour la version 9 (Stretch)
2017-05-20 18:24:23 +02:00
### Attaque via un utilisateur
Un utilisateur local peut générer des logs vers _syslog_ (par exemple avec la commande **logger**), il faut donc bien avoir en tête
que toute jail s'appuyant sur des logs _syslog_ (comme `/var/log/auth.log`) pourra être activée par un utilisateur logué en SSH ou via PHP, CGI, etc.
2017-05-24 22:01:25 +02:00
### Comment mettre en liste blanche certaines adresses IP ?
Pour mettre en whitelist certaines adresses IP, il faut utiliser le paramètre _ignoreip_ qui peut s'utiliser globalement (section [DEFAULT]) ou au sein de chaque jail :
~~~
ignoreip = 127.0.0.1/8 192.0.2.42
~~~
2019-05-31 15:24:04 +02:00
Ou à chaud :
~~~
# fail2ban-client set sshd addignoreip 31.170.8.69
~~~
2018-04-17 11:07:29 +02:00
### Comment bannir une ip manuellement ?
~~~
fail2ban-client set JAIL banip IP
~~~
2022-02-22 10:25:03 +01:00
### Erreur "fail2ban.actions.action: ERROR" avec jail au nom trop long
Si le nom de votre jail dépasse 20 caractères, vous obtiendrez des erreurs du type :
~~~
fail2ban.actions.action: ERROR iptables -N fail2ban-accesslog-custom-12345
fail2ban.actions.action: ERROR iptables -n -L INPUT | grep -q fail2ban-accesslog-custom-12345 returned 100
~~~
la raison est que Fail2Ban utilise le nom de la jail pour ajouter une chaîne IPTables et elle ne doit pas dépasser une certaine longueur :
~~~
22:52 < reg> iptables v1.4.14: chain name `fail2ban-accesslog-custom-12345' too long (must be under 29 chars)
~~~
2022-02-22 10:25:03 +01:00
### Taille de la base de données SQLite et durée de conservation des bans
[Un bug](https://github.com/fail2ban/fail2ban/issues/1267#issuecomment-323336619) affecte les versions antérieures à 0.11 (Debian Bullseye) dont la base `/var/lib/fail2ban/fail2ban.sqlite3` n'est pas purgée.
2022-03-03 15:44:31 +01:00
Le contournement est de mettre en place un cron `/etc/cron.daily/fail2ban_dbpurge` :
2022-02-22 10:25:03 +01:00
~~~
#!/bin/sh
sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 ".timeout 5000; DELETE FROM bans WHERE datetime('now', '-86400 second') > datetime(timeofban, 'unixepoch'); VACUUM;"
2022-02-22 10:25:03 +01:00
~~~
Notons que la commande `VACUUM` va copier la base en supprimant les espaces inutilisés dans la nouvelle base.
Par défaut, la durée maximale est définie par l'option `bantime` dont l'unité est à la seconde :
~~~
grep -R -E "bantime[[:blank:]]*=[[:blank:]]*[0-9]+" /etc/fail2ban/
~~~
2022-02-22 11:01:12 +01:00
Le défaut de cette solution est qu'il ne permet plus les bans illimités (`bantime = -1`), car ceux-ci seront supprimés par le cron.
2022-02-22 10:25:03 +01:00
Si la base de données est volumineuse parce qu'elle n'a jamais été purgée, la requête `DELETE` échouera.
2022-03-03 15:44:31 +01:00
Pour libérer de l'espace, il faut faire des `DELETE` successifs à la main (qui peuvent prendre un certain temps) :
2022-02-22 10:25:03 +01:00
~~~
# sqlite3 /var/lib/fail2ban/fail2ban.sqlite3
sqlite > .timeout 5000;
2022-03-03 15:44:31 +01:00
sqlite > DELETE FROM bans WHERE date('now', '-1000 day') > datetime(timeofban, 'unixepoch');
sqlite > DELETE FROM bans WHERE date('now', '-500 day') > datetime(timeofban, 'unixepoch');
(...)
sqlite > DELETE FROM bans WHERE date('now', '-14 day') > datetime(timeofban, 'unixepoch');
sqlite > DELETE FROM bans WHERE date('now', '-$days day') > datetime(timeofban, 'unixepoch');
2022-02-22 10:25:03 +01:00
sqlite > VACUUM;
~~~