Table des matières

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}'

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

 Ce texte est placé sous licence CC0