Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
pratique:informatique:parefeu:reaction [15/06/2026 07:43] – [Installation et lancement automatique] Zatalyzpratique:informatique:parefeu:reaction [16/06/2026 12:25] (Version actuelle) Zatalyz
Ligne 108: Ligne 108:
 </WRAP> </WRAP>
  
-<WRAP center round info 100%> 
 Avec la version 2 il y a un à présent un service systemd déjà fourni. Il se trouve sur /lib/systemd/system/reaction@.service. Avec la version 2 il y a un à présent un service systemd déjà fourni. Il se trouve sur /lib/systemd/system/reaction@.service.
- 
-Je laisse La vieille doc "pour mémoire" mais ce n'est plus forcément utile.  
-</WRAP> 
  
 Après installation et vérification, pour utiliser systemd : Après installation et vérification, pour utiliser systemd :
Ligne 123: Ligne 119:
  
 <WRAP center round alert 100%> <WRAP center round alert 100%>
 +<WRAP center round info 100%>
 +Je laisse la vieille doc "pour mémoire" ci-dessous mais ce n'est plus forcément utile. 
 +</WRAP>
 +
 Je vais créer deux services : un pour Reaction proprement dit, un pour avertir en cas de plantage. Vu que j'ai eu des plantages muets, je lui dis de se relancer si ça lui arrive((Je précise que ça date des premières versions du logiciel, qui a bien évolué depuis.)) et sinon, j'ai une alerte. Je vais créer deux services : un pour Reaction proprement dit, un pour avertir en cas de plantage. Vu que j'ai eu des plantages muets, je lui dis de se relancer si ça lui arrive((Je précise que ça date des premières versions du logiciel, qui a bien évolué depuis.)) et sinon, j'ai une alerte.
  
