- Nouvelle structure : linux-essentials/ et forgejo/ - Nouveau guide : architecture-filesystem.md (comprendre /etc, /var, etc.) - Déplacement et renommage des guides existants - README pour chaque dossier - Suppression des sections auteurs Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1070 lines
27 KiB
Markdown
1070 lines
27 KiB
Markdown
# Guide : Bloquer les téléchargements abusifs sur Forgejo
|
||
|
||
Guide complet pour empêcher les bots de télécharger massivement les archives Git et saturer votre serveur.
|
||
|
||
## Résumé exécutif
|
||
|
||
**Problème :** Des bots téléchargent massivement des archives Git, saturant le disque (47G en 24-48h).
|
||
|
||
**Solution en 3 axes :**
|
||
|
||
| Mesure | Impact | Temps |
|
||
| ------------------------- | ------------------------------------------ | ----- |
|
||
| **Fail2ban durci** | Ban après 8 archives au lieu de 20 | 5 min |
|
||
| **Rate limiting Forgejo** | 20 requêtes/min au lieu de 100 | 5 min |
|
||
| **Expiration rapide** | Archives supprimées après 1h au lieu de 7j | 2 min |
|
||
|
||
**Résultat attendu :** Cache réduit de **47G → 2-3G** maximum.
|
||
|
||
---
|
||
|
||
## Table des matières
|
||
|
||
1. [Comprendre le problème](#1-comprendre-le-problème)
|
||
2. [Solution 1 : Durcir Fail2ban](#2-solution-1--durcir-fail2ban)
|
||
3. [Solution 2 : Désactiver les archives publiques](#3-solution-2--désactiver-les-archives-publiques)
|
||
4. [Solution 3 : Rate limiting dans Forgejo](#4-solution-3--rate-limiting-dans-forgejo)
|
||
5. [Solution 4 : Exiger l'authentification](#5-solution-4--exiger-lauthentification)
|
||
6. [Solution 5 : Rate limiting avec Nginx](#6-solution-5--rate-limiting-avec-nginx)
|
||
7. [Configuration complète recommandée](#7-configuration-complète-recommandée)
|
||
8. [Monitoring et alertes](#8-monitoring-et-alertes)
|
||
|
||
---
|
||
|
||
## 1. Comprendre le problème
|
||
|
||
### Le symptôme
|
||
|
||
Les bots (crawlers, scrapers, scanners de vulnérabilités) téléchargent massivement des archives Git :
|
||
|
||
- `/owner/repo/archive/main.zip`
|
||
- `/owner/repo/archive/branch-name.tar.gz`
|
||
- `/owner/repo/archive/commit-hash.zip`
|
||
|
||
**Impact :**
|
||
|
||
- Le cache `repo-archive` se remplit rapidement (40-50G en 24-48h)
|
||
- Le disque sature (100% d'utilisation)
|
||
- Le serveur devient lent ou inaccessible
|
||
|
||
### Exemple de diagnostic réel
|
||
|
||
```bash
|
||
# Nombre total de fichiers et taille
|
||
find repo-archive -type f | wc -l
|
||
→ 1189 fichiers
|
||
|
||
du -sh repo-archive
|
||
→ 47G
|
||
|
||
# Distribution par date
|
||
find repo-archive -type f -printf '%TY-%Tm-%Td\n' | sort | uniq -c
|
||
→ 676 fichiers créés le 2026-02-03
|
||
→ 513 fichiers créés le 2026-02-04
|
||
|
||
# IP les plus actives
|
||
docker logs forgejo --since 24h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn
|
||
→ 2144 requêtes depuis 216.73.216.118 ← BOT DÉTECTÉ
|
||
```
|
||
|
||
### Pourquoi le nettoyage cron ne suffit pas
|
||
|
||
**Même avec un cron qui supprime les vieux fichiers, le problème persiste :**
|
||
|
||
- Les bots génèrent 40-50G par jour
|
||
- Le cron nettoie une fois par jour ou toutes les 6h
|
||
- Entre deux nettoyages, le disque se remplit quand même
|
||
|
||
**Le cron traite le symptôme, pas la cause.**
|
||
|
||
### La vraie solution
|
||
|
||
**Bloquer les téléchargements abusifs à la source** plutôt que nettoyer après coup :
|
||
|
||
1. Fail2ban bannit les IP abusives rapidement
|
||
2. Rate limiting empêche les téléchargements en masse
|
||
3. Expiration rapide des archives libère l'espace automatiquement
|
||
|
||
---
|
||
|
||
## 2. Solution 1 : Durcir Fail2ban
|
||
|
||
Fail2ban bannit les IP abusives, mais il faut ajuster les paramètres selon votre usage.
|
||
|
||
### Analyser votre configuration actuelle
|
||
|
||
```bash
|
||
sudo cat /etc/fail2ban/jail.d/forgejo.conf
|
||
```
|
||
|
||
**Exemple de configuration trop permissive :**
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
logpath = /var/lib/docker/containers/.../...json.log
|
||
maxretry = 20 # Seuil avant ban
|
||
findtime = 600 # Fenêtre de temps (10 minutes)
|
||
bantime = 3600 # Durée du ban (1 heure)
|
||
```
|
||
|
||
**Calcul de l'impact :**
|
||
|
||
- Une IP peut télécharger **20 archives en 10 minutes** avant d'être bannie
|
||
- Si chaque archive fait ~50 MB → 20 × 50 MB = **1 GB** par IP
|
||
- Une fois bannie, l'IP est débloquée après **1 heure**
|
||
- Le bot peut reprendre et générer 24 GB/jour avec une seule IP
|
||
|
||
**Problème identifié :**
|
||
|
||
- `maxretry = 20` est trop élevé pour des archives volumineuses
|
||
- `bantime = 3600` (1h) est trop court, les bots reviennent rapidement
|
||
|
||
### Configurations recommandées selon votre usage
|
||
|
||
#### Option A : Configuration stricte (serveur personnel/privé)
|
||
|
||
**Pour qui :** Forge personnelle, peu de visiteurs légitimes.
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
logpath = /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
||
|
||
maxretry = 5 # Ban après 5 archives
|
||
findtime = 300 # Dans les 5 dernières minutes
|
||
bantime = 86400 # Ban pour 24h
|
||
```
|
||
|
||
**Impact :** 5 archives max en 5 min = ~250 MB max par IP avant ban.
|
||
|
||
#### Option B : Configuration modérée (serveur public)
|
||
|
||
**Pour qui :** Forge publique avec visiteurs légitimes occasionnels.
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
logpath = /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
||
|
||
maxretry = 10 # Ban après 10 archives
|
||
findtime = 600 # Dans les 10 dernières minutes
|
||
bantime = 14400 # Ban pour 4h
|
||
```
|
||
|
||
**Impact :** 10 archives max en 10 min = ~500 MB max par IP.
|
||
|
||
#### Option C : Configuration équilibrée (RECOMMANDÉ)
|
||
|
||
**Pour qui :** Forge publique avec du trafic légitime, mais protégée contre les abus.
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
logpath = /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
||
|
||
maxretry = 8 # Ban après 8 archives
|
||
findtime = 600 # Dans les 10 dernières minutes
|
||
bantime = 21600 # Ban pour 6h
|
||
```
|
||
|
||
**Impact :** 8 archives max en 10 min = ~400 MB max par IP.
|
||
|
||
### Comment choisir ?
|
||
|
||
| Critère | Stricte (A) | Équilibrée (C) | Modérée (B) |
|
||
| --------------------------- | ----------- | -------------- | ------------ |
|
||
| Trafic légitime attendu | Faible | Moyen | Élevé |
|
||
| Tolérance aux faux positifs | Faible | Moyenne | Élevée |
|
||
| Protection | Maximum | Forte | Moyenne |
|
||
| Serveur type | Personnel | PME/Startup | Public large |
|
||
|
||
**Pour votre cas actuel (maxretry=20)**, je recommande **l'option C (équilibrée)** comme premier ajustement, puis monitorer pendant 48h avant de durcir si nécessaire.
|
||
|
||
### Trouver le CONTAINER_ID de votre conteneur Forgejo
|
||
|
||
Le `logpath` doit pointer vers le fichier de log Docker. Pour trouver le bon chemin :
|
||
|
||
```bash
|
||
# Méthode 1 : Via docker inspect
|
||
docker inspect forgejo --format='{{.LogPath}}'
|
||
|
||
# Méthode 2 : Trouver le conteneur ID
|
||
docker ps | grep forgejo
|
||
# Puis construire le chemin : /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
||
```
|
||
|
||
**Exemple de résultat :**
|
||
|
||
```
|
||
/var/lib/docker/containers/73485bbed075b287c0cb9f21327b1c244bf700d9fdbefb0abac0e3413ee4aa89/73485bbed075b287c0cb9f21327b1c244bf700d9fdbefb0abac0e3413ee4aa89-json.log
|
||
```
|
||
|
||
Copiez ce chemin complet dans votre config Fail2ban.
|
||
|
||
### Ban incrémental pour les récidivistes
|
||
|
||
Pour bannir plus longtemps les IP qui reviennent après un premier ban :
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
# ... config précédente ...
|
||
|
||
# Ban incrémental
|
||
bantime.increment = true
|
||
bantime.factor = 2
|
||
bantime.maxtime = 2592000 # 30 jours max
|
||
```
|
||
|
||
**Signification :**
|
||
|
||
- 1ère offense : durée du `bantime` configuré (ex: 6h)
|
||
- 2ème offense : 12h (6h × 2)
|
||
- 3ème offense : 24h (12h × 2)
|
||
- 4ème offense : 48h (24h × 2)
|
||
- Maximum : 30 jours
|
||
|
||
### Appliquer la configuration
|
||
|
||
**1. Éditer la configuration :**
|
||
|
||
```bash
|
||
sudo nano /etc/fail2ban/jail.d/forgejo.conf
|
||
```
|
||
|
||
**2. Tester la configuration :**
|
||
|
||
```bash
|
||
sudo fail2ban-client -t
|
||
```
|
||
|
||
Si pas d'erreur, la config est valide.
|
||
|
||
**3. Redémarrer Fail2ban :**
|
||
|
||
```bash
|
||
sudo systemctl restart fail2ban
|
||
```
|
||
|
||
**4. Vérifier que la jail est active :**
|
||
|
||
```bash
|
||
sudo fail2ban-client status
|
||
```
|
||
|
||
Vous devriez voir `forgejo-archive` dans la liste des jails.
|
||
|
||
### Vérifier l'efficacité
|
||
|
||
```bash
|
||
sudo fail2ban-client status forgejo-archive
|
||
```
|
||
|
||
**Exemple de sortie saine :**
|
||
|
||
```
|
||
Status for the jail: forgejo-archive
|
||
|- Filter
|
||
| |- Currently failed: 1 ← Tentatives en cours
|
||
| |- Total failed: 3038 ← Total de tentatives détectées
|
||
| `- File list: /var/lib/docker/containers/.../...json.log
|
||
`- Actions
|
||
|- Currently banned: 1 ← IP actuellement bannies
|
||
|- Total banned: 16 ← Total d'IP bannies depuis le démarrage
|
||
`- Banned IP list: 216.73.216.126
|
||
```
|
||
|
||
**Indicateurs de succès :**
|
||
|
||
- `Total banned` augmente régulièrement → Fail2ban fonctionne
|
||
- `Currently banned` > 0 → Des IP sont bloquées en ce moment
|
||
- `Total failed` élevé → Beaucoup de tentatives détectées
|
||
|
||
---
|
||
|
||
## 3. Solution 2 : Désactiver les archives publiques
|
||
|
||
Si vous n'avez pas besoin que les visiteurs non-authentifiés téléchargent des archives, désactivez-les.
|
||
|
||
### Dans Forgejo
|
||
|
||
```bash
|
||
sudo nano /home/debian/forgejo/data/gitea/conf/app.ini
|
||
```
|
||
|
||
Ajouter ou modifier :
|
||
|
||
```ini
|
||
[repository]
|
||
DISABLE_HTTP_GIT = false
|
||
ENABLE_PUSH_CREATE_USER = true
|
||
ENABLE_PUSH_CREATE_ORG = true
|
||
|
||
# Désactiver les téléchargements anonymes d'archives
|
||
DOWNLOAD_METHODS = ssh # Seulement SSH (pas http/https)
|
||
```
|
||
|
||
Ou plus radical :
|
||
|
||
```ini
|
||
[repository]
|
||
# Désactiver complètement les archives
|
||
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true
|
||
```
|
||
|
||
**Redémarrer Forgejo :**
|
||
|
||
```bash
|
||
docker restart forgejo
|
||
```
|
||
|
||
**Impact :**
|
||
|
||
- Les archives ne seront plus disponibles via l'interface web
|
||
- Les utilisateurs devront cloner via `git clone` (plus léger)
|
||
- Le cache `repo-archive` ne se remplira plus
|
||
|
||
---
|
||
|
||
## 4. Solution 3 : Rate limiting dans Forgejo
|
||
|
||
Limiter le nombre de requêtes par IP directement dans Forgejo.
|
||
|
||
### Vérifier votre configuration actuelle
|
||
|
||
```bash
|
||
cat /home/debian/forgejo/data/gitea/conf/app.ini | grep -A5 "\[api\]"
|
||
cat /home/debian/forgejo/data/gitea/conf/app.ini | grep -A5 "\[repository.local\]"
|
||
```
|
||
|
||
**Valeurs problématiques courantes :**
|
||
|
||
| Paramètre | Valeur par défaut | Problème |
|
||
| ------------------------- | ------------------ | --------------------------------------------- |
|
||
| `RATE_LIMIT_BURST = 100` | Souvent trop élevé | Permet 100 requêtes en burst = 5GB instantané |
|
||
| `ARCHIVE_EXPIRY = 604800` | 7 jours | Archives restent 7 jours = cache énorme |
|
||
| Paramètre absent | Pas de limite | Aucune protection |
|
||
|
||
### Configuration recommandée
|
||
|
||
```bash
|
||
nano /home/debian/forgejo/data/gitea/conf/app.ini
|
||
```
|
||
|
||
**Section [api] - Rate limiting global :**
|
||
|
||
```ini
|
||
[api]
|
||
; Activer le rate limiting
|
||
ENABLE_RATE_LIMIT = true
|
||
|
||
; Maximum 20 requêtes en burst (au lieu de 100)
|
||
RATE_LIMIT_BURST = 20
|
||
|
||
; Période de rate limit (60 secondes)
|
||
RATE_LIMIT_PERIOD = 60s
|
||
```
|
||
|
||
**Section [repository.local] - Expiration des archives :**
|
||
|
||
```ini
|
||
[repository.local]
|
||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||
|
||
; Archives expirent après 1 heure (au lieu de 7 jours)
|
||
; 3600 = 1 heure, 86400 = 1 jour, 604800 = 7 jours
|
||
ARCHIVE_EXPIRY = 3600
|
||
```
|
||
|
||
### Explication des valeurs
|
||
|
||
**RATE_LIMIT_BURST = 20 :**
|
||
|
||
- Une IP peut faire **maximum 20 requêtes en burst** (rafale)
|
||
- Si un bot télécharge 20 archives de 50 MB → 1 GB max avant blocage
|
||
- Ensuite, il doit attendre 60 secondes
|
||
|
||
**RATE_LIMIT_PERIOD = 60s :**
|
||
|
||
- La limite se réinitialise toutes les 60 secondes
|
||
- Exemple : Un utilisateur légitime fait 15 requêtes → attend 1 min → peut refaire 20 requêtes
|
||
|
||
**ARCHIVE_EXPIRY = 3600 :**
|
||
|
||
- Les archives générées sont **automatiquement supprimées** après 1 heure
|
||
- Même si un bot génère 10 GB d'archives, elles disparaissent après 1h
|
||
- Le cache ne s'accumule plus indéfiniment
|
||
|
||
### Calcul de l'impact
|
||
|
||
**Avant (exemple de config trop permissive) :**
|
||
|
||
```ini
|
||
RATE_LIMIT_BURST = 100
|
||
ARCHIVE_EXPIRY = 604800 # 7 jours
|
||
```
|
||
|
||
- Un bot génère : 100 archives × 50 MB = **5 GB** instantané
|
||
- Les archives restent **7 jours** : 5 GB × 7 = **35 GB cumulés**
|
||
|
||
**Après (config recommandée) :**
|
||
|
||
```ini
|
||
RATE_LIMIT_BURST = 20
|
||
ARCHIVE_EXPIRY = 3600 # 1 heure
|
||
```
|
||
|
||
- Un bot génère : 20 archives × 50 MB = **1 GB** max
|
||
- Les archives disparaissent après **1h** : **1 GB max en permanence**
|
||
|
||
**Gain : 35 GB → 1 GB = Division par 35**
|
||
|
||
### Redémarrer Forgejo
|
||
|
||
```bash
|
||
docker restart forgejo
|
||
docker logs forgejo --tail 30
|
||
```
|
||
|
||
Vérifiez qu'il n'y a pas d'erreur dans les logs.
|
||
|
||
### Tester le rate limiting
|
||
|
||
**Simuler plusieurs requêtes rapidement (optionnel) :**
|
||
|
||
```bash
|
||
# Depuis votre machine locale
|
||
for i in {1..25}; do curl -I https://forge.studio-variable.com/repo/archive/main.zip; done
|
||
```
|
||
|
||
**Résultat attendu :**
|
||
|
||
- Les 20 premières requêtes passent (code 200)
|
||
- La 21ème et suivantes sont bloquées (code 429 - Too Many Requests)
|
||
|
||
**Note :** Ne testez pas avec des vraies archives si vous ne voulez pas saturer votre serveur. Utilisez plutôt le monitoring pour vérifier que les bots sont limités.
|
||
|
||
---
|
||
|
||
## 5. Solution 4 : Exiger l'authentification
|
||
|
||
Forcer les utilisateurs à se connecter pour télécharger.
|
||
|
||
### Rendre les dépôts privés par défaut
|
||
|
||
```bash
|
||
sudo nano /home/debian/forgejo/data/gitea/conf/app.ini
|
||
```
|
||
|
||
```ini
|
||
[repository]
|
||
DEFAULT_PRIVATE = auto # Les nouveaux repos sont privés
|
||
|
||
[service]
|
||
REQUIRE_SIGNIN_VIEW = false # false = voir les repos publics
|
||
DISABLE_REGISTRATION = false # true = désactiver les inscriptions
|
||
ENABLE_CAPTCHA = true # Captcha pour les inscriptions
|
||
REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = true
|
||
```
|
||
|
||
### Bloquer les archives pour les non-connectés
|
||
|
||
```ini
|
||
[repository]
|
||
# Exiger l'authentification pour télécharger
|
||
FORCE_PRIVATE = false
|
||
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
|
||
|
||
# Mais limiter les téléchargements anonymes
|
||
[server]
|
||
DISABLE_SSH = false
|
||
ENABLE_GZIP = true
|
||
|
||
[service]
|
||
# Empêcher les téléchargements anonymes via une permission
|
||
DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = true
|
||
```
|
||
|
||
**Note :** Cette approche est plus complexe. La solution 2 (désactiver complètement) ou 3 (rate limiting) est plus simple.
|
||
|
||
---
|
||
|
||
## 6. Solution 5 : Rate limiting avec Nginx
|
||
|
||
Si vous utilisez Nginx comme reverse proxy devant Forgejo.
|
||
|
||
### Vérifier si Nginx est utilisé
|
||
|
||
```bash
|
||
sudo systemctl status nginx
|
||
```
|
||
|
||
Si Nginx est actif, configurez le rate limiting :
|
||
|
||
### Configuration Nginx
|
||
|
||
```bash
|
||
sudo nano /etc/nginx/sites-available/forgejo
|
||
```
|
||
|
||
Ajouter dans le bloc `http` :
|
||
|
||
```nginx
|
||
http {
|
||
# Zone de rate limiting pour les archives
|
||
limit_req_zone $binary_remote_addr zone=archive_limit:10m rate=5r/m;
|
||
|
||
# Zone de rate limiting global
|
||
limit_req_zone $binary_remote_addr zone=general_limit:10m rate=30r/s;
|
||
|
||
server {
|
||
server_name git.example.com;
|
||
|
||
# Rate limiting spécifique aux archives
|
||
location ~ /.*/(archive|releases/download)/ {
|
||
limit_req zone=archive_limit burst=3 nodelay;
|
||
limit_req_status 429;
|
||
|
||
proxy_pass http://localhost:3000;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# Rate limiting général
|
||
location / {
|
||
limit_req zone=general_limit burst=50 nodelay;
|
||
|
||
proxy_pass http://localhost:3000;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Explication :**
|
||
|
||
- `rate=5r/m` : Maximum 5 requêtes par minute pour les archives
|
||
- `burst=3` : Autorise un burst de 3 requêtes supplémentaires
|
||
- `rate=30r/s` : Maximum 30 requêtes par seconde pour le reste
|
||
- `limit_req_status 429` : Retourne une erreur 429 (Too Many Requests)
|
||
|
||
### Tester et recharger
|
||
|
||
```bash
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Configuration complète recommandée
|
||
|
||
Plan d'action complet pour sécuriser votre forge en 30 minutes.
|
||
|
||
### Vue d'ensemble de la stratégie
|
||
|
||
**Approche en couches :**
|
||
|
||
1. **Fail2ban** : Bannit les IP abusives automatiquement
|
||
2. **Rate limiting Forgejo** : Limite les requêtes par IP
|
||
3. **Expiration des archives** : Nettoie automatiquement le cache
|
||
4. **Cron de sécurité** : Filet de sécurité en cas de problème
|
||
5. **Monitoring** : Détecte les anomalies
|
||
|
||
---
|
||
|
||
### Étape 1 : Durcir Fail2ban (5 min)
|
||
|
||
**Éditer la configuration :**
|
||
|
||
```bash
|
||
sudo nano /etc/fail2ban/jail.d/forgejo.conf
|
||
```
|
||
|
||
**Remplacer par (configuration équilibrée) :**
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
|
||
# Remplacer CONTAINER_ID par le vrai (voir commande ci-dessous)
|
||
logpath = /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
||
|
||
# Paramètres équilibrés
|
||
maxretry = 8 # Ban après 8 archives
|
||
findtime = 600 # Dans les 10 minutes
|
||
bantime = 21600 # Ban pour 6h
|
||
|
||
# Ban incrémental pour récidivistes
|
||
bantime.increment = true
|
||
bantime.factor = 2
|
||
bantime.maxtime = 604800 # 7 jours max
|
||
```
|
||
|
||
**Trouver le CONTAINER_ID :**
|
||
|
||
```bash
|
||
docker inspect forgejo --format='{{.LogPath}}'
|
||
# Copiez le chemin complet dans logpath
|
||
```
|
||
|
||
**Appliquer :**
|
||
|
||
```bash
|
||
sudo fail2ban-client -t # Tester la config
|
||
sudo systemctl restart fail2ban # Redémarrer
|
||
sudo fail2ban-client status forgejo-archive # Vérifier
|
||
```
|
||
|
||
---
|
||
|
||
### Étape 2 : Configurer le rate limiting dans Forgejo (5 min)
|
||
|
||
**Vérifier d'abord votre config actuelle :**
|
||
|
||
```bash
|
||
cat /home/debian/forgejo/data/gitea/conf/app.ini | grep -A3 "\[api\]"
|
||
cat /home/debian/forgejo/data/gitea/conf/app.ini | grep -A3 "\[repository.local\]"
|
||
```
|
||
|
||
**Valeurs à corriger :**
|
||
|
||
- `RATE_LIMIT_BURST = 100` → Descendre à **20**
|
||
- `ARCHIVE_EXPIRY = 604800` (7 jours) → Descendre à **3600** (1h)
|
||
|
||
**Éditer la configuration Forgejo :**
|
||
|
||
```bash
|
||
nano /home/debian/forgejo/data/gitea/conf/app.ini
|
||
```
|
||
|
||
**Modifier ces sections :**
|
||
|
||
```ini
|
||
[api]
|
||
; Limite globale de requêtes
|
||
ENABLE_RATE_LIMIT = true
|
||
; 20 requêtes maximum par minute par IP (au lieu de 100)
|
||
RATE_LIMIT_BURST = 20
|
||
; Période de rate limit
|
||
RATE_LIMIT_PERIOD = 60s
|
||
|
||
[repository.local]
|
||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||
; Durée de vie du cache d'archives (en secondes)
|
||
; 3600 = 1 heure (au lieu de 604800 = 7 jours)
|
||
ARCHIVE_EXPIRY = 3600
|
||
```
|
||
|
||
**Impact :**
|
||
|
||
- Avant : 100 requêtes possibles → 5 GB en burst, archives restent 7 jours
|
||
- Après : 20 requêtes max → 1 GB max, archives disparaissent après 1h
|
||
- **Gain : Cache divisé par 35**
|
||
|
||
**Appliquer :**
|
||
|
||
```bash
|
||
docker restart forgejo
|
||
docker logs forgejo --tail 50 # Vérifier qu'il n'y a pas d'erreur
|
||
```
|
||
|
||
---
|
||
|
||
### Étape 3 : Cron de nettoyage et alertes (5 min)
|
||
|
||
**Éditer le cron :**
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
**Ajouter ces lignes :**
|
||
|
||
```bash
|
||
# Nettoyage toutes les 6 heures (fichiers de plus de 6h)
|
||
0 */6 * * * find /home/debian/forgejo/data/gitea/repo-archive -type f -mmin +360 -delete
|
||
|
||
# Alerte dans les logs système si repo-archive > 10G
|
||
0 */6 * * * [ $(du -sb /home/debian/forgejo/data/gitea/repo-archive | cut -f1) -gt 10737418240 ] && logger -t forgejo "ALERTE: repo-archive dépasse 10G"
|
||
```
|
||
|
||
**Explication :**
|
||
|
||
- `0 */6 * * *` : Toutes les 6 heures (00:00, 06:00, 12:00, 18:00)
|
||
- `-mmin +360` : Fichiers de plus de 360 minutes (6h)
|
||
- `logger -t forgejo` : Écrit dans les logs système (visible avec `journalctl`)
|
||
|
||
**Vérifier que le cron est enregistré :**
|
||
|
||
```bash
|
||
sudo crontab -l
|
||
```
|
||
|
||
---
|
||
|
||
### Étape 4 : Vérification immédiate (5 min)
|
||
|
||
**Vérifier que tout fonctionne :**
|
||
|
||
```bash
|
||
# 1. Fail2ban actif ?
|
||
sudo fail2ban-client status forgejo-archive
|
||
|
||
# 2. Forgejo a bien redémarré ?
|
||
docker ps | grep forgejo
|
||
docker logs forgejo --tail 20
|
||
|
||
# 3. Taille actuelle du cache
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
|
||
# 4. IP les plus actives (devrait être limité maintenant)
|
||
docker logs forgejo --since 1h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5
|
||
```
|
||
|
||
---
|
||
|
||
### Étape 5 : Nettoyage initial (optionnel)
|
||
|
||
Si le cache est déjà saturé, nettoyez-le maintenant :
|
||
|
||
```bash
|
||
# Voir ce qui sera supprimé
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f | wc -l
|
||
|
||
# ATTENTION : Supprime tous les fichiers d'archives
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f -delete
|
||
|
||
# Vérifier
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Monitoring et alertes
|
||
|
||
### Tableau de bord quotidien (5 min)
|
||
|
||
**Commandes à exécuter chaque jour pour surveiller :**
|
||
|
||
```bash
|
||
# 1. Taille du cache (devrait rester < 10G)
|
||
echo "=== Taille du cache ==="
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
|
||
# 2. Nombre de fichiers (devrait baisser ou stagner)
|
||
echo "=== Nombre de fichiers ==="
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f | wc -l
|
||
|
||
# 3. IP bannies actuellement
|
||
echo "=== Fail2ban status ==="
|
||
sudo fail2ban-client status forgejo-archive | grep -E "Currently banned|Total banned"
|
||
|
||
# 4. Top 5 IP des dernières 24h
|
||
echo "=== Top 5 IP (24h) ==="
|
||
docker logs forgejo --since 24h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5
|
||
|
||
# 5. Nombre total de téléchargements d'archives (24h)
|
||
echo "=== Total archives (24h) ==="
|
||
docker logs forgejo --since 24h | grep "archive" | wc -l
|
||
```
|
||
|
||
**Créer un script de monitoring :**
|
||
|
||
```bash
|
||
sudo nano /usr/local/bin/forgejo-daily-check.sh
|
||
```
|
||
|
||
**Contenu :**
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
|
||
echo "============================================"
|
||
echo "Forgejo Health Check - $(date)"
|
||
echo "============================================"
|
||
|
||
# Taille cache
|
||
CACHE_SIZE=$(du -sb /home/debian/forgejo/data/gitea/repo-archive | cut -f1)
|
||
CACHE_SIZE_GB=$((CACHE_SIZE / 1073741824))
|
||
echo "Cache size: ${CACHE_SIZE_GB}G"
|
||
|
||
# Nombre de fichiers
|
||
FILE_COUNT=$(find /home/debian/forgejo/data/gitea/repo-archive -type f | wc -l)
|
||
echo "Files in cache: ${FILE_COUNT}"
|
||
|
||
# Fail2ban
|
||
BANNED=$(sudo fail2ban-client status forgejo-archive | grep "Currently banned" | awk '{print $4}')
|
||
TOTAL_BANNED=$(sudo fail2ban-client status forgejo-archive | grep "Total banned" | awk '{print $4}')
|
||
echo "Currently banned IPs: ${BANNED}"
|
||
echo "Total banned since start: ${TOTAL_BANNED}"
|
||
|
||
# Top IP
|
||
echo ""
|
||
echo "Top 5 IP (last 24h):"
|
||
docker logs forgejo --since 24h 2>/dev/null | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5
|
||
|
||
# Alertes
|
||
echo ""
|
||
if [ $CACHE_SIZE_GB -gt 10 ]; then
|
||
echo "⚠️ WARNING: Cache > 10G"
|
||
fi
|
||
|
||
if [ $BANNED -gt 5 ]; then
|
||
echo "⚠️ WARNING: ${BANNED} IPs currently banned (possible attack ongoing)"
|
||
fi
|
||
|
||
if [ $FILE_COUNT -gt 500 ]; then
|
||
echo "⚠️ WARNING: More than 500 files in cache"
|
||
fi
|
||
|
||
echo "============================================"
|
||
```
|
||
|
||
**Rendre exécutable :**
|
||
|
||
```bash
|
||
sudo chmod +x /usr/local/bin/forgejo-daily-check.sh
|
||
```
|
||
|
||
**Tester :**
|
||
|
||
```bash
|
||
sudo /usr/local/bin/forgejo-daily-check.sh
|
||
```
|
||
|
||
**Ajouter au cron quotidien (optionnel) :**
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
Ajouter :
|
||
|
||
```bash
|
||
0 8 * * * /usr/local/bin/forgejo-daily-check.sh
|
||
```
|
||
|
||
### Script de monitoring quotidien
|
||
|
||
```bash
|
||
sudo nano /usr/local/bin/forgejo-health-check.sh
|
||
```
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
|
||
CACHE_SIZE=$(du -sb /home/debian/forgejo/data/gitea/repo-archive | cut -f1)
|
||
CACHE_SIZE_GB=$((CACHE_SIZE / 1073741824))
|
||
|
||
BANNED_IPS=$(sudo fail2ban-client status forgejo-archive | grep "Currently banned" | awk '{print $4}')
|
||
|
||
echo "=== Forgejo Health Check - $(date) ==="
|
||
echo "Cache size: ${CACHE_SIZE_GB}G"
|
||
echo "Banned IPs: ${BANNED_IPS}"
|
||
|
||
if [ $CACHE_SIZE_GB -gt 10 ]; then
|
||
echo "⚠️ WARNING: Cache > 10G"
|
||
fi
|
||
|
||
if [ $BANNED_IPS -gt 5 ]; then
|
||
echo "⚠️ WARNING: ${BANNED_IPS} IPs banned (possible attack)"
|
||
fi
|
||
```
|
||
|
||
**Rendre exécutable :**
|
||
|
||
```bash
|
||
sudo chmod +x /usr/local/bin/forgejo-health-check.sh
|
||
```
|
||
|
||
**Ajouter au cron (tous les jours à 8h) :**
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
```bash
|
||
0 8 * * * /usr/local/bin/forgejo-health-check.sh | mail -s "Forgejo Health" admin@example.com
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Cas pratiques
|
||
|
||
### Cas 1 : Serveur personnel (peu de trafic)
|
||
|
||
**Configuration recommandée :**
|
||
|
||
- Fail2ban strict (maxretry=10, bantime=86400)
|
||
- Rate limiting Forgejo activé
|
||
- Cron de nettoyage toutes les 6h
|
||
|
||
### Cas 2 : Serveur public (beaucoup de trafic légitime)
|
||
|
||
**Configuration recommandée :**
|
||
|
||
- Fail2ban modéré (maxretry=30, bantime=3600)
|
||
- Rate limiting Nginx (permet plus de flexibilité)
|
||
- Monitoring actif
|
||
|
||
### Cas 3 : Serveur privé (équipe restreinte)
|
||
|
||
**Configuration recommandée :**
|
||
|
||
- Désactiver les archives publiques complètement
|
||
- Exiger l'authentification pour tout
|
||
- Fail2ban très strict
|
||
|
||
---
|
||
|
||
## 10. Diagnostic en cas de problème persistant
|
||
|
||
Si le disque se remplit encore :
|
||
|
||
```bash
|
||
# 1. Identifier les IP actives
|
||
docker logs forgejo --since 6h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5
|
||
|
||
# 2. Vérifier si Fail2ban a banni
|
||
sudo fail2ban-client status forgejo-archive
|
||
|
||
# 3. Vérifier l'âge des fichiers
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f -printf '%TY-%Tm-%Td %TH:%TM\n' | sort | tail -20
|
||
|
||
# 4. Bannir manuellement si nécessaire
|
||
sudo fail2ban-client set forgejo-archive banip IP_SUSPECTE
|
||
|
||
# 5. Nettoyage d'urgence
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f -delete
|
||
```
|
||
|
||
---
|
||
|
||
## Ressources complémentaires
|
||
|
||
**Documentation officielle :**
|
||
|
||
- Forgejo Configuration: https://forgejo.org/docs/latest/admin/config-cheat-sheet/
|
||
- Fail2ban Manual: https://www.fail2ban.org/wiki/index.php/Main_Page
|
||
- Nginx Rate Limiting: https://www.nginx.com/blog/rate-limiting-nginx/
|
||
|
||
**Outils utiles :**
|
||
|
||
- `goaccess` : Analyseur de logs web en temps réel
|
||
- `iptables` : Firewall Linux
|
||
- `htop` : Monitoring des ressources
|
||
|
||
---
|
||
|
||
## 11. Guide de démarrage rapide (15 min chrono)
|
||
|
||
Pour ceux qui veulent appliquer la solution immédiatement sans lire tout le guide.
|
||
|
||
### Étape 1 : Durcir Fail2ban (3 min)
|
||
|
||
```bash
|
||
# Éditer la config
|
||
sudo nano /etc/fail2ban/jail.d/forgejo.conf
|
||
```
|
||
|
||
**Remplacer `maxretry = 20` par `maxretry = 8` et `bantime = 3600` par `bantime = 21600` :**
|
||
|
||
```ini
|
||
[forgejo-archive]
|
||
enabled = true
|
||
filter = forgejo-archive
|
||
logpath = /var/lib/docker/containers/73485bb.../73485bb...-json.log
|
||
maxretry = 8
|
||
findtime = 600
|
||
bantime = 21600
|
||
bantime.increment = true
|
||
bantime.factor = 2
|
||
bantime.maxtime = 604800
|
||
```
|
||
|
||
```bash
|
||
# Redémarrer
|
||
sudo systemctl restart fail2ban
|
||
sudo fail2ban-client status forgejo-archive
|
||
```
|
||
|
||
### Étape 2 : Configurer Forgejo (3 min)
|
||
|
||
```bash
|
||
nano /home/debian/forgejo/data/gitea/conf/app.ini
|
||
```
|
||
|
||
**Modifier ces valeurs :**
|
||
|
||
- `RATE_LIMIT_BURST = 100` → `RATE_LIMIT_BURST = 20`
|
||
- `ARCHIVE_EXPIRY = 604800` → `ARCHIVE_EXPIRY = 3600`
|
||
|
||
```bash
|
||
# Redémarrer
|
||
docker restart forgejo
|
||
```
|
||
|
||
### Étape 3 : Améliorer le cron (2 min)
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
**Remplacer la ligne existante par :**
|
||
|
||
```bash
|
||
0 */6 * * * find /home/debian/forgejo/data/gitea/repo-archive -type f -mmin +360 -delete
|
||
```
|
||
|
||
### Étape 4 : Nettoyage initial (2 min)
|
||
|
||
```bash
|
||
# Voir la taille actuelle
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
|
||
# Nettoyer
|
||
find /home/debian/forgejo/data/gitea/repo-archive -type f -delete
|
||
|
||
# Vérifier
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
```
|
||
|
||
### Étape 5 : Vérification (5 min)
|
||
|
||
```bash
|
||
# Check Fail2ban
|
||
sudo fail2ban-client status forgejo-archive
|
||
|
||
# Check cache (devrait être vide ou petit)
|
||
du -sh /home/debian/forgejo/data/gitea/repo-archive
|
||
|
||
# Check IP actives
|
||
docker logs forgejo --since 1h | grep "archive" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | head -5
|
||
```
|
||
|
||
### Monitoring quotidien
|
||
|
||
**Script de vérification quotidienne :**
|
||
|
||
```bash
|
||
sudo nano /usr/local/bin/forgejo-check.sh
|
||
```
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
echo "Cache: $(du -sh /home/debian/forgejo/data/gitea/repo-archive | cut -f1)"
|
||
echo "Banned: $(sudo fail2ban-client status forgejo-archive | grep "Currently banned" | awk '{print $4}')"
|
||
docker logs forgejo --since 24h | grep "archive" | wc -l | xargs echo "Archives (24h):"
|
||
```
|
||
|
||
```bash
|
||
sudo chmod +x /usr/local/bin/forgejo-check.sh
|
||
/usr/local/bin/forgejo-check.sh
|
||
```
|