# Guide d'analyse des logs et détection de bots abusifs Guide complet pour analyser les logs d'un serveur, identifier les IP problématiques, détecter les bots malveillants et mettre en place des protections automatiques. ## Table des matières 1. [Comprendre les logs](#1-comprendre-les-logs) 2. [Analyser les logs Docker](#2-analyser-les-logs-docker) 3. [Identifier les IP problématiques](#3-identifier-les-ip-problématiques) 4. [Analyser le comportement d'une IP](#4-analyser-le-comportement-dune-ip) 5. [Déterminer le type de bot](#5-déterminer-le-type-de-bot) 6. [Bloquer manuellement une IP](#6-bloquer-manuellement-une-ip) 7. [Automatiser avec Fail2ban](#7-automatiser-avec-fail2ban) 8. [Rate limiting](#8-rate-limiting) 9. [Monitoring continu](#9-monitoring-continu) 10. [Mémo rapide](#10-mémo-rapide) --- ## 1. Comprendre les logs ### Types de logs sous Linux | Type | Emplacement | Contenu | |------|-------------|---------| | **Logs système** | `/var/log/syslog` | Messages généraux du système | | **Logs d'authentification** | `/var/log/auth.log` | Connexions SSH, sudo, etc. | | **Logs Docker** | `/var/lib/docker/containers/.../*.log` | Logs des conteneurs | | **Journald** | `journalctl` | Logs systemd (moderne) | | **Logs d'applications** | Variable | Nginx, Apache, bases de données... | ### Format typique d'une ligne de log ``` 2026/02/02 08:17:57 [I] router: completed GET /repo/archive/main.zip for 216.73.216.118:0, 200 OK in 10.8ms │ │ │ │ │ │ │ │ └─ IP source └─ Code HTTP │ │ └─ Action (GET, POST...) │ └─ Niveau (I=Info, E=Error, W=Warning) └─ Timestamp ``` --- ## 2. Analyser les logs Docker ### Voir les logs d'un conteneur **Logs complets :** ```bash docker logs nom_conteneur ``` **Dernières lignes :** ```bash docker logs nom_conteneur --tail 50 ``` **Logs en temps réel (suivi) :** ```bash docker logs nom_conteneur -f ``` **Logs depuis un moment spécifique :** ```bash # Dernières 24 heures docker logs nom_conteneur --since 24h # Dernières 2 heures docker logs nom_conteneur --since 2h # Depuis une date précise docker logs nom_conteneur --since 2026-02-01T00:00:00 ``` ### Filtrer les logs **Chercher un pattern spécifique :** ```bash docker logs nom_conteneur | grep "erreur" docker logs nom_conteneur | grep "404" docker logs nom_conteneur | grep -i "archive" # -i = insensible à la casse ``` **Exclure certaines lignes :** ```bash docker logs nom_conteneur | grep -v "health check" # -v = inverse ``` **Sauvegarder dans un fichier :** ```bash docker logs nom_conteneur --since 24h > /tmp/logs.txt ``` --- ## 3. Identifier les IP problématiques ### Compter toutes les requêtes par IP **Méthode générale (si les IP sont dans les logs) :** ```bash docker logs conteneur --since 24h | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -20 ``` **Explication :** - `grep -oP '\d+\.\d+\.\d+\.\d+'` : Extrait toutes les adresses IP (regex) - `sort` : Trie les IP - `uniq -c` : Compte les occurrences uniques - `sort -rn` : Trie par nombre décroissant - `head -20` : Garde les 20 premières **Exemple de résultat :** ``` 2144 216.73.216.118 ← SUSPECT (trop de requêtes) 42 192.168.1.100 12 10.0.0.5 3 172.18.0.1 ``` ### Filtrer par type de requête **Requêtes d'archives uniquement :** ```bash docker logs forgejo --since 24h | grep "archive" > /tmp/archives.log grep -oP '\d+\.\d+\.\d+\.\d+' /tmp/archives.log | sort | uniq -c | sort -rn ``` **Requêtes avec erreur 500 :** ```bash docker logs forgejo --since 24h | grep "500 Internal" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn ``` **Requêtes POST (modifications) :** ```bash docker logs forgejo --since 24h | grep "POST" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn ``` ### Statistiques par heure **Voir l'activité par heure :** ```bash docker logs forgejo --since 24h | grep "archive" | grep -oP '^\d{4}/\d{2}/\d{2} \d{2}' | uniq -c ``` **Exemple :** ``` 12 2026/02/02 08 ← 12 requêtes à 8h 145 2026/02/02 09 ← 145 requêtes à 9h (SUSPECT) 18 2026/02/02 10 ``` --- ## 4. Analyser le comportement d'une IP Une fois une IP suspecte identifiée (ex: `216.73.216.118`), analysons son comportement. ### Voir toutes ses requêtes ```bash docker logs forgejo --since 24h | grep "216.73.216.118" > /tmp/ip_suspect.log ``` ### Compter ses requêtes ```bash wc -l /tmp/ip_suspect.log ``` **Exemple :** `2144` requêtes en 24h = ~90 requêtes/heure = suspect ### Voir ce qu'elle télécharge ```bash grep "216.73.216.118" /tmp/ip_suspect.log | head -20 ``` **Patterns suspects :** | Pattern | Signification | |---------|---------------| | `/archive/main:vendor/...` | Scanne les dépendances (recherche de vulnérabilités) | | `/archive/commit123.zip` répété | Télécharge tous les commits (crawler) | | Requêtes très rapprochées | Bot automatisé | | 500 Internal Server Error | Tentatives qui échouent (disque plein, etc.) | ### Identifier les repos ciblés ```bash grep "216.73.216.118" /tmp/ip_suspect.log | grep -oP '/[^/]+/[^/]+/archive' | sort | uniq -c | sort -rn ``` **Exemple :** ``` 1350 /studio-variable/designtopack/archive ← Cible principale 232 /studio-variable/index-shop/archive 86 /studio-variable/world-game/archive ``` ### Analyser la fréquence **Temps entre chaque requête :** ```bash grep "216.73.216.118" /tmp/ip_suspect.log | grep -oP '^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}' | head -20 ``` **Si les timestamps sont très rapprochés (< 1 seconde) :** C'est un bot automatisé. --- ## 5. Déterminer le type de bot ### Identifier le User-Agent ```bash docker logs forgejo --since 24h | grep "216.73.216.118" | grep -oP 'User-Agent: [^"]*' | sort | uniq -c ``` **User-Agents courants :** | User-Agent | Type | Légitime ? | |------------|------|------------| | `Googlebot` | Crawler Google | ✅ Oui | | `bingbot` | Crawler Bing | ✅ Oui | | `curl/7.x` | Script automatisé | ⚠️ Dépend | | `python-requests/2.x` | Script Python | ⚠️ Dépend | | `Go-http-client` | Script Go | ⚠️ Dépend | | Aucun ou vide | Bot basique | ❌ Suspect | ### Identifier le propriétaire de l'IP (whois) ```bash whois 216.73.216.118 | head -30 ``` **Cherche :** - `OrgName:` → Propriétaire (AWS, Google, hébergeur...) - `NetName:` → Type de réseau - `Country:` → Pays **Exemples :** ``` OrgName: Amazon.com, Inc. → Hébergé sur AWS OrgName: Google LLC → Infrastructure Google OrgName: OVH SAS → Hébergeur français ``` ### Vérifier la réputation de l'IP **Services en ligne :** - https://www.abuseipdb.com/check/IP - https://www.virustotal.com/gui/ip-address/IP - https://mxtoolbox.com/SuperTool.aspx?action=blacklist:IP --- ## 6. Bloquer manuellement une IP ### Dans Forgejo/Gitea **Éditer la configuration :** ```bash sudo nano /path/to/forgejo/data/gitea/conf/app.ini ``` **Ajouter la section `[security]` :** ```ini [security] BANNED_IP_ADDRESSES = 216.73.216.118,192.168.1.50 ``` **Redémarrer :** ```bash docker restart forgejo ``` ### Avec iptables (niveau firewall) **Bloquer une IP :** ```bash sudo iptables -A INPUT -s 216.73.216.118 -j DROP ``` **Voir les règles :** ```bash sudo iptables -L -n ``` **Sauvegarder (pour que ça persiste au reboot) :** ```bash sudo iptables-save > /etc/iptables/rules.v4 ``` **Débloquer une IP :** ```bash sudo iptables -D INPUT -s 216.73.216.118 -j DROP ``` ### Avec UFW (plus simple) **Bloquer une IP :** ```bash sudo ufw deny from 216.73.216.118 ``` **Voir les règles :** ```bash sudo ufw status numbered ``` **Supprimer une règle :** ```bash sudo ufw delete NUMÉRO ``` --- ## 7. Automatiser avec Fail2ban Fail2ban surveille les logs et bannit automatiquement les IP abusives. ### Installation ```bash sudo apt update sudo apt install fail2ban sudo systemctl enable fail2ban sudo systemctl start fail2ban ``` ### Configuration pour détecter les requêtes d'archives excessives **Créer un filtre :** ```bash sudo nano /etc/fail2ban/filter.d/forgejo-archive.conf ``` **Contenu :** ```ini [Definition] failregex = completed GET .*/archive/.* for ignoreregex = ``` **Créer une jail :** ```bash sudo nano /etc/fail2ban/jail.d/forgejo.conf ``` **Contenu :** ```ini [forgejo-archive] enabled = true filter = forgejo-archive logpath = /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log maxretry = 50 findtime = 600 bantime = 3600 ``` **Remplace `CONTAINER_ID` par le vrai ID :** ```bash docker inspect forgejo --format='{{.LogPath}}' ``` **Redémarrer Fail2ban :** ```bash sudo systemctl restart fail2ban ``` ### Vérifier le statut ```bash # Statut général sudo fail2ban-client status # Statut d'une jail spécifique sudo fail2ban-client status forgejo-archive ``` **Exemple de sortie :** ``` Status for the jail: forgejo-archive |- Filter | |- Currently failed: 2 | |- Total failed: 145 | `- File list: /var/lib/docker/containers/.../...json.log `- Actions |- Currently banned: 1 |- Total banned: 3 `- Banned IP list: 216.73.216.118 ``` ### Commandes utiles ```bash # Voir les IP bannies sudo fail2ban-client get forgejo-archive banip # Bannir manuellement une IP sudo fail2ban-client set forgejo-archive banip 192.168.1.50 # Débannir une IP sudo fail2ban-client set forgejo-archive unbanip 192.168.1.50 # Voir les logs de Fail2ban sudo tail -f /var/log/fail2ban.log ``` ### Ajuster les paramètres Dans `/etc/fail2ban/jail.d/forgejo.conf` : | Paramètre | Signification | Exemple | |-----------|---------------|---------| | `maxretry` | Nombre de tentatives avant ban | `50` = bannir après 50 requêtes | | `findtime` | Fenêtre de temps (secondes) | `600` = dans les 10 dernières minutes | | `bantime` | Durée du ban (secondes) | `3600` = bannir pour 1 heure | **Exemples de configurations :** ```ini # Tolérant (serveur public) maxretry = 100 findtime = 600 bantime = 3600 # Strict (serveur privé) maxretry = 20 findtime = 300 bantime = 86400 # 24 heures # Permanent bantime = -1 # Ban permanent ``` --- ## 8. Rate limiting Limite le nombre de requêtes par IP directement dans l'application. ### Dans Forgejo/Gitea **Éditer `app.ini` :** ```bash sudo nano /path/to/forgejo/data/gitea/conf/app.ini ``` **Ajouter :** ```ini [api] ENABLE_RATE_LIMIT = true RATE_LIMIT_BURST = 100 [repository] DOWNLOAD_OR_CLONE_METHODS = http,https,ssh DOWNLOAD_EXPIRY_TIME = 60 ``` **Redémarrer :** ```bash docker restart forgejo ``` ### Avec Nginx (si reverse proxy) **Dans la config Nginx :** ```nginx http { # Définir une zone de rate limiting limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { location / { # Appliquer la limite limit_req zone=mylimit burst=20 nodelay; proxy_pass http://localhost:3000; } } } ``` **Tester la config :** ```bash sudo nginx -t sudo systemctl reload nginx ``` --- ## 9. Monitoring continu ### Script de surveillance quotidien **Créer un script :** ```bash sudo nano /usr/local/bin/check-suspicious-ips.sh ``` **Contenu :** ```bash #!/bin/bash LOG_FILE="/tmp/suspicious_ips_$(date +%Y%m%d).log" THRESHOLD=100 echo "=== Suspicious IP Report - $(date) ===" > "$LOG_FILE" echo "" >> "$LOG_FILE" # Top 20 IP des dernières 24h echo "Top 20 IPs (last 24h):" >> "$LOG_FILE" docker logs forgejo --since 24h | grep -oP '\d+\.\d+\.\d+\.\d+' | \ sort | uniq -c | sort -rn | head -20 >> "$LOG_FILE" echo "" >> "$LOG_FILE" # IP dépassant le seuil echo "IPs with more than $THRESHOLD requests:" >> "$LOG_FILE" docker logs forgejo --since 24h | grep -oP '\d+\.\d+\.\d+\.\d+' | \ sort | uniq -c | sort -rn | awk -v threshold="$THRESHOLD" '$1 > threshold' >> "$LOG_FILE" # Envoyer par email (optionnel) # mail -s "Suspicious IPs Report" admin@example.com < "$LOG_FILE" echo "Report saved to $LOG_FILE" ``` **Rendre exécutable :** ```bash sudo chmod +x /usr/local/bin/check-suspicious-ips.sh ``` **Ajouter au cron (tous les jours à 8h) :** ```bash sudo crontab -e ``` Ajouter : ``` 0 8 * * * /usr/local/bin/check-suspicious-ips.sh ``` ### Dashboard temps réel **Surveiller les requêtes d'archives en temps réel :** ```bash watch -n 5 'docker logs forgejo --since 5m | grep "archive" | wc -l' ``` **Voir les nouvelles IP actives :** ```bash watch -n 10 'docker logs forgejo --since 10m | grep -oP "\d+\.\d+\.\d+\.\d+" | sort -u' ``` ### Alertes par email **Installer mailutils :** ```bash sudo apt install mailutils ``` **Script d'alerte :** ```bash #!/bin/bash COUNT=$(docker logs forgejo --since 1h | grep "archive" | wc -l) if [ "$COUNT" -gt 500 ]; then echo "ALERTE: $COUNT requêtes d'archives dans la dernière heure!" | \ mail -s "Alerte serveur Forgejo" admin@example.com fi ``` **Ajouter au cron (toutes les heures) :** ``` 0 * * * * /path/to/alert-script.sh ``` --- ## 10. Mémo rapide (cheat sheet) ### Analyse basique ```bash # Top 20 IP des dernières 24h docker logs conteneur --since 24h | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -20 # Requêtes d'une IP spécifique docker logs conteneur --since 24h | grep "IP_ADRESSE" # Compter les requêtes d'archives docker logs conteneur --since 24h | grep "archive" | wc -l # Repos les plus ciblés docker logs conteneur --since 24h | grep "archive" | grep -oP '/[^/]+/[^/]+/archive' | sort | uniq -c | sort -rn | head -10 # Whois d'une IP whois IP_ADRESSE | head -30 ``` ### Fail2ban ```bash # Statut général sudo fail2ban-client status # Statut d'une jail sudo fail2ban-client status nom_jail # IP bannies sudo fail2ban-client get nom_jail banip # Bannir manuellement sudo fail2ban-client set nom_jail banip IP # Débannir sudo fail2ban-client set nom_jail unbanip IP # Logs Fail2ban sudo tail -f /var/log/fail2ban.log ``` ### Blocage manuel ```bash # Dans Forgejo (app.ini) [security] BANNED_IP_ADDRESSES = IP1,IP2,IP3 # Avec UFW sudo ufw deny from IP_ADRESSE sudo ufw status numbered sudo ufw delete NUMERO # Avec iptables sudo iptables -A INPUT -s IP_ADRESSE -j DROP sudo iptables -L -n ``` --- ## Cas pratiques ### Cas 1 : Bot qui télécharge massivement des archives **Symptômes :** - 2000+ requêtes d'archives en 24h - Disque qui se remplit rapidement - Cache repo-archive qui grossit **Diagnostic :** ```bash # Identifier l'IP docker logs forgejo --since 24h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5 # Analyser son comportement docker logs forgejo --since 24h | grep "IP_SUSPECTE" | head -20 # Whois whois IP_SUSPECTE ``` **Solution :** 1. Bloquer l'IP dans Forgejo (app.ini) 2. Configurer Fail2ban pour détecter automatiquement 3. Ajouter rate limiting 4. Mettre en place un cron de nettoyage du cache ### Cas 2 : Scan de vulnérabilités **Symptômes :** - Requêtes ciblant `/vendor`, `/node_modules`, `.env` - Beaucoup d'erreurs 404 - User-Agent = `curl` ou `python-requests` **Diagnostic :** ```bash # Voir les URLs demandées docker logs forgejo --since 24h | grep "IP_SUSPECTE" | grep -oP 'GET [^ ]*' | sort | uniq -c ``` **Solution :** 1. Bloquer l'IP 2. Vérifier qu'aucun fichier sensible n'est exposé 3. Configurer Fail2ban pour bannir après 10 erreurs 404 ### Cas 3 : Attaque DDoS **Symptômes :** - Centaines d'IP différentes - Requêtes très rapprochées - Serveur lent/inaccessible **Diagnostic :** ```bash # Nombre d'IP uniques docker logs forgejo --since 10m | grep -oP '\d+\.\d+\.\d+\.\d+' | sort -u | wc -l # Si > 100 IP en 10 min = DDoS potentiel ``` **Solution :** 1. Mettre le service derrière Cloudflare 2. Activer le mode "Under Attack" temporairement 3. Réduire drastiquement le rate limiting --- ## Ressources complémentaires **Documentation :** - Fail2ban : https://www.fail2ban.org/wiki/index.php/Main_Page - iptables : `man iptables` - UFW : `man ufw` - grep : `man grep` **Outils utiles :** - `goaccess` : Analyseur de logs web en temps réel - `geoiplookup` : Géolocalisation d'IP - `tcpdump` : Capture du trafic réseau - `netstat` / `ss` : Connexions actives **Regex IP :** ```regex \d+\.\d+\.\d+\.\d+ # IPv4 basique \b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b # IPv4 plus précis ``` --- **Guide créé le 2026-02-03**