Ligne 189: Ligne 189:
  
  
-==== Envoyer un mail en cas de plantage ====+
  
  
Ligne 210: Ligne 210:
 === server.jsonnet === === server.jsonnet ===
 Ici c'est assez classique, le seul point important étant que je tourne avec nftables. Il peut être utile de spécifier les ip à ne pas bannir avec Reaction, couplé avec un fichier [[pratique:informatique:parefeu:nftables|nftables]] complet (entre autre sur la vérification des ip locales), ça évite de se bannir son propre routeur ou en tant que sysadmin.  Ici c'est assez classique, le seul point important étant que je tourne avec nftables. Il peut être utile de spécifier les ip à ne pas bannir avec Reaction, couplé avec un fichier [[pratique:informatique:parefeu:nftables|nftables]] complet (entre autre sur la vérification des ip locales), ça évite de se bannir son propre routeur ou en tant que sysadmin. 
 +
 +Sur un pare-feu, l'ordre des règles a une importance((Même si la façon dont ça s'applique est parfois complexe à comprendre.)), aussi j'ai préféré directement ajouter les bonnes instructions dans [[https://port.numenaute.org/zatalyz/zscript-sysadmin/src/branch/main/files/nftables/nftables.d|mes fichiers nftables]] : 
 +
 +<code bash nftables.conf_ou_autre>
 +set reaction_v4 {
 +    type ipv4_addr
 +    flags interval
 +}
 +set reaction_v6 {
 +    type ipv6_addr
 +    flags interval
 +}
 +chain input_all {
 + # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous.
 + type filter hook input priority 0; policy drop;
 +
 + # Vérifie si l'IP est bloquée (du plus long au plus court)
 + # ... Durablement 
 + ip saddr @blocklist_v4 drop
 + ip6 saddr @blocklist_v6 drop
 + # ... Par Reaction
 + ip saddr @reaction_v4 drop
 + ip6 saddr @reaction_v6 drop
 + # Ou dans la liste temporaire
 + ip saddr @tempblock_v4 drop
 + ip6 saddr @tempblock_v6 drop
 +# [...]
 +}
 +</code>
 +
 +De ce fait, je ne crée pas les sets à la volée au démarrage de Reaction (l'action ''start'' ne déclenche rien), et c'est déjà au bon endroit dans le bon tableau. 
 +
 +Les patterns des ip sont à présent dans le logiciel (depuis la version 2.0?) ce qui rend certaines déclarations plus rapides. Notons aussi l'apparition de la gestion des masques de sous-réseau. 
  
 <code json server.jsonnet> <code json server.jsonnet>
Ligne 215: Ligne 248:
   patterns: {   patterns: {
     ip: {     ip: {
-    // Both IPv4 and IPv6, do not accept malformed IPs +    // IPv4 et IPv6, et masque des ipv6. 
-      regex@'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|(?:(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))',+      type: 'ip', 
 +      ipv6mask64,
       ignore: [       ignore: [
 +        // Ne pas bannir les ip des sysadmins et sur le local
         // Ne pas oublier la virgule après chaque ip, pour l'énumération ;)         // Ne pas oublier la virgule après chaque ip, pour l'énumération ;)
         '127.0.0.1',         '127.0.0.1',
         '::1',         '::1',
         // Sous-réseau d'une box         // Sous-réseau d'une box
-        '192.168.1.0/24'+        '192.168.1.0/24',
         // Sous-réseau proxmox ?         // Sous-réseau proxmox ?
-        //'10.0.0.0/8' +        //'10.0.0.0/8', 
-        // Ip fixes de sysadmins +        // Ip fixes de sysadmins et/ou des bastions à ajouter. 
-        // ip de bastion+      ], 
 +    }, 
 +    ipmask: { 
 +      // Uniquement utilisé pour les filtres les plus aggressifs, risque de trop ban sinon ! 
 +      type: 'ip', 
 +      // ipv4 : 24 = tout le dernier bit, soit toute ip du type a.b.c.* (tout est dans le joker). 
 +      ipv4mask: 24,  
 +      // ipv6 : 48 = ban des datacenters. 56 est un peu moins excessif. 64 est une norme de particulier. 
 +      ipv6mask: 56, 
 +      ignore: [ 
 +        '127.0.0.1', 
 +        '::1', 
 +        '192.168.1.0/24', 
 +        '82.65.53.240', 
 +        '2a01:e0a:26f:e650:aaa1:59ff:fe82:5187',
       ],       ],
     },     },
   },   },
  
-  start: [ +// nftables est directement paramétré avec des tables/sets pour Reaction, histoire que ce soit au bon endroit dans la chaine.  
-    ['nft', ||| +  start: [], 
-    table inet reaction { +  // Je flush le set au stopquand même. Car Reaction les renvoie au redémarrage ; évite les doublons.
-      set ipv4bans { +
-        type ipv4_addr +
-        flags interval +
-        auto-merge +
-      } +
-      set ipv6bans { +
-        type ipv6_addr +
-        flags interval +
-        auto-merge +
-      } +
-      chain input { +
-        type filter hook input priority 0 +
-        policy accept +
-        ip saddr @ipv4bans drop +
-        ip6 saddr @ipv6bans drop +
-      } +
-    } +
-||| ], +
-  ],+
   stop: [   stop: [
-    ['nft', 'delete table inet reaction'],+    ['nft', 'flush', 'set', 'inet', 'firewall', 'reaction_v4'], 
 +    ['nft', 'flush', 'set', 'inet', 'firewall', 'reaction_v6'],
   ],   ],
 } }
Ligne 265: Ligne 296:
 On peut ainsi définir des actions par défaut : combien de temps on bannit, combien de lignes dans les logs avant de bannir, etc. 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.  On peut ainsi définir des actions par défaut : combien de temps on bannit, combien de lignes dans les logs avant de bannir, etc. 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. 
  
