Outils pour utilisateurs

Outils du site


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
140-pare-feu-fail2ban:20-config-sshd [le 30/06/2025 à 16:01] – [Une configuration possible] prof140-pare-feu-fail2ban:20-config-sshd [le 05/07/2025 à 14:25] (Version actuelle) – [fail2ban a-t-il de la mémoire ?] prof
Ligne 123: Ligne 123:
 </code> </code>
 Nous pouvons désormais supprimer le fichier ''defaults-debian.conf''. Nous pouvons désormais supprimer le fichier ''defaults-debian.conf''.
 +==== Tests ====
 +Pour rappel, le filtre installé au démarrage du serveur de test est le suivant:
 +<code>table inet filter {
 + chain input_ipv4 {
 + icmp type echo-request limit rate 5/second burst 5 packets accept
 + }
 +
 + chain input_ipv6 {
 + icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
 + icmpv6 type echo-request limit rate 5/second burst 5 packets accept
 + }
 +
 + chain input {
 + type filter hook input priority filter; policy drop;
 + iifname "lo" accept
 + ct state vmap { invalid : drop, established : accept, related : accept }
 + meta protocol vmap { ip : jump input_ipv4, ip6 : jump input_ipv6 }
 + tcp dport { 22, 80, 443 } accept
 + }
 +}
 +</code>
 +Un attaquant, lui aussi virtuel, dont la configuration IP est la suivante:
 +      inet 192.168.60.76/24 brd 192.168.60.255 scope global dynamic
 +      inet6 2a01:e0a:875:b1d0:f80d:77c3:5e30:243a/64 scope global dynamic
 +Va essayer (maladroitement) de forcer ssh sur le serveur de test.
 +
 +Nous observons pendant ce temps les logs au fil de l'eau, tel que les voit fail2ban:
 +
 +<html><pre class="code">
 +<b>journalctl _SYSTEMD_UNIT=ssh.service + _COMM=sshd -f</b>
 +
 +<span class="hly">juin 30 18:19:13 trixie-nft sshd-session[1040]: Invalid user admin from 2a01:e0a:875:b1d0:5054:ff:fefe:c099 port 55938
 +juin 30 18:19:18 trixie-nft sshd-session[1040]: pam_unix(sshd:auth): check pass; user unknown
 +juin 30 18:19:18 trixie-nft sshd-session[1040]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=2a01:e0a:875:b1d0:5054:ff:fefe:c099
 +juin 30 18:19:20 trixie-nft sshd-session[1040]: Failed password for invalid user admin from 2a01:e0a:875:b1d0:5054:ff:fefe:c099 port 55938 ssh2</span>
 +<span class="hlo">juin 30 18:21:01 trixie-nft sshd-session[1065]: Invalid user admin from 192.168.60.76 port 45056
 +juin 30 18:21:09 trixie-nft sshd-session[1065]: pam_unix(sshd:auth): check pass; user unknown
 +juin 30 18:21:09 trixie-nft sshd-session[1065]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.60.76
 +juin 30 18:21:11 trixie-nft sshd-session[1065]: Failed password for invalid user admin from 192.168.60.76 port 45056 ssh2</span>
 +<span class="hlg">juin 30 18:21:13 trixie-nft sshd[750]: Timeout before authentication for connection from 2a01:e0a:875:b1d0:5054:ff:fefe:c099 to 2a01:e0a:875:b1d0:5054:ff:fe79:7d6f, pid = 1040
 +juin 30 18:23:01 trixie-nft sshd[750]: Timeout before authentication for connection from 192.168.60.76 to 192.168.60.5, pid = 1065</span>
 +</pre></html>
 +L'attaquant, ce bourrin, s'est fait planter avec son adresse IPv6, mail il a insisté avec son adresse IPv4, ce qui a produit le même résultat.
 +
 +Sur le serveur, la configuration «nftables» a été dynamiquement mise à jour par fail2ban. Nous pouvons observer le résultat:
 +
 +<html><pre class="code">
 +<b>nft list ruleset</b>
 +
 +table inet filter {
 + chain input_ipv4 {
 + icmp type echo-request limit rate 5/second burst 5 packets accept
 + }
 +
 + chain input_ipv6 {
 + icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
 + icmpv6 type echo-request limit rate 5/second burst 5 packets accept
 + }
 +
 + chain input {
 + type filter hook input priority filter; policy drop;
 + iifname "lo" accept
 + ct state vmap { invalid : drop, established : accept, related : accept }
 + meta protocol vmap { ip : jump input_ipv4, ip6 : jump input_ipv6 }
 + tcp dport { 22, 80, 443 } accept
 + }
 +}
 +<span class="hly">table inet f2b-table {
 + set addr6-set-sshd {
 + type ipv6_addr
 + elements = { 2a01:e0a:875:b1d0:5054:ff:fefe:c099 }
 + }
 +
 + set addr-set-sshd {
 + type ipv4_addr
 + elements = { 192.168.60.76 }
 + }
 +
 + chain f2b-chain {
 + type filter hook input priority filter - 1; policy accept;
 + tcp dport 22 ip6 saddr @addr6-set-sshd reject with icmpv6 port-unreachable
 + tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
 + }
 +}</span>
 +</pre></html>
 +
 +Fail2ban a créé une nouvelle table : «table inet f2b-table»
 +Dans cette table, il a créé:
 +  * deux «sets»:
 +    * **set addr6-set-sshd** destiné à collectionner les adresses IPv6 à bloquer;
 +    * **set addr-set-sshd** la même chose, mais pour les adresses IPv4.
 +  * une chaîne «chain f2b-chain» qui par défaut accepte tout sauf:
 +    * les adresses IPv6 collectées qui n'ont plus accès au port 22,
 +    * la même chose, mais pour les adresses IPv4.
 +Du bon vieux temps d'IPtables, fail2ban aurait créé une chaîne «f2b-ssh» dans laquelle il aurait ajouté une règle de blocage complète pour chaque adresse repérée, dans le style:
 +<code>
 +-A f2b-ssh -s 80.240.252.168/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 157.254.54.192/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 8.222.168.120/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 65.108.211.181/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 154.209.4.36/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 157.10.252.119/32 -j REJECT --reject-with icmp-port-unreachable
 +-A f2b-ssh -s 14.103.114.20/32 -j REJECT --reject-with icmp-port-unreachable
 +....
 +</code>
 +Et le même procédure pour les adresses IPv6. Si les «sets» existaient déjà avec iptables, fail2ban ne les utilisait pas (l'exemple est pris sur une Debian 11 mise à jour en Debian 12).
 +
 +La technique exposée avec fail2ban et nftables sur la trixie donne un résultat bien plus concis.
 +
 +Et du temps nécessaire à la rédaction de ces lignes, les 5 minutes de bannissement sont passées, et désormais:
 +<html><pre class="code">
 +<b>nft list table inet f2b-table</b>
 +
 +table inet f2b-table {
 +<span class="bhly"> set addr6-set-sshd {
 + type ipv6_addr
 + }
 +
 + set addr-set-sshd {
 + type ipv4_addr
 + }</span>
 +
 + chain f2b-chain {
 + type filter hook input priority filter - 1; policy accept;
 + tcp dport 22 ip6 saddr @addr6-set-sshd reject with icmpv6 port-unreachable
 + tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
 + }
 +}
 +</pre></html>
 +Si la structure ajoutée par fail2ban est toujours intacte, les sets ont quant-à-eux été purgés.
 +
 +==== Aménagement du filtre ====
 +Certains filtres, dont ''sshd.conf'', proposent des modes de fonctionnement. Ces modes agissent sur le choix des expressions régulières utilisées pour le filtrage.
 +
 +Des explications, plus ou moins sibyllines, peuvent se trouver dans le fichier de filtre lui-même. Pour ''sshd.conf'', nous trouvons:
 +<html><pre class="code">
 +<span class="txtb"># Parameter "mode": normal (default), ddos, extra or aggressive (combines all)
 +# Usage example (for jail.local):
 +#   [sshd]
 +#   mode = extra
 +#   # or another jail (rewrite filter parameters of jail):
 +#   [sshd-aggressive]
 +#   filter = sshd[mode=aggressive]
 +#</span>
 +<span class="hly">mode = normal</span>
 +</pre></html>
 +Hélas, la maîtrise de ces modes suppose non seulement celle des expressions régulières, mais également celle des [[https://fail2ban.readthedocs.io/en/latest/filters.html|règles de création des filtres]]. Si le mode «ddos» peut laisser supposer qu'il s'intéresse essentiellement aux attaques par déni de service distribuées, le mode «extra» est plus obscur.
 +
 +Le mode «normal» sélectionné par défaut est généralement satisfaisant.
 +===== Analyse plus profonde =====
 +
 +
 +
 +==== fail2ban a-t-il de la mémoire ? ====
 +Nous allons considérablement rallonger la durée de bannissement, pour vérifier ce qu'il se passerait pour les adresses bannies en cas de redémarrage de l'hôte:
 +  findtime = 10minutes
 +  bantime = 1hour
 +Le fait de changer la configuration oblige à la faire relire par fail2ban. La commande «fail2ban-client» permet de le faire de façon élégante:
 +<html>pre class="code">
 +<b>fail2ban reload sshd</b>
 +
 +OK
 +</pre></html>
 +(«OK» étant le signe que la commande a bien été prise en compte).
 +
 +
 +Le même pirate va re-tenter sa chance, va se faire de nouveau coincer. Nous retrouvons son adresse dans le «set» idoine:
 +<code>
 +table inet f2b-table {
 + set addr6-set-sshd {
 + type ipv6_addr
 + elements = { 2a01:e0a:875:b1d0:f80d:77c3:5e30:243a }
 + }
 +
 + chain f2b-chain {
 + type filter hook input priority filter - 1; policy accept;
 + tcp dport 22 ip6 saddr @addr6-set-sshd reject with icmpv6 port-unreachable
 + }
 +}
 +</code>
 +Reboot de la machine et contrôle de l'état du pare-feu. Nous retrouvons bien le bannissement:
 +<html><pre class="code">
 +<b>nft list table inet f2b-table</b>
 +
 +table inet f2b-table {
 + set addr6-set-sshd {
 + type ipv6_addr
 + elements = { 2a01:e0a:875:b1d0:f80d:77c3:5e30:243a }
 + }
 +
 + chain f2b-chain {
 + type filter hook input priority filter - 1; policy accept;
 + tcp dport 22 ip6 saddr @addr6-set-sshd reject with icmpv6 port-unreachable
 + }
 +}
 +</pre></html>
 +
 +fail2ban a bonne mémoire.
 +
 +Dans la foulée, nous pouvons également vérifier qu'une commande comme:
 +  systemctl restart fail2ban
 +n'efface pas pour autant sa mémoire.
 +==== L'outil «fail2ban-client» ====
 +Cet outil sert essentiellement à contrôler le fonctionnement du serveur fail2ban. Le manuel fournit (en anglais) tous les détails de son utilisation.
 +Voici quelques-uns de ses usages:
 +  * **fail2ban-client ping** permet de savoir si le serveur est vivant. S'il l'est, il répond simplement: «pong»,
 +  * **fail2ban-client status** retourne l'état du serveur. exemple:\\ <code>Status
 +|- Number of jail: 1
 +`- Jail list: ssh</code>
 +  * **fail2ban-client start/stop/reload <JAIL>** permet de démarrer, arrêter, recharger la configuration d'une prison,
 +  * **fail2ban-client get <JAIL> banned** retourne la liste des adresses IP bannies dans la prison indiquée. Exemple: \\  <code>['1.202.223.2', '101.126.14.37', '101.126.151.131', '101.126.81.188', '101.126.88.203', '101.126.89.164', '101.126.91.34', '101.36.108.134', '101.36.122.23', '101.36.231.231', '102.140.97.134', '102.210.80.6', '102.215.218.114', '103.106.194.74', '103.112.54.86', '103.113.105.228', '103.116.177.252', '103.117.56.152', '103.120.227.88', '103.123.227.244', '103.137.194.125', '103.139.192.247']</code>Notons que le résultat est sous la forme d'un tableau python (fail2ban est écrit en python).
 +  * **fail2ban-client unban <IP> ... <IP>** Permet de sortir une liste d'adresses IP de prison, quelle que soit sa prison.
 +  * etc.
  
Surveillance de sshd: Dernière modification le: 30/06/2025 à 16:01 par prof