first commit
This commit is contained in:
commit
74e9840452
2 changed files with 1172 additions and 0 deletions
733
serveur/analyse-logs-detection-bots.md
Normal file
733
serveur/analyse-logs-detection-bots.md
Normal file
|
|
@ -0,0 +1,733 @@
|
|||
# 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 <HOST>
|
||||
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**
|
||||
439
serveur/diagnostic-espace-disque.md
Normal file
439
serveur/diagnostic-espace-disque.md
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
# Guide de diagnostic d'espace disque Linux
|
||||
|
||||
Guide complet pour identifier et résoudre les problèmes d'espace disque sur un serveur Linux.
|
||||
|
||||
## 1. Vue d'ensemble : quel disque est plein ?
|
||||
|
||||
```bash
|
||||
df -h
|
||||
```
|
||||
|
||||
**Cherche :**
|
||||
- La ligne `/dev/sda1` (ou `/dev/nvme0n1p1`, `/dev/vda1`) montée sur `/`
|
||||
- Si `Use%` > 80% → Problème
|
||||
|
||||
**Exemple :**
|
||||
```
|
||||
/dev/sda1 59G 57G 171M 100% / ← PROBLÈME ICI
|
||||
```
|
||||
|
||||
**Comprendre la sortie :**
|
||||
|
||||
| Colonne | Signification |
|
||||
|---------|---------------|
|
||||
| Filesystem | Nom du disque/partition |
|
||||
| Size | Capacité totale |
|
||||
| Used | Espace utilisé |
|
||||
| Avail | Espace disponible |
|
||||
| Use% | Pourcentage d'utilisation |
|
||||
| Mounted on | Point de montage (où le disque est accessible) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Niveau 1 : Identifier les gros dossiers à la racine
|
||||
|
||||
```bash
|
||||
sudo du -sh /* 2>/dev/null | sort -h
|
||||
```
|
||||
|
||||
**Explication :**
|
||||
- `du` : **D**isk **U**sage (utilisation disque)
|
||||
- `-s` : **S**ummary (résumé total)
|
||||
- `-h` : **H**uman-readable (Go, Mo au lieu d'octets)
|
||||
- `/*` : Tous les dossiers à la racine
|
||||
- `2>/dev/null` : Masque les erreurs de permission
|
||||
- `sort -h` : Trie par taille humaine (comprend que 10G > 2G)
|
||||
|
||||
**Résultat typique :**
|
||||
```
|
||||
4.0K /mnt
|
||||
128M /boot
|
||||
2.1G /usr
|
||||
15G /var
|
||||
40G /home ← SUSPECT
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Niveau 2 : Descendre dans le dossier suspect
|
||||
|
||||
**Si `/home` est gros :**
|
||||
|
||||
```bash
|
||||
sudo du -sh /home/* | sort -h
|
||||
```
|
||||
|
||||
**Si `/var` est gros :**
|
||||
|
||||
```bash
|
||||
sudo du -sh /var/* | sort -h
|
||||
```
|
||||
|
||||
**Continue à descendre dans l'arborescence :**
|
||||
|
||||
```bash
|
||||
# Exemple : /var/lib est gros
|
||||
sudo du -sh /var/lib/* | sort -h
|
||||
|
||||
# Puis /var/lib/docker est gros
|
||||
sudo du -sh /var/lib/docker/* | sort -h
|
||||
```
|
||||
|
||||
**Astuce :** Garde seulement les 10 plus gros avec `tail -10` :
|
||||
|
||||
```bash
|
||||
sudo du -sh /var/* | sort -h | tail -10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Trouver les plus gros fichiers (top 20)
|
||||
|
||||
```bash
|
||||
sudo find /home -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h | tail -20
|
||||
```
|
||||
|
||||
**Explication :**
|
||||
- `find /home` : Cherche dans /home (change le path selon besoin)
|
||||
- `-type f` : Seulement les fichiers (pas les dossiers)
|
||||
- `-size +100M` : Fichiers de plus de 100 MB
|
||||
- `-exec ls -lh {} \;` : Affiche les détails de chaque fichier trouvé
|
||||
- `sort -k5 -h` : Trie par la 5ème colonne (taille) en mode humain
|
||||
- `tail -20` : Garde les 20 derniers (= les plus gros)
|
||||
|
||||
**Variantes :**
|
||||
|
||||
| Taille | Option |
|
||||
|--------|--------|
|
||||
| Plus de 100 MB | `-size +100M` |
|
||||
| Plus de 500 MB | `-size +500M` |
|
||||
| Plus de 1 GB | `-size +1G` |
|
||||
| Plus de 10 GB | `-size +10G` |
|
||||
|
||||
---
|
||||
|
||||
## 5. Cas particuliers
|
||||
|
||||
### A. Fichiers supprimés mais encore ouverts (fantômes)
|
||||
|
||||
Les fichiers supprimés mais encore ouverts par un processus continuent d'occuper l'espace disque jusqu'à ce que le processus se termine.
|
||||
|
||||
**Identifier les fichiers fantômes :**
|
||||
|
||||
```bash
|
||||
sudo lsof +L1 | grep deleted
|
||||
```
|
||||
|
||||
**Calculer l'espace total occupé :**
|
||||
|
||||
```bash
|
||||
sudo lsof +L1 | grep deleted | awk '{sum+=$7} END {print "Space: " sum/1024/1024/1024 " GB"}'
|
||||
```
|
||||
|
||||
**Solution :** Redémarre le service qui garde les fichiers ouverts :
|
||||
|
||||
```bash
|
||||
# Identifier le processus
|
||||
sudo lsof +L1 | grep deleted
|
||||
|
||||
# Redémarrer le service (exemple avec Docker)
|
||||
docker restart container_name
|
||||
|
||||
# Ou redémarrer un service système
|
||||
sudo systemctl restart service_name
|
||||
```
|
||||
|
||||
### B. Logs système volumineux
|
||||
|
||||
Les logs système peuvent grossir indéfiniment et remplir le disque.
|
||||
|
||||
**Vérifier la taille des logs :**
|
||||
|
||||
```bash
|
||||
sudo journalctl --disk-usage
|
||||
```
|
||||
|
||||
**Nettoyer les logs (garder seulement 500M) :**
|
||||
|
||||
```bash
|
||||
sudo journalctl --vacuum-size=500M
|
||||
```
|
||||
|
||||
**Nettoyer les logs de plus de 7 jours :**
|
||||
|
||||
```bash
|
||||
sudo journalctl --vacuum-time=7d
|
||||
```
|
||||
|
||||
### C. Docker qui prend trop de place
|
||||
|
||||
Docker accumule des images, conteneurs, volumes et cache de build.
|
||||
|
||||
**Voir l'utilisation Docker :**
|
||||
|
||||
```bash
|
||||
docker system df
|
||||
```
|
||||
|
||||
**Exemple de sortie :**
|
||||
```
|
||||
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
||||
Images 10 3 2.935GB 2.719GB (92%)
|
||||
Containers 3 2 110.1MB 0B (0%)
|
||||
Local Volumes 1 0 0B 0B
|
||||
Build Cache 35 0 108.7MB 108.7MB
|
||||
```
|
||||
|
||||
**Nettoyer Docker :**
|
||||
|
||||
⚠️ **ATTENTION :** Cette commande supprime :
|
||||
- Toutes les images non utilisées
|
||||
- Tous les conteneurs arrêtés
|
||||
- Tous les volumes non utilisés
|
||||
- Tout le cache de build
|
||||
|
||||
```bash
|
||||
docker system prune -a --volumes
|
||||
```
|
||||
|
||||
**Nettoyage conservateur (seulement les ressources danglings) :**
|
||||
|
||||
```bash
|
||||
docker system prune
|
||||
```
|
||||
|
||||
### D. Cache APT (paquets téléchargés)
|
||||
|
||||
Les paquets `.deb` téléchargés par APT sont conservés dans le cache.
|
||||
|
||||
**Taille du cache :**
|
||||
|
||||
```bash
|
||||
sudo du -sh /var/cache/apt
|
||||
```
|
||||
|
||||
**Nettoyer :**
|
||||
|
||||
```bash
|
||||
sudo apt clean
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Méthodologie complète (étape par étape)
|
||||
|
||||
Voici la séquence complète pour diagnostiquer un problème d'espace disque :
|
||||
|
||||
```bash
|
||||
# 1. Vue globale - quel disque est plein ?
|
||||
df -h
|
||||
|
||||
# 2. Identifier les gros dossiers à la racine
|
||||
sudo du -sh /* 2>/dev/null | sort -h | tail -10
|
||||
|
||||
# 3. Descendre dans le dossier suspect (exemple : /home)
|
||||
sudo du -sh /home/* | sort -h | tail -10
|
||||
|
||||
# 4. Descendre encore plus profond (exemple : /home/debian)
|
||||
sudo du -sh /home/debian/* | sort -h | tail -10
|
||||
|
||||
# 5. Trouver les gros fichiers individuels
|
||||
sudo find /home/debian -type f -size +100M -exec ls -lh {} \; 2>/dev/null
|
||||
|
||||
# 6. Vérifier les fichiers fantômes (supprimés mais ouverts)
|
||||
sudo lsof +L1 | grep deleted
|
||||
|
||||
# 7. Vérifier les logs système
|
||||
sudo journalctl --disk-usage
|
||||
|
||||
# 8. Vérifier Docker
|
||||
docker system df
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Outil interactif : ncdu (recommandé)
|
||||
|
||||
`ncdu` est un outil interactif qui permet d'explorer visuellement l'espace disque, comme un explorateur de fichiers en mode texte.
|
||||
|
||||
**Installation :**
|
||||
|
||||
```bash
|
||||
sudo apt install ncdu
|
||||
```
|
||||
|
||||
**Utilisation :**
|
||||
|
||||
```bash
|
||||
# Scanner un dossier
|
||||
sudo ncdu /home
|
||||
|
||||
# Scanner depuis la racine (lent sur gros disques)
|
||||
sudo ncdu /
|
||||
```
|
||||
|
||||
**Navigation :**
|
||||
- `↑` `↓` : Se déplacer dans la liste
|
||||
- `Entrée` : Entrer dans un dossier
|
||||
- `←` : Remonter au dossier parent
|
||||
- `d` : Supprimer le fichier/dossier (⚠️ ATTENTION !)
|
||||
- `g` : Afficher en graphique
|
||||
- `?` : Aide
|
||||
- `q` : Quitter
|
||||
|
||||
---
|
||||
|
||||
## 8. Mémo rapide (cheat sheet)
|
||||
|
||||
À garder sous la main pour un diagnostic rapide :
|
||||
|
||||
```bash
|
||||
# Vue globale
|
||||
df -h
|
||||
|
||||
# Top 10 gros dossiers dans un path
|
||||
sudo du -sh /path/* | sort -h | tail -10
|
||||
|
||||
# Top 20 gros fichiers dans un path
|
||||
sudo find /path -type f -size +100M -exec ls -lh {} \; 2>/dev/null | tail -20
|
||||
|
||||
# Fichiers fantômes (supprimés mais ouverts)
|
||||
sudo lsof +L1 | grep deleted
|
||||
|
||||
# Logs système
|
||||
sudo journalctl --disk-usage
|
||||
sudo journalctl --vacuum-size=500M
|
||||
|
||||
# Docker
|
||||
docker system df
|
||||
docker system prune -a --volumes
|
||||
|
||||
# Cache APT
|
||||
sudo apt clean
|
||||
|
||||
# Outil interactif
|
||||
sudo ncdu /
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Exemples de problèmes courants
|
||||
|
||||
### Problème 1 : Cache d'archives Git (Forgejo/GitLab)
|
||||
|
||||
**Symptôme :**
|
||||
```
|
||||
/home/user/forgejo/data/gitea/repo-archive → 48G
|
||||
```
|
||||
|
||||
**Solution :**
|
||||
```bash
|
||||
# Supprimer le cache d'archives
|
||||
sudo rm -rf /home/user/forgejo/data/gitea/repo-archive/*
|
||||
|
||||
# Configurer une expiration automatique dans app.ini
|
||||
[repository.local]
|
||||
ARCHIVE_EXPIRY = 604800 # 7 jours
|
||||
|
||||
# Ajouter un cron de nettoyage quotidien
|
||||
sudo crontab -e
|
||||
# Ajouter : 0 3 * * * find /path/to/repo-archive -type f -mtime +1 -delete
|
||||
```
|
||||
|
||||
### Problème 2 : Logs Docker volumineux
|
||||
|
||||
**Symptôme :**
|
||||
```
|
||||
/var/lib/docker/containers/.../container-json.log → 10G
|
||||
```
|
||||
|
||||
**Solution :**
|
||||
```bash
|
||||
# Limiter la taille des logs Docker
|
||||
sudo nano /etc/docker/daemon.json
|
||||
```
|
||||
|
||||
Ajouter :
|
||||
```json
|
||||
{
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
# Redémarrer Docker
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
### Problème 3 : Base de données SQLite gonflée
|
||||
|
||||
**Symptôme :**
|
||||
```
|
||||
/var/lib/app/database.db → 5G
|
||||
```
|
||||
|
||||
**Solution :**
|
||||
```bash
|
||||
# Vacuum (compacter) la base de données
|
||||
sqlite3 /var/lib/app/database.db "VACUUM;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Prévention
|
||||
|
||||
**Meilleures pratiques pour éviter les disques pleins :**
|
||||
|
||||
1. **Rotation des logs**
|
||||
- Configurer `logrotate` pour limiter la taille des logs
|
||||
- Utiliser `journalctl --vacuum-size=500M`
|
||||
|
||||
2. **Nettoyage automatique**
|
||||
- Ajouter des crons pour nettoyer les caches/tmp
|
||||
- Docker auto-prune régulier
|
||||
|
||||
3. **Monitoring**
|
||||
- Alertes quand le disque dépasse 80%
|
||||
- Vérifier régulièrement `df -h`
|
||||
|
||||
4. **Limites de taille**
|
||||
- Configurer `max-size` pour les logs Docker
|
||||
- Limiter les caches applicatifs
|
||||
|
||||
5. **Stockage externe**
|
||||
- Monter les gros volumes sur des disques séparés
|
||||
- Utiliser du stockage objet (S3) pour les archives
|
||||
|
||||
---
|
||||
|
||||
## Ressources complémentaires
|
||||
|
||||
**Commandes utiles :**
|
||||
|
||||
```bash
|
||||
# Voir les inodes (nombre de fichiers)
|
||||
df -i
|
||||
|
||||
# Trouver les dossiers avec beaucoup de petits fichiers
|
||||
sudo find / -type d -exec sh -c 'echo "$(find "$1" -maxdepth 1 | wc -l) $1"' _ {} \; 2>/dev/null | sort -n | tail -20
|
||||
|
||||
# Voir l'espace utilisé par utilisateur
|
||||
sudo du -sh /home/* | sort -h
|
||||
|
||||
# Monitoring en temps réel
|
||||
watch -n 5 'df -h'
|
||||
```
|
||||
|
||||
**Pages man utiles :**
|
||||
- `man df` - Afficher l'espace disque
|
||||
- `man du` - Calculer l'utilisation disque
|
||||
- `man find` - Rechercher des fichiers
|
||||
- `man lsof` - Lister les fichiers ouverts
|
||||
|
||||
---
|
||||
|
||||
**Guide créé le 2026-02-03**
|
||||
Loading…
Add table
Add a link
Reference in a new issue