URL: https://linuxfr.org/news/reaction-remplacant-de-fail2ban Title: reaction, remplaçant de fail2ban Authors: ppom Arkem et Benoît Sibaud Date: 2023-11-25T13:31:40+01:00 License: CC By-SA Tags: fail2ban, sécurité, programme, logiciel et annonce Score: 4 L'honorable fail2ban semble utilisé sur de très nombreuses petites infrastructures. NdM: _Fail2ban est un framework de prévention contre les intrusions, écrit en Python_ (Wikipédia), ou dit autrement à bloquer et bannir des pénibles. Il est diffusé sous GPLv2+. Il était installé sur mes serveurs, avant que j'essaie de le remplacer. > Mais dis-moi, pourquoi remplacer fail2ban ? - Parce que fail2ban est lent - Parce que sa configuration est très désagréable et mal documentée. > Mais dis-moi, il doit bien exister une alternative ? Avant de me lancer yeux fermés dans l'implémentation d'une alternative, j'ai fait le tour du propriétaire libre : - *sshguard* est uniquement adapté à SSH. - *crowdsec* semble chouette, mais adapté à des grosses infras et à des workflows compliqués. De plus, je n'ai pas réussi à l'installer. - *salt* est plus un WAF (*Web Application Firewall*). Pareil, semble chouette mais adapté à des grosses infrastructures. - *minos*, développé par Exarius (un des CHATONS), efficace mais ne supporte que les logs stockés dans des fichiers texte et le pare-feu nftables. - *pyruse*, que je découvre aujourd'hui sur LinuxFr.org avec l'étiquette [fail2ban](https://linuxfr.org/tags/fail2ban/public). Uniquement adapté à *systemd*/*journald*. Cri de joie, de toutes les alternatives que j'ai trouvé, fail2ban semble être encore le mieux adapté ! ---- [Article de présentation sur mon blog](https://blog.ppom.me/fr-reaction) [Presentation article on my blog](https://blog.ppom.me/en-reaction) [Git](https://framagit.org/ppom/reaction) [📽️ Action... Réaction !](https://u.ppom.me/reaction.webm) [Annonce Fediverse](https://mamot.fr/@ppom/111319697102347990) ---- Après 6 mois de développement à temps très partiel, je suis fièr·e de vous présenter mon petit bébé : *reaction*. NdM: écrit en Go et C, placé sous AGPLv3. > Action... Réaction ! L'article sur mon blog présente le logiciel en détail, alors je vous fais un résumé que j'espère convaincant : - À charge de travail égale, reaction consomme 30x moins de CPU et 10x moins de RAM. - Il est codé en Go, ce qui est pour ce cas d'usage un bon équilibre entre facilité de développement et efficacité. - La configuration est possible en JSON, YAML ou JSONnet. - JSONnet est un langage étendant JSON, permettant d'écrire des commentaires, de définir des variables, des fonctions... Je l'aime beaucoup. C'est un peu comme le langage *Nix* de NixOS, mais avec une syntaxe agréable. - Protéger un service, c'est seulement 8 lignes de configuration environ ! - Contrairement à fail2ban, reaction ne vient pas avec ses 160 fichiers de configuration par défaut (soit 8900 lignes de TOML bizarre). - Au lieu de ça, il y a un wiki centralisant des bonnes pratiques, des expressions rationnelles (_regex_), des exemples, une FAQ. ## Aperçu de la configuration Je vous présente le coeur du fichier de configuration, en utilisant cette fois le YAML. En remplacement des *jails* de fail2ban, on a des *streams*, qui définissent une source de données (par exemple `tail -f /var/log/nginx/access.log` pour nginx). ```yaml streams: ssh: cmd: ['journalctl', '-fu', 'sshd.service'] ``` À ces *streams*, on attache un ou plusieurs *filters*. Ce sont des groupes d'expressions régulières. C'est aussi sur un *filter* qu'on décide du nombre de mauvais essais (`retry`) qu'on accorde à une IP avant de *réagir*. ```yaml streams: ssh: cmd: ['journalctl', '-fu', 'sshd.service'] filters: fail: regex: - 'authentication failure;.*rhost=' retry: 3 retryperiod: '3h' ``` À un *filter*, on rajoute une ou plusieurs *actions*, qui seront exécutées quand il se déclenche. ```yaml streams: ssh: cmd: ['journalctl', '-fu', 'sshd.service'] filters: fail: regex: - 'authentication failure;.*rhost=' retry: 3 retryperiod: '3h' actions: ban: cmd: ['iptables', '-w', '-A', 'reaction', '-s', '', '-j', 'DROP'] ``` Elles peuvent être effectuées tout de suite, ou être délayées avec `after`, ce qui permet de bannir une IP maintenant, et de la débannir quelque temps plus tard. ```yaml streams: ssh: cmd: ['journalctl', '-fu', 'sshd.service'] filters: fail: regex: - 'authentication failure;.*rhost=' retry: 3 retryperiod: '3h' actions: ban: cmd: ['iptables', '-w', '-A', 'reaction', '-s', '', '-j', 'DROP'] unban: cmd: ['iptables', '-w', '-D', 'reaction', '-s', '', '-j', 'DROP'] after: '24h' ``` Je recommande toutefois d'utiliser JSONnet, qui permettra d'éviter les répétitions, ici en définissant un ensemble d'actions `banFor` : ```jsonnet local banFor(time) = { ban: { cmd: ['iptables', '-w', '-A', 'reaction', '-s', '', '-j', 'DROP'], }, unban: { after: time, cmd: ['iptables', '-w', '-D', 'reaction', '-s', '', '-j', 'DROP'], }, }; { streams: { ssh: { cmd: ['journalctl', '-f', '-u', 'sshd.service'], filters: { login: { regex: [ @'authentication failure;.*rhost=' ], retry: 3, retryperiod: '3h', actions: banFor('24h'), }, }, }, }, } ``` ## Version 2 Et pour vous vendre quelque chose qui n'est pas encore fait : La v2 sera capable de fonctionner en grappe, en échangeant en pair-à-pair des adresses IP à bannir (ou des recettes de cuisine, configurez-le comme vous voulez !) Une bibliothèque Go couvre exactement mes cas d'usage : elle a été écrite pour Nomad, une alternative à Kubernetes. J'ai donc confiance en l'arrivée de cette v2. Mais avant de m'y atteler, j'essaie de faire connaitre un maximum *reaction*, pour avoir des retours le plus tôt possible.