Pare-feu : Iptables/Nftables, Fail2ban/Reaction
N'utilisez pas ça “comme ça”, ne croyez pas à la qualité de ce qui est là ! J'apprend, je note, mais je suis loin d'être assez experte pour que ce soit fiable, ce bazar.
À la base, mes notes concernaient Fail2ban et iptables, pour des raisons historiques.
Mais il est temps de passer à la suite. À présent c'est nftables qui est là par défaut. Quand à Reaction ben c'est juste sacrément plus clair et sympa que Fail2ban.
Le principal est de bien configurer le pare-feu (iptables/nftables ou autre). Fail2ban, Reaction, SSHguard ajoutent des protections en plus en délayant les attaques par brute-force, selon le principe du tamis : si ça passe une couche, avec un peu de chance ça ne passera pas la suivante.
La liste des pages liées :
Scripts et astuces de pare-feu
Faudrait que je reprenne et mette à jour…
Lister les occurrences d'ip bannies
cat /var/log/fail2ban.lo* | grep -v "Restore" | grep "Ban" |awk '{print $6" "$8}'|sort|uniq -c|sort -nr | awk '{gsub(/^[ \t]+/,""); print$0}'
cat /var/log/fail2ban.lo*
: va regarder tous les fichiers de log de fail2bangrep -v “Restore”
: exclure les moments où on restaure les ip (ça fout le dawa dans les résultats)grep “Ban”
: garder, dans ce qui reste, toutes les lignes où on bannit un trucawk '{print $6" "$8}'
: garder seulement la 6e et 7e partie (celle avec le nom du service et celle avec l'ip)sort
une fois pour que les ip identiques soient les unes à la suite des autresuniq -c
réunit les lignes communes et affiche devant le nombre de fois qu’elles apparaissent- un dernier sort (avec l’option reverse et l’option number) pour faire un tri inverse par nombre
awk '{gsub(/^[ \t]+/,""); print$0}'
: compliqué à lire celui-ci. Il enlève les espaces au début, ce qui est utile pour se servir du truc dans un script par la suite.
Très beau, très simple, fonctionnel. Mais on va aller plus loin avec un petit cron qui lance de temps en temps une vérification et bannit définitivement les ip qui ont un peu trop essayé.
Script de bannissement définitif
J'ai mis ça dans /root/banip/ (dossier à créer donc).
mkdir /root/banip/
- banip_auto.sh
#!/bin/bash # Bannir automatiquement une liste d'ip qui ont abusé. #fichier de log folderbanip="/root/banip" badiphuman="$folderbanip/badiphuman.txt" todayiptable="$folderbanip/today_iptable.txt" logban="$folderbanip/logban.log" ## Liste les ip gênantes, d'une façon lisible pour un humain # awk '{gsub(/^[ \t]+/,""); print$0}' => enlève les espaces au début cat /var/log/fail2ban.lo* | grep -v "Restore" | grep "Ban" |awk '{print $6" "$8}'|sort|uniq -c|sort -nr | awk '{gsub(/^[ \t]+/,""); print$0}' > $badiphuman # sauvegarde les règles iptables et ipset actuelles pour comparer iptables -L -n -v > $todayiptable ipset list >> $todayiptable # On alimente le fichier de log echo "#####" >> $logban date >> $logban ## Si l'ip est revenu plus d'un certain nombre de fois, alors on la sélectionne pour un ban définitif # lire fichier $badiphuman cat $badiphuman | while IFS= read -r line; do tableau=(${line// /,}) number=$(echo $tableau | cut -d ',' -f 1) ip=$(echo $tableau | cut -d ',' -f 3) #Si l'ip apparait 2 fois ou plus, on la bannit, sinon elle a sa chance if (($number >= 2)) then # on va tester si on a déjà la règle if grep -q "$ip" $todayiptable then echo "IP address already blocked, skipping" >> $logban else ipset add blocklist_ip $ip echo "Blocking $ip because $number occurences" >> $logban fi else echo "$ip not blocking for the moment, only $number try" >> $logban fi done #Sauver les modifs ipset save netfilter-persistent save #iptables-save >> /etc/iptables/rules.v4
Et maintenant un cron, une fois par jour, pour s'assurer qu'on bloque les plus méchants (et les moins futés, certes…)
crontab -e 30 0 * * * /root/banip/banip_auto.sh
Bannir des plages d'ip
Parfois des comportements malveillants viennent d'une plage d'ip et pas seulement d'une ip seule.
Il faut des alertes pour les repérer (ou si y'a moyen d'affiner les outils déjà présents, je ne sais pas encore comment). Et je suis contre le fait de bannir des pays entiers. D'autant que ça m'arrive d'avoir des échanges avec des gens dans un “mauvais” pays… Je peux comprendre qu'on utilise ça en cas de gros soucis mais tant que je peux m'en passer, je vais essayer de le faire.
La notation d'une plage d'ip est de la forme x.x.x.0/24. Enfin, les chiffres au bout varient parfois… Comment être sûr de son coup ?
Installer ipcalc
. Puis demandez lui des détails sur une de ces adresses ip malveillantes :
% ipcalc 87.120.84.142 Address: 87.120.84.142 01010111.01111000.01010100. 10001110 Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000 Wildcard: 0.0.0.255 00000000.00000000.00000000. 11111111 => Network: 87.120.84.0/24 01010111.01111000.01010100. 00000000 HostMin: 87.120.84.1 01010111.01111000.01010100. 00000001 HostMax: 87.120.84.254 01010111.01111000.01010100. 11111110 Broadcast: 87.120.84.255 01010111.01111000.01010100. 11111111 Hosts/Net: 254 Class A
Network
nous indique toute la plage associée, qui va de HostMin
à HostMax
. Vérifions…
% ipcalc 87.120.84.0/24 Address: 87.120.84.0 01010111.01111000.01010100. 00000000 Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000 Wildcard: 0.0.0.255 00000000.00000000.00000000. 11111111 => Network: 87.120.84.0/24 01010111.01111000.01010100. 00000000 HostMin: 87.120.84.1 01010111.01111000.01010100. 00000001 HostMax: 87.120.84.254 01010111.01111000.01010100. 11111110 Broadcast: 87.120.84.255 01010111.01111000.01010100. 11111111 Hosts/Net: 254 Class A
Ici 0/24
semble marcher. Hop, on ajoute ça dans le ban…
ipset add blocklist_ip 87.120.84.0/24
et ipset list
va nous montrer les 254 nouvelles adresses bloquées… Pfiou !
D'où viennent les attaques ?
Là c'est de la curiosité car je ne pense pas que je puisse y faire grand chose. Mais, quand même, ça permet de voir la pertinence (ou pas) de bloquer un pays.
En premier, récupérer les logs montrant une “authentification failed”. Vu le nombre de personnes ayant accès à mon serveur, c'est *toujours* des attaques.
grep "authentication failed" /var/log/mail.log > /var/vmail/viewmail.log
Ensuite je me suis envoyée ce fichier via Mutt parce que ce n'était pas très pratique à distance, je l'ai nettoyé avec diverses bidouilles pour n'avoir que les ips et en un exemplaire (sort|uniq). Ça mériterais que je note la manip un jour… peut-être !
Et après, j'ai mouliné ce fichier appelé “badip.txt” avec ce petit script :
#!/bin/bash
# Savoir d'où vienne les méchantes ip
cat badip.txt | while IFS= read -r line; do
tableau=(${line// /,})
geo=$(geoiplookup $tableau)
echo $geo >> country.txt
cat country.txt | sort|uniq -c | sort > finalbadip.txt
done
Ce qui donne lors de ce test, 90 tentatives d'intrusion sur une seule journée, dont 33 en provenance de Chine et le reste réparti dans divers pays, de l'Australie aux USA en passant par l'Italie ou l'Allemagne.
Si je ne me vois pas bloquer ces pays (même la Chine), je me demande s'il y a moyen de filtrer quel pays a le droit de tester certaines actions, comme se connecter à un compte mail.
Une alternative via systemd
Pour les IPs qui ont le plus chercher à se connecter au serveur mail sans succès, pour une journée donnée :
journalctl --since=2023-10-06 --until=2023-10-07 --grep='SASL LOGIN authentication failed' --unit=postfix@-.service | sed 's/.*warning: \([^ ]*\): .*$/\1/' | sort | uniq --count | sort --human-numeric-sort --reverse | head
Et juste pour le jour même :
journalctl --since=today --grep='SASL LOGIN authentication failed' --unit=postfix@-.service | sed 's/.*warning: \([^ ]*\): .*$/\1/' | sort | uniq --count | sort --human-numeric-sort --reverse | head