Créer une blacklist IP en fonction des logs serveurs récupérés dans un fichier
Objectif : rejeter les requêtes des clients qui génèrent des erreurs 404 et 500 trop fréquemment en les ajoutant à une blacklist. En général, cela signifie que le client scanne le serveur à la recherche de failles de sécurité ou fait du scraping de données. C'est un premier niveau de protection contre les attaques type DDoS ou reconnaissance.
Prérequis
Installer les outils suivants :
sudo apt update && sudo apt install -y jq iptablesVérifier l'installation :
jq --version
iptables --versionFichier de logs attendu
Caddy doit être configuré pour écrire des logs JSON dans :
/var/log/caddy/requests.jsonCe fichier doit contenir des champs .ts (timestamp) et .request.client_ip.
Créer le script monitor_blacklist.sh
sudo nano /usr/local/bin/monitor_blacklist.shContenu du script :
#!/bin/bash
LOG_DIR="/var/log/caddy"
LOG_FILES="$LOG_DIR/requests*.json"
BLACKLIST_FILE="/etc/caddy/blacklist.txt"
FAIL2BAN_JAIL="/etc/fail2ban/jail.local"
THRESHOLD=5
DELAY=180
cleanup() {
echo "Arrêt du script monitor_blacklist.sh"
pkill -f "sleep"
exit 0
}
trap cleanup SIGINT SIGTERM
# Vérification des dépendances
for cmd in iptables jq; do
if ! command -v $cmd &>/dev/null; then
echo "Erreur : $cmd non installé"
exit 1
fi
done
echo "Démarrage de la surveillance des logs..."
# Récupération dynamique des IP whitelists à partir du jail.local
readarray -t WHITELIST < <(grep -E '^ignoreip\s*=' "$FAIL2BAN_JAIL" \
| sed 's/.*=\s*//' \
| tr -s ' ' '\n' \
| grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]+)?')
echo "IPs en liste blanche (issues de Fail2Ban) : ${WHITELIST[*]}"
# Création de la chaîne BLOCKED si absente
if ! sudo iptables -L BLOCKED &>/dev/null; then
sudo iptables -N BLOCKED && echo "Chaîne BLOCKED créée."
fi
# Fonction pour vérifier si une IP est dans la whitelist
is_whitelisted() {
local ip=$1
for entry in "${WHITELIST[@]}"; do
if [[ "$entry" == *"/"* ]]; then
# C'est un réseau CIDR (ex: 192.168.0.0/24)
local network=$(echo "$entry" | cut -d'/' -f1)
local prefix=$(echo "$network" | cut -d'.' -f1-3)
# Si l'IP commence par le préfixe du réseau, elle est whitelistée
if [[ "$ip" == "$prefix."* ]]; then
return 0
fi
else
# IP individuelle
if [[ "$ip" == "$entry" ]]; then
return 0
fi
fi
done
return 1
}
# Boucle principale
while true; do
echo "-------------------------------------"
echo "Analyse des logs à $(date)"
TMP_FILE=$(mktemp)
> "$BLACKLIST_FILE"
# Extraction des IP à bannir
for file in $LOG_FILES; do
if [ -r "$file" ] && jq empty "$file" 2>/dev/null; then
jq -r '. | [.ts, .request.client_ip] | @tsv' "$file" >> "$TMP_FILE"
else
echo "Fichier ignoré (illisible ou invalide JSON) : $file"
fi
done
# Calcul des IP à bloquer selon le seuil
awk -F'\t' '{ ipcount[int($1)" "$2]++ } END {
for (key in ipcount) {
split(key, parts, " ")
if (ipcount[key] >= '"$THRESHOLD"') {
print parts[2]
}
}
}' "$TMP_FILE" | sort -u | while read -r ip; do
# Filtrer avec la fonction is_whitelisted
if ! is_whitelisted "$ip"; then
echo "$ip"
fi
done > "$BLACKLIST_FILE"
rm "$TMP_FILE"
if [ -s "$BLACKLIST_FILE" ]; then
echo "IPs à bloquer :"
cat "$BLACKLIST_FILE"
while read -r ip; do
if [ -n "$ip" ]; then
if ! sudo iptables -C BLOCKED -s "$ip" -j REJECT 2>/dev/null; then
sudo iptables -A BLOCKED -s "$ip" -j REJECT
echo "→ IP bannie : $ip"
else
echo "→ IP déjà bannie : $ip"
fi
fi
done < "$BLACKLIST_FILE"
if ! sudo iptables -L INPUT -n | grep -q 'BLOCKED'; then
sudo iptables -A INPUT -j BLOCKED
echo "Chaîne BLOCKED ajoutée à INPUT."
fi
> "$BLACKLIST_FILE"
echo "Fichier blacklist.txt réinitialisé."
else
echo "Aucune IP à blacklister."
fi
sleep "$DELAY"
doneRendre le script exécutable
sudo chmod +x /usr/local/bin/monitor_blacklist.shConfiguration de la whitelist
Le script récupère automatiquement la liste des IPs à ne jamais bloquer depuis le fichier /etc/fail2ban/jail.local. Cette configuration est critique pour éviter de se bloquer soi-même.
Whitelister des IPs individuelles
sudo nano /etc/fail2ban/jail.localAjouter ou modifier la ligne ignoreip dans la section [DEFAULT] :
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.50 198.51.100.25Whitelister un réseau local complet (recommandé)
Pour éviter de bloquer des machines sur le réseau local lors de tests ou scans de sécurité, whitelist la plage complète en notation CIDR :
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/24Explications des notations réseau :
192.168.0.0/24: toutes les IPs de 192.168.0.0 à 192.168.0.25510.0.0.0/8: toutes les IPs de 10.0.0.0 à 10.255.255.255172.16.0.0/12: toutes les IPs de 172.16.0.0 à 172.31.255.255
Ces plages sont des adresses privées (RFC 1918) non routables sur Internet. Les whitelister n'expose pas le serveur à des attaques externes.
Combiner réseaux et IPs individuelles
On peut combiner plusieurs types d'entrées :
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/24 10.0.0.0/8 203.0.113.50Appliquer les changements
Après modification du fichier jail.local, redémarrer les services :
sudo systemctl restart fail2ban
sudo systemctl restart monitor_blacklist.serviceVérifier que la whitelist est bien chargée :
sudo tail -20 /var/log/monitor_blacklist.logOn doit voir une ligne similaire à :
IPs en liste blanche (issues de Fail2Ban) : 127.0.0.1/8 192.168.0.0/24 203.0.113.50Lancer le script manuellement (test)
sudo nohup /usr/local/bin/monitor_blacklist.sh &Vérification
Vérifier que le script tourne :
ps aux | grep monitor_blacklist.shLister les IP bloquées :
sudo iptables -L BLOCKED -v -nLister les IP bloquées avec numéros de ligne :
sudo iptables -L BLOCKED -v -n --line-numbersVérifier si une IP spécifique est bloquée :
sudo iptables -L BLOCKED -v -n | grep 185.177.72.104Lister les appels de la règle BLOCKED dans INPUT :
sudo iptables -L INPUT -v -nGestion des IPs bloquées
Débloquer une IP spécifique
Méthode 1 - Par IP :
sudo iptables -D BLOCKED -s 185.177.72.104 -j REJECTMéthode 2 - Par numéro de ligne :
# Lister avec numéros
sudo iptables -L BLOCKED -n --line-numbers
# Supprimer la ligne X (remplacer X par le numéro de la ligne)
sudo iptables -D BLOCKED XVider toute la chaîne BLOCKED
sudo iptables -F BLOCKEDRechercher une IP dans toutes les règles
sudo iptables-save | grep 185.177.72.104Créer un service systemd
sudo nano /etc/systemd/system/monitor_blacklist.serviceContenu :
[Unit]
Description=Surveillance automatique des logs HTTP et blacklisting IP
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/monitor_blacklist.sh
Restart=always
RestartSec=10
User=root
WorkingDirectory=/var/www/html
StandardOutput=append:/var/log/monitor_blacklist.log
StandardError=append:/var/log/monitor_blacklist.log
[Install]
WantedBy=multi-user.targetActiver et démarrer le service :
sudo systemctl daemon-reload
sudo systemctl enable monitor_blacklist.service
sudo systemctl start monitor_blacklist.serviceVérifier son statut :
sudo systemctl status monitor_blacklist.serviceVérifier les logs en temps réel :
sudo tail -f /var/log/monitor_blacklist.logGestion des logs Caddy
Vider les logs après un scan de sécurité
Si vous effectuez un scan de sécurité (ZAP, Nessus, etc.) qui génère beaucoup de requêtes, les logs peuvent contenir un grand nombre d'erreurs qui déclenchent le blacklisting. Pour éviter d'être bloqué après le scan :
# Arrêter le service de surveillance
sudo systemctl stop monitor_blacklist.service
# Vider les logs
sudo truncate -s 0 /var/log/caddy/requests*.json
# Redémarrer le service
sudo systemctl start monitor_blacklist.serviceArchiver les logs avant nettoyage
# Créer un répertoire d'archives
sudo mkdir -p /var/log/caddy/archives
# Archiver avec timestamp
sudo tar -czf /var/log/caddy/archives/requests-$(date +%Y%m%d-%H%M%S).tar.gz /var/log/caddy/requests*.json
# Vider les logs
sudo truncate -s 0 /var/log/caddy/requests*.jsonAjuster le seuil de détection
Le paramètre THRESHOLD dans le script définit le nombre minimum de requêtes suspectes avant blocage.
Augmenter temporairement le seuil pour un scan
sudo nano /usr/local/bin/monitor_blacklist.shModifier la ligne :
THRESHOLD=50 # au lieu de 5Puis redémarrer :
sudo systemctl restart monitor_blacklist.serviceRestaurer le seuil par défaut
Remettre THRESHOLD=5 après le scan et redémarrer le service.
Diagnostic en cas de blocage
Identifier si vous êtes bloqué
Symptômes : connexion refusée ou timeout sur les ports HTTP/HTTPS depuis une machine spécifique, mais SSH fonctionne.
Trouver votre IP
Depuis la machine bloquée :
# Linux/macOS
curl -s https://api.ipify.org
# Afficher l'IP locale (réseau privé)
ip addr show # Linux
ipconfig getifaddr en0 # macOS WiFiRechercher votre IP dans les règles
# Rechercher dans toutes les règles iptables
sudo iptables-save | grep VOTRE_IP
# Rechercher spécifiquement dans BLOCKED
sudo iptables -L BLOCKED -n -v | grep VOTRE_IP
# Rechercher dans tous les logs
sudo grep -r "VOTRE_IP" /var/log/ /etc/ 2>/dev/null | grep -v "Binary"Débloquer et whitelister
# Débloquer
sudo iptables -D BLOCKED -s VOTRE_IP -j REJECT
# Whitelister définitivement
sudo nano /etc/fail2ban/jail.local
# Ajouter VOTRE_IP dans ignoreip
# Redémarrer
sudo systemctl restart fail2ban
sudo systemctl restart monitor_blacklist.serviceSupprimer proprement le service
sudo systemctl stop monitor_blacklist.service
sudo systemctl disable monitor_blacklist.service
sudo rm /etc/systemd/system/monitor_blacklist.service
sudo systemctl daemon-reloadSupprimer la chaîne BLOCKED d'iptables :
# Retirer la référence dans INPUT
sudo iptables -D INPUT -j BLOCKED
# Vider la chaîne
sudo iptables -F BLOCKED
# Supprimer la chaîne
sudo iptables -X BLOCKEDBonnes pratiques
Avant un scan de sécurité
- Identifier l'IP source du scan
- L'ajouter dans la whitelist fail2ban
- Redémarrer le service monitor_blacklist
- Vérifier dans les logs que l'IP est bien whitelistée
Après un scan de sécurité
- Vérifier qu'aucune IP légitime n'a été bloquée
- Nettoyer les logs Caddy pour éviter les faux positifs
- Examiner les IPs bloquées pour identifier de réelles menaces
Pour un environnement de développement
Whitelister l'intégralité du réseau local :
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/24 10.0.0.0/8 172.16.0.0/12Pour un environnement de production
Whitelister uniquement les IPs fixes de confiance :
ignoreip = 127.0.0.1/8 ::1 203.0.113.50 198.51.100.25Troubleshooting
Le script ne démarre pas
Vérifier les dépendances :
which jq
which iptablesVérifier les permissions :
ls -l /usr/local/bin/monitor_blacklist.sh
# Doit être exécutable : -rwxr-xr-xLa whitelist n'est pas appliquée
Vérifier que le fichier jail.local existe et contient bien ignoreip :
sudo cat /etc/fail2ban/jail.local | grep ignoreipVérifier que la fonction is_whitelisted est présente dans le script :
grep -A 10 "is_whitelisted" /usr/local/bin/monitor_blacklist.shDes IPs du réseau local sont toujours bloquées
Vérifier le format CIDR dans jail.local (doit inclure /24) :
sudo cat /etc/fail2ban/jail.local | grep ignoreip
# Doit contenir : 192.168.0.0/24 (et non 192.168.0.0)Vérifier les logs du service :
sudo tail -50 /var/log/monitor_blacklist.logNettoyer les vieux logs Caddy qui contiennent des requêtes du scan :
sudo truncate -s 0 /var/log/caddy/requests*.json
sudo systemctl restart monitor_blacklist.serviceCe script offre une solution autonome et robuste pour réagir automatiquement aux comportements suspects détectés dans les logs HTTP générés par Caddy.