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 | ||
| 140-pare-feu-fail2ban:20-config-sshd [le 30/06/2025 à 15:54] – [Une configuration possible] prof | 140-pare-feu-fail2ban:20-config-sshd [le 05/07/2025 à 14:25] (Version actuelle) – [fail2ban a-t-il de la mémoire ?] prof | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| ====== Surveillance de sshd ====== | ====== Surveillance de sshd ====== | ||
| ===== Dans les journaux ===== | ===== Dans les journaux ===== | ||
| - | Nous avons vu que : | + | Nous allons voir que le filtre proposé par défaut pour sshd est le suivant: |
| // | // | ||
| Ligne 43: | Ligne 43: | ||
| 31 tentatives en 16 heures. La configuration de fail2ban est telle que des adresses repérées deux fois en moins de 600 secondes sont bannies 1 mois. Il n'est donc pas paranoïaque de protéger sévèrement sshd. | 31 tentatives en 16 heures. La configuration de fail2ban est telle que des adresses repérées deux fois en moins de 600 secondes sont bannies 1 mois. Il n'est donc pas paranoïaque de protéger sévèrement sshd. | ||
| ===== Une configuration possible ===== | ===== Une configuration possible ===== | ||
| + | En relisant les divers fichiers de configuration, | ||
| Dans '' | Dans '' | ||
| Ligne 53: | Ligne 54: | ||
| - action = %(action_)s | - action = %(action_)s | ||
| - | Debian installe un unique fichier dans ce répertoire '' | + | Dans '' |
| < | < | ||
| [DEFAULT] | [DEFAULT] | ||
| Ligne 66: | Ligne 67: | ||
| Debian protège donc ssh par défaut. Nous allons modifier un peu, mais avant, voyons le principe: | Debian protège donc ssh par défaut. Nous allons modifier un peu, mais avant, voyons le principe: | ||
| - la source des informations (backend), c'est le journal géré par systemd | - la source des informations (backend), c'est le journal géré par systemd | ||
| - | - ce qu'il faut observer dans le journal (journalmatch) c'est :\ '' | + | - ce qu'il faut observer dans le journal (journalmatch) c'est :\ '' |
| - le filtre est actif (enabled = true) | - le filtre est actif (enabled = true) | ||
| Toutes les autres directives sont données dans les divers paragraphes [DEFAULT] déjà rencontrés lors de la lecture séquentielle de la configuration. | Toutes les autres directives sont données dans les divers paragraphes [DEFAULT] déjà rencontrés lors de la lecture séquentielle de la configuration. | ||
| - | Nous allons casser le fichier '' | + | Nous allons casser le fichier '' |
| < | < | ||
| [DEFAULT] | [DEFAULT] | ||
| Ligne 97: | Ligne 98: | ||
| - | |||
| - | Commençons pas dissocier dans le répertoire '' | ||
| Ligne 124: | Ligne 123: | ||
| </ | </ | ||
| Nous pouvons désormais supprimer le fichier '' | Nous pouvons désormais supprimer le fichier '' | ||
| + | ==== Tests ==== | ||
| + | Pour rappel, le filtre installé au démarrage du serveur de test est le suivant: | ||
| + | < | ||
| + | chain input_ipv4 { | ||
| + | icmp type echo-request limit rate 5/second burst 5 packets accept | ||
| + | } | ||
| + | |||
| + | chain input_ipv6 { | ||
| + | icmpv6 type { nd-router-advert, | ||
| + | icmpv6 type echo-request limit rate 5/second burst 5 packets accept | ||
| + | } | ||
| + | |||
| + | chain input { | ||
| + | type filter hook input priority filter; policy drop; | ||
| + | iifname " | ||
| + | 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 | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | Un attaquant, lui aussi virtuel, dont la configuration IP est la suivante: | ||
| + | inet 192.168.60.76/ | ||
| + | inet6 2a01: | ||
| + | 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: | ||
| + | |||
| + | < | ||
| + | < | ||
| + | |||
| + | <span class=" | ||
| + | juin 30 18:19:18 trixie-nft sshd-session[1040]: | ||
| + | juin 30 18:19:18 trixie-nft sshd-session[1040]: | ||
| + | juin 30 18:19:20 trixie-nft sshd-session[1040]: | ||
| + | <span class=" | ||
| + | juin 30 18:21:09 trixie-nft sshd-session[1065]: | ||
| + | juin 30 18:21:09 trixie-nft sshd-session[1065]: | ||
| + | juin 30 18:21:11 trixie-nft sshd-session[1065]: | ||
| + | <span class=" | ||
| + | juin 30 18:23:01 trixie-nft sshd[750]: Timeout before authentication for connection from 192.168.60.76 to 192.168.60.5, | ||
| + | </ | ||
| + | L' | ||
| + | |||
| + | Sur le serveur, la configuration «nftables» a été dynamiquement mise à jour par fail2ban. Nous pouvons observer le résultat: | ||
| + | |||
| + | < | ||
| + | < | ||
| + | |||
| + | 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, | ||
| + | icmpv6 type echo-request limit rate 5/second burst 5 packets accept | ||
| + | } | ||
| + | |||
| + | chain input { | ||
| + | type filter hook input priority filter; policy drop; | ||
| + | iifname " | ||
| + | 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=" | ||
| + | set addr6-set-sshd { | ||
| + | type ipv6_addr | ||
| + | elements = { 2a01: | ||
| + | } | ||
| + | |||
| + | 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 | ||
| + | } | ||
| + | }</ | ||
| + | </ | ||
| + | |||
| + | 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' | ||
| + | < | ||
| + | -A f2b-ssh -s 80.240.252.168/ | ||
| + | -A f2b-ssh -s 157.254.54.192/ | ||
| + | -A f2b-ssh -s 8.222.168.120/ | ||
| + | -A f2b-ssh -s 65.108.211.181/ | ||
| + | -A f2b-ssh -s 154.209.4.36/ | ||
| + | -A f2b-ssh -s 157.10.252.119/ | ||
| + | -A f2b-ssh -s 14.103.114.20/ | ||
| + | .... | ||
| + | </ | ||
| + | Et le même procédure pour les adresses IPv6. Si les «sets» existaient déjà avec iptables, fail2ban ne les utilisait pas (l' | ||
| + | |||
| + | 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: | ||
| + | < | ||
| + | < | ||
| + | |||
| + | table inet f2b-table { | ||
| + | <span class=" | ||
| + | type ipv6_addr | ||
| + | } | ||
| + | |||
| + | set addr-set-sshd { | ||
| + | type ipv4_addr | ||
| + | }</ | ||
| + | |||
| + | 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 | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | 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 '' | ||
| + | |||
| + | Des explications, | ||
| + | < | ||
| + | <span class=" | ||
| + | # Usage example (for jail.local): | ||
| + | # | ||
| + | # mode = extra | ||
| + | # # or another jail (rewrite filter parameters of jail): | ||
| + | # | ||
| + | # | ||
| + | #</ | ||
| + | <span class=" | ||
| + | </ | ||
| + | Hélas, la maîtrise de ces modes suppose non seulement celle des expressions régulières, | ||
| + | |||
| + | 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, | ||
| + | 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: | ||
| + | < | ||
| + | < | ||
| + | |||
| + | OK | ||
| + | </ | ||
| + | («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: | ||
| + | < | ||
| + | table inet f2b-table { | ||
| + | set addr6-set-sshd { | ||
| + | type ipv6_addr | ||
| + | elements = { 2a01: | ||
| + | } | ||
| + | |||
| + | 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 | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | Reboot de la machine et contrôle de l' | ||
| + | < | ||
| + | < | ||
| + | |||
| + | table inet f2b-table { | ||
| + | set addr6-set-sshd { | ||
| + | type ipv6_addr | ||
| + | elements = { 2a01: | ||
| + | } | ||
| + | |||
| + | 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 | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | fail2ban a bonne mémoire. | ||
| + | |||
| + | Dans la foulée, nous pouvons également vérifier qu'une commande comme: | ||
| + | systemctl restart fail2ban | ||
| + | n' | ||
| + | ==== L' | ||
| + | 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' | ||
| + | |- Number of jail: 1 | ||
| + | `- Jail list: | ||
| + | * **fail2ban-client start/ | ||
| + | * **fail2ban-client get < | ||
| + | * **fail2ban-client unban <IP> ... < | ||
| + | * etc. | ||
Surveillance de sshd: Dernière modification le: 30/06/2025 à 15:54 par prof