-Le fait que le fichier commence par "_" fait qu'il ne sera pas lu automatiquement au lancement de Reaction, il faudra l'appeler là où il est utile (dans les streams). Si on ne fais pas ça (s'il est noté "lib.jsonnet" par exemple), on aura l'erreur "ERROR While reading ssh.jsonnet in /etc/reaction: variable is not defined: filter_defaultlors de l'execution.+Le fait que le fichier commence par "_" fait qu'il ne sera pas lu automatiquement au lancement de Reaction, il faudra l'appeler là où il est utile (dans les streams). Si on ne fais pas ça (s'il est noté "lib.jsonnet" par exemple), on aura l'erreur ''ERROR While reading ssh.jsonnet in /etc/reaction: variable is not defined: filter_default'' lors de l'execution
 + 
 +Mon "banFor" a une subtilité : il attends qu'on déclare un temps (celui avant de débannir) ET une raison. Cette info peut être récupérée dans un log ou envoyé dans un mail, ou autre (cf le script plus bas). 
 + 
 +Je n'utilise pas les outils "nft" fournis avec Reaction, au final la commande de base Unix fonctionne bien pour mes besoins.
  
 <code json _lib.jsonnet> <code json _lib.jsonnet>
-local banFor(time) = { +local banFor(time, name) = { 
-  ban: { +    ban_v4: { 
-    cmd: ['nft46', 'add element inet reaction ipvXbans { <ip> }'], +        cmd: ['nft', 'add', 'element', 'inet', 'firewall', 'reaction_v4', '{ <ip> }'], 
-  }, +        ipv4only: true, 
-  unban: { +    }, 
-    cmd: ['nft46', 'delete element inet reaction ipvXbans { <ip> }'], +    ban_v6: { 
-    after: time, +        cmd: ['nft', 'add', 'element', 'inet', 'firewall', 'reaction_v6', '{ <ip> }'], 
-  },+        ipv6only: true, 
 +    }, 
 +    unban_v4: { 
 +        after: time, 
 +        cmd: ['nft', 'delete', 'element', 'inet', 'firewall', 'reaction_v4', '{ <ip> }']
 +        ipv4only: true
 +    }, 
 +    unban_v6: { 
 +        after: time, 
 +        cmd: ['nft', 'delete', 'element', 'inet', 'firewall', 'reaction_v6', '{ <ip> }'], 
 +        ipv6only: true, 
 +    }, 
 +    log: { 
 +        cmd: ['/etc/reaction/_ban.sh', '<ip>', name], 
 +        oneshot: true, 
 +    },
 }; };
  
 // retry et retryperiod sont quand il y a plusieurs tentatives autorisées // retry et retryperiod sont quand il y a plusieurs tentatives autorisées
-// juste mettre le banFor sinon...+// juste mettre le banFor sinon... Le ban sera alors à la première tentative.
  
 // Filtre (et options) par défaut : ni trop doux, ni trop cruel. // Filtre (et options) par défaut : ni trop doux, ni trop cruel.
 local filter_default = { local filter_default = {
   retry: 3,   retry: 3,
-  retryperiod: '3h', +  retryperiod: '1h', 
-  actions: banFor('48h'),+  actions: banFor('48h', 'ban par défaut'),
 }; };
  
-// Filtre doux : c'est peut-être légitime. Et peut-être pas.+// Filtre doux : c'est peut-être légitime. Et peut-être pas. Ça délaye les attaques.
 local filter_soft = { local filter_soft = {
   retry: 6,   retry: 6,
-  retryperiod: '3h', +  retryperiod: '1h', 
-  actions: banFor('10s'),+  actions: banFor('30s', 'ban temporaire'),
 }; };
  
 // Filtre violent : un seul essai, banni un mois. // Filtre violent : un seul essai, banni un mois.
 local filter_hard = { local filter_hard = {
-  actions: banFor('720h'),+  actions: banFor('720h', 'banni un mois'),
 }; };
  
-local stream_name(name) ={ 
-  reason: { 
-    cmd: ['logger', 'REACTION BLOCK <ip> because: ', name], 
-  }, 
-}; 
  
 // Exposer les définitions précédentes pour qu'elles soient accessibles depuis un autre fichier Jsonnet // Exposer les définitions précédentes pour qu'elles soient accessibles depuis un autre fichier Jsonnet
Ligne 312: Ligne 357:
   filter_soft: filter_soft,   filter_soft: filter_soft,
   filter_hard: filter_hard,   filter_hard: filter_hard,
-  stream_name: stream_name, 
 } }
 +
  
 </code> </code>
  
 +== Script bash de log, notif, etc ==
 +Un script très basique pour "loguer" les adresses bannis, avec la raison, appelé par l'action "banFor". Je compte me servir de ce genre de log pour alimenter par la suite :
 +  * les ips bloquées en longue durée (celles qui reviennent plusieurs fois via les filtres doux et par défaut : 6 fois c'est peut-être une erreur, 12 c'est de la maladresse, 24 c'est de l'acharnement...),
 +  * les ips en bloc (ipmask). Ce n'est pas du tout paramétré pour le moment !
 +Le format actuel de mon log n'est sans doute pas parfait pour ça, mais s'améliorera au fil des tests.
  
 +<code bash _ban.sh>
 +#!/bin/bash
 +# Envoi d'un mail ou notif ou ce qu'on veut
 +# Log des ip
 +echo "$1 banni car $2 // Date : $(date)" >> /var/log/reaction_ban.log
 +</code>
  
 === Streams === === Streams ===
