Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
pratique:informatique:parefeu:reaction [30/05/2024 08:22] – supprimée - modification externe (Unknown date) 127.0.0.1 | pratique:informatique:parefeu:reaction [04/02/2025 10:13] (Version actuelle) – [Commandes de base] Zatalyz | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ====== Reaction, alternative à Fail2ban ====== | ||
+ | [[https:// | ||
+ | * Consomme moins | ||
+ | * Plus facile à customiser | ||
+ | * Carrément plus simple de faire des regex | ||
+ | |||
+ | Et autres qualités que l' | ||
+ | |||
+ | Faudra que je participe au wiki officiel mais en attendant je met mes idées en place ici. | ||
+ | |||
+ | <WRAP center round tip 60%> | ||
+ | J' | ||
+ | </ | ||
+ | |||
+ | ===== Installation et lancement automatique ===== | ||
+ | Pour l' | ||
+ | |||
+ | < | ||
+ | wget https:// | ||
+ | | ||
+ | minisign -VP RWSpLTPfbvllNqRrXUgZzM7mFjLUA7PQioAItz80ag8uU4A2wtoT2DzX -m reaction_1.4.1-1_amd64.deb && | ||
+ | rm reaction_1.4.1-1_amd64.deb.minisig && | ||
+ | sudo apt install ./ | ||
+ | </ | ||
+ | | ||
+ | Ensuite on crée un fichier de config, on le modifie, et aussi un truc pour systemd. | ||
+ | sudo mkdir / | ||
+ | sudo nano / | ||
+ | (voir plus bas la/les confs). | ||
+ | |||
+ | sudo nano / | ||
+ | |||
+ | < | ||
+ | [Install] | ||
+ | WantedBy=multi-user.target | ||
+ | [Service] | ||
+ | ExecStart=/ | ||
+ | StateDirectory=reaction | ||
+ | RuntimeDirectory=reaction | ||
+ | WorkingDirectory=/ | ||
+ | Restart=on-failure | ||
+ | RestartSec=3 | ||
+ | </ | ||
+ | |||
+ | Vu que j'ai eu des plantages muets, je lui dis de se relancer si ça lui arrive. | ||
+ | |||
+ | Et puis on y lance : | ||
+ | < | ||
+ | sudo service reaction start</ | ||
+ | |||
+ | <WRAP center round tip 60%> | ||
+ | Mais avant de démarrer le service, c'est pas mal de tester sa configuration en lançant seulement la ligne de démarrage dans le terminal, ce qui casse à la première erreur : | ||
+ | sudo reaction start -c / | ||
+ | </ | ||
+ | |||
+ | ===== Commandes de base ===== | ||
+ | Voir qui est banni : | ||
+ | reaction show | ||
+ | |||
+ | Débannir quelqu' | ||
+ | reaction flush IP | ||
+ | |||
+ | Consulter l'aide : | ||
+ | reaction --help | ||
+ | |||
+ | |||
+ | Par défaut les bases de données sont dans ''/ | ||
+ | ===== Envoyer des mails quand il y a une action ===== | ||
+ | J'ai une commande qui va envoyer un mail via un script, en ayant en paramètre deux variables : '' | ||
+ | < | ||
+ | mail: { | ||
+ | cmd: [' | ||
+ | }, | ||
+ | }; | ||
+ | |||
+ | </ | ||
+ | |||
+ | Le script : | ||
+ | < | ||
+ | # Envoyer un mail | ||
+ | dossiermail="/ | ||
+ | titremail=" | ||
+ | # Création du fichier du corps du mail dans un fichier temporaire qui évite toute collision | ||
+ | corpmail=" | ||
+ | listeip="/ | ||
+ | |||
+ | # Vérifier si l' | ||
+ | if grep -q $1 $listeip; then | ||
+ | exit | ||
+ | else | ||
+ | # Message pour le corps du mail | ||
+ | echo " | ||
+ | # Ajouter les logs pour les détails | ||
+ | journalctl --since yesterday | grep $1 >> $corpmail | ||
+ | #Envoyer le mail | ||
+ | cat $corpmail | mail -s " | ||
+ | # Effacer le corps du crime pour éviter d' | ||
+ | rm $corpmail | ||
+ | fi</ | ||
+ | |||
+ | Penser évidement à créer les dossiers ''/ | ||
+ | |||
+ | Plus loin dans le fichier de configuration de Reaction, dans les streams, comment dire qu'il faut envoyer un mail (exemple sur ssh) : | ||
+ | < | ||
+ | ssh: { | ||
+ | cmd: [' | ||
+ | filters: { | ||
+ | failedlogin: | ||
+ | regex: [ | ||
+ | @' | ||
+ | @' | ||
+ | @' | ||
+ | ], | ||
+ | retry: 6, | ||
+ | retryperiod: | ||
+ | actions: banFor(' | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | </ | ||
+ | |||
+ | ===== Actions par défaut ===== | ||
+ | On peut créer des actions par défaut qu'on appelle ensuite ; cela permet par exemple de définir pour tout le monde la même durée de bannissement et de la changer à un seul endroit si besoin. | ||
+ | |||
+ | Ce n'est pas forcément pertinent pour tout, par exemple je préfère préciser la raison du bannissement pour savoir quels services se font attaquer. | ||
+ | |||
+ | On déclare la commande : | ||
+ | < | ||
+ | local filter_default = { | ||
+ | retry: 3, | ||
+ | retryperiod: | ||
+ | actions: banFor(' | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | Et dans les streams, on l' | ||
+ | < | ||
+ | { | ||
+ | streams: { | ||
+ | ssh: { | ||
+ | filters: { | ||
+ | failedlogin: | ||
+ | regex: [' | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | } | ||
+ | </ | ||
+ | ===== Découper la configuration ===== | ||
+ | On peut tout mettre dans un seul fichier, moi j'aime bien séparer pour m'y retrouver. Faut avouer que je prévois max de regex à un moment, et max de services couverts aussi. | ||
+ | |||
+ | |||
+ | |||
+ | Dans le fichier principal, on peut appeler un autre fichier avec cette syntaxe : | ||
+ | < | ||
+ | streams: { | ||
+ | ssh: import ' | ||
+ | }, | ||
+ | }</ | ||
+ | |||
+ | et '' | ||
+ | |||
+ | <WRAP center round todo 60%> | ||
+ | Mais j'ai du manquer un bout, ça me fait des erreurs ça... Il ne reconnait pas le " | ||
+ | </ | ||
+ | |||
+ | ===== Mes bouts de stream et de config ===== | ||
+ | Fichier principal | ||
+ | <code jsonnet server.jsonnet> | ||
+ | // This file is using JSONNET, a complete configuration language based on JSON // See https:// | ||
+ | // action pour bannir/ | ||
+ | local banFor(time) = { | ||
+ | ban: { | ||
+ | cmd: [' | ||
+ | }, | ||
+ | unban: { | ||
+ | after: time, | ||
+ | cmd: [' | ||
+ | }, | ||
+ | }; | ||
+ | |||
+ | // Envoyer un mail lors des actions et précisant ip et raison | ||
+ | local sendmail(ip, | ||
+ | mail: { | ||
+ | cmd: [' | ||
+ | }, | ||
+ | }; | ||
+ | |||
+ | // pourquoi ça ouvre ici ? Mais, ça marche. | ||
+ | { | ||
+ | // patterns are substitued in regexes. when a filter performs an action, it replaces the found pattern. | ||
+ | // reaction regex syntax is defined here: https:// | ||
+ | // jsonnet' | ||
+ | patterns: { | ||
+ | // IPs can be IPv4 or IPv6 | ||
+ | // ip46tables (C program also in this repo) handles running the good commands | ||
+ | ip: { | ||
+ | regex: @' | ||
+ | ignore: [' | ||
+ | }, | ||
+ | }, | ||
+ | |||
+ | // Commandes exécutées au lancement | ||
+ | start: [ | ||
+ | [' | ||
+ | [' | ||
+ | [' | ||
+ | ], | ||
+ | // Commandes exécutées à l' | ||
+ | stop: [ | ||
+ | [' | ||
+ | [' | ||
+ | [' | ||
+ | [' | ||
+ | ], | ||
+ | |||
+ | // Streams : c'est là qu'on va définir les services et règles menant au bannissement | ||
+ | streams: { | ||
+ | ssh: import ' | ||
+ | kernel: import ' | ||
+ | badguypostfix: | ||
+ | }, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Pour ssh et kernel, il s'agit des configurations par défaut auxquelles j'ai ajouté mon envoi de mail : | ||
+ | <code jsonnet ssh.jsonnet> | ||
+ | { | ||
+ | cmd: [' | ||
+ | filters: { | ||
+ | failedlogin: | ||
+ | regex: [ | ||
+ | @' | ||
+ | @' | ||
+ | @' | ||
+ | ], | ||
+ | retry: 6, | ||
+ | retryperiod: | ||
+ | actions: banFor(' | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | |||
+ | </ | ||
+ | |||
+ | <code jsonnet kernel.jsonnet> | ||
+ | // Ban hosts which knock on closed ports. | ||
+ | // It needs this iptables chain to be used to drop packets: | ||
+ | // ip46tables -N log-refuse | ||
+ | // ip46tables -A log-refuse -p tcp --syn -j LOG --log-level info --log-prefix ' | ||
+ | // ip46tables -A log-refuse -m pkttype ! --pkt-type unicast -j nixos-fw-refuse | ||
+ | // ip46tables -A log-refuse -j DROP | ||
+ | { | ||
+ | cmd: [' | ||
+ | filters: { | ||
+ | portscan: { | ||
+ | regex: [' | ||
+ | retry: 4, | ||
+ | retryperiod: | ||
+ | actions: banFor(' | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | Pour postfix, pour le moment je cible certains bot cons. | ||
+ | <code jsonnet badguypostfix.jsonnet> | ||
+ | { | ||
+ | cmd: [' | ||
+ | filters: { | ||
+ | badguy: { | ||
+ | regex: [ | ||
+ | @'^.* improper command pipelining after CONNECT from unknown\[< | ||
+ | @' | ||
+ | @'^.* NOQUEUE: reject: RCPT from unknown\[< | ||
+ | @' | ||
+ | @' | ||
+ | ], | ||
+ | retry: 1, | ||
+ | retryperiod: | ||
+ | actions: banFor(' | ||
+ | }, | ||
+ | }, | ||
+ | }, | ||
+ | </ | ||
+ | |||
+ | {{tag> | ||
+ | |||
+ | [[https:// | ||
+ | |||