-Je met ici une config très basique pour ssh (<wrap todo>Faudra que je mette le tout sur une forge, une fois fini...</wrap>), suffisante pour lister les "pièges" dans la syntaxe.+Je met ici une config très basique pour ssh (voir [[https://port.numenaute.org/zatalyz/zscript-sysadmin/src/branch/main/files/reaction|la forge]] pour plus de filtres), suffisante pour lister les "pièges" dans la syntaxe. 
 + 
 +<WRAP center round tip 100%> 
 +[[https://www.sshguard.net/|SSHguard]]((Empaqueté sur Debian)) est souvent plus adapté pour la protection de SSH, car il bannit sur des durées de plus en plus longues. Donc attention à ne pas gêner son fonctionnement avec Reaction. Ce qui n'empêche pas d'ajouter quelques pains bien violents à certains attaquants. Personnellement je n'ai aucune pitié avec ceux qui tentent de se connecter en root, et un banissement d'un mois est presque tendre ; je ne vois pas l'intérêt de les laisser essayer deux fois de suite. Aucun sysadmin suivant les bonnes pratiques ne pourrait faire l'erreur de tenter de se connecter en root.  
 +</WRAP>
  
 <code json ssh.jsonnet> <code json ssh.jsonnet>
Ligne 329: Ligne 389:
       cmd: ['journalctl', '-fn0', '-u', 'sshd.service'],       cmd: ['journalctl', '-fn0', '-u', 'sshd.service'],
       filters: {       filters: {
-        failedlogin: lib.filter_default + {+        badssh: lib.filter_default + 
 +          regex: [ 
 +            @'User root from <ip> not allowed because not listed in AllowUsers', 
 +          ], 
 +        // ce filtre est peu pertinent avec sshguard et va le ralentir dans sa lutte contre les méchants. 
 +        failedlogin: {
           regex: [           regex: [
             @'authentication failure;.*rhost=<ip>',             @'authentication failure;.*rhost=<ip>',
Ligne 337: Ligne 402:
           retry: 3,           retry: 3,
           retryperiod: '6h',           retryperiod: '6h',
-          actions: lib.banFor('48h'),+          actions: lib.banFor('48h', 'SSH: login échoué'),
         },         },
       },       },
Ligne 361: Ligne 426:
 [...] [...]
 </code> </code>
 +
 Ici ''lib.filter_default.actions'' précise qu'il faut appliquer les actions par défaut de "filter_default". ''+ lib.stream_name('apache_auth')'' permet d'ajouter l'action stream_name (qui permet de loguer pour "quoi" on a banni), en précisant une raison personnalisée donc. Il faut quand même déclarer ''lib.filter_default'' au niveau du stream (après "apache_auth" dans l'exemple), afin que les paramètres "retry" et "retryperiod" s'appliquent sur le stream.  Ici ''lib.filter_default.actions'' précise qu'il faut appliquer les actions par défaut de "filter_default". ''+ lib.stream_name('apache_auth')'' permet d'ajouter l'action stream_name (qui permet de loguer pour "quoi" on a banni), en précisant une raison personnalisée donc. Il faut quand même déclarer ''lib.filter_default'' au niveau du stream (après "apache_auth" dans l'exemple), afin que les paramètres "retry" et "retryperiod" s'appliquent sur le stream. 
 ==== Réaliser des actions plus compliqués ==== ==== Réaliser des actions plus compliqués ====
 +<WRAP center round tip 60%>
 +Ce qui suit est plus pour retrouver comment faire au besoin, mais la configuration précédente (log, sans mail en plus, intégré à banFor) me semble suffisante en général.
 +</WRAP>
 +
 Lorsqu'il y a bannissement via Reaction, j'aimerais pouvoir réaliser certaines actions, comme être avertie par mail.  Lorsqu'il y a bannissement via Reaction, j'aimerais pouvoir réaliser certaines actions, comme être avertie par mail. 
  
Ligne 454: Ligne 524:
 </code> </code>
  
-{{tag>fail2ban sysadmin iptable}}+===== Transformer les règles de fail2ban ===== 
 +Ça c'est du chantier... 
 + 
 +Quand on a fail2ban installé, retrouver les regex est un sacré bazar. Il n'y a pas de solution "immédiatement fonctionnelle". Mais deux commandes utiles. 
 + 
 +  fail2ban-client -d 
 +Celle-ci va lister toutes les règles actives, dans un format permettant de voir quel fichier de log est surveillé et divers détails. C'est assez verbeux, mais utile. 
 + 
 +  fail2ban-client get JAIL failregex 
 +Remplacer "JAIL" par le nom de la jail ; ne liste que les regex dans un format relativement lisible (enfin, ça reste des regex). On remarque cependant que la partie "<HOST>" n'est pas renseigné, c'est ballot hein ? Suivant les jail, cette variable qui capture l'ip de l'attaquant est soit dans un préfixe (à trouver...) soit sous un format décompressé.  
 + 
 +Jails que je tente d'analyser et recopier :  
 +  * Apache, error.log 
 +    * ''apache-auth'' : la plupart des règles semblent utiles. Pas forcément un ban trop violent au premier abord. 
 +    * ''apache-botsearch'' : c'est surtout le scan de pages à attaquer ; déjà mis dans mes filtres Reaction et aucune pitié avec ça, mais on note que là c'est la version pour "error" et non "access" donc pas les mêmes ? 
 +    * ''apache-modsecurity'' : faut que je creuse plus, ça semble relié à un mod apache que je ne gère pas. 
 +    * ''apache-nohome'' : alors, là, lui, je ne sais pas ce qu'il vise... 
 +    * ''apache-noscript'' : peu de règles, lisibles et très importantes car en effet les badbots les cherchent ! 
 +    * ''apache-overflows'' : à analyser plus finement, car sans doute qu'il y a des histoires de "retry" pour que ce soit pertinent. 
 +    * ''apache-shellshock'' : j'sais pô. 
 +  * Apache access.log 
 +    * ''apache-badbots'' : me semble assez douteuse. Ça ban d'après les users agent, mais ce qui est cherché est plein de vieux trucs. Après, ça peut éviter que les bots indexent trop, trop vite, ou de se faire aspirer le site. Mais j'aurais tendance à plutôt mettre des limiteurs de vitesse ? 
 +      * Notons cependant qu'on a des badbots repérables aux user-agents et que les ban peut réduire le trafic simplement. 
 +    * ''apache-fakegooglebot'' : celle-ci semble sacrément foireuse ? 
 + 
 +Autres services, où en théorie on va tout reprendre (plus les notres) : 
 + 
 +  * postfix 
 +  * dovecot 
 +  * sieve 
 +  * sshd 
 + 
 +{{tag>fail2ban sysadmin iptable nftables}}
  
 [[https://creativecommons.org/publicdomain/zero/1.0/deed.fr|{{ https://liev.re/imagesweb/licences/cc-zero.png?100 | Ce texte est placé sous licence CC0}}]] [[https://creativecommons.org/publicdomain/zero/1.0/deed.fr|{{ https://liev.re/imagesweb/licences/cc-zero.png?100 | Ce texte est placé sous licence CC0}}]]
  
  
pratique/informatique/parefeu/reaction.1781502181.txt.gz · Dernière modification : 15/06/2026 07:43 de Zatalyz