# [COURS] EXERCICES CORRIGÉS FTP/FTPS - ULTRA DÉTAILLÉS

## [LIVRE] INTRODUCTION

Ce document contient **5 exercices pratiques corrigés** sur FTP/FTPS (File Transfer Protocol), allant du niveau débutant au niveau expert. Chaque exercice est conçu pour :

- **Renforcer** tes compétences en transfert de fichiers
- **Consolider** les concepts théoriques
- **Simuler** des situations réelles en entreprise
- **Te préparer** à des projets professionnels

**Niveau de progression :**
- [VERT] Exercice 1 : Débutant - Installation et configuration de base
- [JAUNE] Exercice 2 : Intermédiaire - Utilisateurs virtuels et chroot
- [JAUNE] Exercice 3 : Intermédiaire - FTPS (FTP sécurisé avec SSL/TLS)
- [ROUGE] Exercice 4 : Avancé - FTP passif, NAT et automatisation
- [ROUGE] Exercice 5 : Expert - Sécurisation complète et audit

**Chaque exercice contient :**
- [OK] Énoncé détaillé avec contexte professionnel
- [OK] Prérequis et objectifs pédagogiques
- [OK] Solution complète étape par étape
- [OK] Code commenté ligne par ligne
- [OK] Explications théoriques approfondies
- [OK] Tests de validation
- [OK] Erreurs courantes et solutions
- [OK] Points clés à retenir
- [OK] Pour aller plus loin

**Technologies couvertes :**
- vsftpd (Very Secure FTP Daemon)
- ProFTPD (alternative)
- OpenSSL pour FTPS
- PAM (Pluggable Authentication Modules)
- iptables/ufw pour le firewall
- Fail2Ban pour la protection
- Scripts d'automatisation

**Conseils avant de commencer :**
1. Lis l'énoncé en entier avant de commencer
2. Essaie de résoudre par toi-même avant de regarder la solution
3. Tape chaque commande manuellement (pas de copier-coller aveugle)
4. Teste à chaque étape pour vérifier que ça fonctionne
5. Prends des notes sur ce que tu apprends
6. Sauvegarde tes configurations avant modifications

**Environnement recommandé :**
- Ubuntu 22.04 LTS ou Debian 12
- Machine virtuelle ou serveur dédié
- Client FTP : FileZilla, lftp, ou ftp
- Accès root ou sudo

**Bon courage ! [RAPIDE]**

---

---

# [VERT] EXERCICE 1 : INSTALLATION ET CONFIGURATION DE BASE DE VSFTPD

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système dans une PME. L'équipe de développement a besoin d'un serveur FTP pour échanger des fichiers de développement (code source, documentation, médias). 

Le responsable technique te demande de mettre en place un serveur FTP simple mais fonctionnel qui permet :
- Aux utilisateurs Linux existants de se connecter avec leurs identifiants
- D'avoir un répertoire personnel pour chaque utilisateur
- De pouvoir télécharger (download) et envoyer (upload) des fichiers
- D'avoir des logs pour le suivi

### Cahier des charges

**Fonctionnalités requises :**
- Serveur FTP accessible en local (pour commencer)
- Authentification avec les comptes utilisateurs Linux
- Upload/Download activés
- Logs détaillés des connexions et transferts
- Pas d'accès anonyme

**Contraintes techniques :**
- Utiliser vsftpd (Very Secure FTP Daemon)
- Ubuntu 22.04 LTS ou Debian 12
- Configuration sécurisée de base
- Tests avec client FileZilla
- Temps estimé : 1-2 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Installer vsftpd sur Linux
- [OK] Comprendre l'architecture FTP (ports, modes actif/passif)
- [OK] Configurer vsftpd pour les utilisateurs locaux
- [OK] Gérer les permissions de fichiers pour FTP
- [OK] Lire et interpréter les logs FTP
- [OK] Tester une connexion FTP avec différents clients
- [OK] Diagnostiquer les problèmes de base

---

## [DOCS] PRÉREQUIS

- Serveur Linux (Ubuntu/Debian) installé
- Accès root ou sudo
- Notions de base Linux (utilisateurs, permissions)
- Compréhension du modèle client-serveur

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Comprendre le protocole FTP

**Avant d'installer quoi que ce soit, comprenons comment FonctiONNE FTP.**

#### Qu'est-ce que FTP ?

**FTP** = File Transfer Protocol (Protocole de Transfert de Fichiers)

**Créé en 1971** (un des plus vieux protocoles d'Internet !)

**Rôle :** Transférer des fichiers entre un client et un serveur

**Analogie :**
- FTP = Un camion de déménagement pour fichiers
- Le client = Toi qui demandes le déménagement
- Le serveur = L'entrepôt qui stocke les fichiers

---

#### Architecture FTP : 2 canaux de communication

**FTP utilise DEUX connexions TCP simultanées :**

**1. Canal de contrôle (Command Channel)**
- **Port 21** (par défaut)
- Transporte les **commandes** et les **réponses**
- Reste ouvert pendant toute la session
- Exemples de commandes :
  - `USER` : Nom d'utilisateur
  - `PASS` : Mot de passe
  - `LIST` : Lister les fichiers
  - `RETR` : Télécharger un fichier
  - `STOR` : Envoyer un fichier
  - `QUIT` : Fermer la connexion

**2. Canal de données (Data Channel)**
- **Port 20** (mode actif) ou **port aléatoire** (mode passif)
- Transporte les **données** (contenu des fichiers, listes de fichiers)
- Ouvert seulement pendant les transferts
- Se ferme après chaque transfert

**Schéma :**

```
Client FTP                    Serveur FTP
    │                              │
    ├──────[BLACK_RIGHT-POINTING_POINTER] Port 21 ──────────────┤  Canal de contrôle
    │     (Commandes/Réponses)     │  (persiste)
    │                              │
    ├──────[BLACK_RIGHT-POINTING_POINTER] Port 20 ou random ────┤  Canal de données
    │     (Transfert fichiers)     │  (temporaire)
    │                              │
```

---

#### Mode ACTIF vs Mode PASSIF

**C'est LA source de confusion #1 avec FTP ! Comprends bien cette différence.**

**MODE ACTIF (Active Mode) :**

```
1. Client se connecte au serveur sur le port 21
2. Client dit "Je suis prêt, contacte-moi sur mon port X"
3. SERVEUR initie la connexion de données vers le CLIENT

Client                    Serveur
  │                          │
  ├─────[BLACK_RIGHT-POINTING_POINTER] PORT 21 ──────────[BLACK_RIGHT-POINTING_POINTER]│ Connexion contrôle
  │                          │
  │[BLACK_LEFT-POINTING_POINTER]──────── PORT 20 ────────┤ Serveur SE CONNECTE au client
  │                          │
```

**Problème du mode actif :**
- Le serveur doit pouvoir **SE CONNECTER** au client
- [X] Bloqué par les firewalls côté client (NAT, routeurs)
- [X] Le client est souvent derrière un routeur (IP privée)

**Résultat : Mode actif ne fonctionne presque jamais aujourd'hui !**

---

**MODE PASSIF (Passive Mode) :**

```
1. Client se connecte au serveur sur le port 21
2. Client dit "Je veux le mode passif"
3. Serveur répond "OK, connecte-toi sur mon port Y"
4. CLIENT initie la connexion de données vers le SERVEUR

Client                    Serveur
  │                          │
  ├─────[BLACK_RIGHT-POINTING_POINTER] PORT 21 ──────────[BLACK_RIGHT-POINTING_POINTER]│ Connexion contrôle
  │                          │
  ├─────[BLACK_RIGHT-POINTING_POINTER] PORT random ──────[BLACK_RIGHT-POINTING_POINTER]│ Client SE CONNECTE au serveur
  │                          │
```

**Avantage du mode passif :**
- [OK] C'est le CLIENT qui initie les deux connexions
- [OK] Fonctionne derrière un firewall/NAT côté client
- [OK] C'est le mode par défaut de FileZilla et autres clients modernes

**Problème du mode passif :**
- Le serveur doit ouvrir une **plage de ports** (ex: 40000-50000)
- Nécessite configuration firewall côté serveur

**-> En production, on utilise TOUJOURS le mode passif !**

---

#### Codes de réponse FTP

Le serveur FTP répond avec des **codes numériques à 3 chiffres** :

| Code | Catégorie | Signification | Exemple |
|------|-----------|---------------|---------|
| **1xx** | Préliminaire | Action commencée, attends | 150 File status okay |
| **2xx** | Succès | Commande exécutée | 200 Command okay |
| **3xx** | Info supplémentaire | Besoin d'info en plus | 331 User name okay, need password |
| **4xx** | Erreur temporaire | Réessayer plus tard | 421 Service not available |
| **5xx** | Erreur permanente | Commande incorrecte | 530 Not logged in |

**Exemples concrets :**

```
220 (Service ready)               -> Serveur prêt à accepter des connexions
331 (User name okay, need password) -> User OK, envoie le mot de passe
230 (User logged in)              -> Authentification réussie
550 (File unavailable)            -> Fichier introuvable
```

---

#### Commandes FTP essentielles

| Commande | Description | Exemple |
|----------|-------------|---------|
| **USER** | Nom d'utilisateur | `USER john` |
| **PASS** | Mot de passe | `PASS secret123` |
| **PWD** | Afficher répertoire actuel | `PWD` -> `/home/john` |
| **CWD** | Changer de répertoire | `CWD /documents` |
| **LIST** | Lister fichiers | `LIST` |
| **RETR** | Télécharger (retrieve) | `RETR file.txt` |
| **STOR** | Envoyer (store) | `STOR newfile.txt` |
| **DELE** | Supprimer | `DELE oldfile.txt` |
| **MKD** | Créer dossier | `MKD newfolder` |
| **RMD** | Supprimer dossier | `RMD oldfolder` |
| **QUIT** | Déconnexion | `QUIT` |
| **PASV** | Activer mode passif | `PASV` |

---

#### Pourquoi vsftpd ?

**vsftpd** = Very Secure FTP Daemon

**Alternatives :**

| Serveur FTP | Points forts | Points faibles |
|-------------|--------------|----------------|
| **vsftpd** | * Très sécurisé, rapide, simple | Configuration basique |
| **ProFTPD** | Très configurable, modules | Plus complexe |
| **Pure-FTPd** | Facile, pas de fichier config | Moins de fonctionnalités |
| **wu-ftpd** | Historique | [X] Obsolète, failles de sécurité |

**Pourquoi vsftpd pour cet exercice ?**
- [OK] Sécurisé par défaut (d'où le nom)
- [OK] Performant (peut gérer 10 000+ connexions)
- [OK] Simple à configurer
- [OK] Bien maintenu
- [OK] Standard sur Ubuntu/Debian

---

### ÉTAPE 2 : Installer vsftpd

```bash
# Mettre à jour la liste des paquets
sudo apt update

# Installer vsftpd
sudo apt install vsftpd -y
```

**Résultat :**

```
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  vsftpd
0 upgraded, 1 newly installed, 0 to remove
```

**[OK] vsftpd installé !**

---

**Vérifier que vsftpd tourne :**

```bash
sudo systemctl status vsftpd
```

**Résultat :**

```
[BLACK_CIRCLE] vsftpd.service - vsftpd FTP server
     Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-12-16 10:00:00 UTC; 1min ago
   Main PID: 12345 (vsftpd)
      Tasks: 1 (limit: 4915)
     Memory: 1.2M
        CPU: 50ms
```

**[OK] Service actif et en cours d'exécution !**

---

**Vérifier que vsftpd écoute sur le port 21 :**

```bash
sudo netstat -tulpn | grep :21
```

**Ou avec `ss` (plus moderne) :**

```bash
sudo ss -tulpn | grep :21
```

**Résultat :**

```
tcp   LISTEN 0   32   *:21   *:*   users:(("vsftpd",pid=12345,fd=3))
```

**Explication :**
- `tcp` = Protocole TCP
- `LISTEN` = En écoute (attend des connexions)
- `0` = Pas de connexions en attente
- `32` = Backlog (file d'attente max)
- `*:21` = Écoute sur TOUTES les interfaces, port 21
- `*:*` = Accepte connexions de n'importe où
- `vsftpd` = Nom du processus
- `pid=12345` = ID du processus

**[OK] vsftpd écoute bien sur le port 21 !**

---

### ÉTAPE 3 : Sauvegarder la configuration par défaut

**TOUJOURS sauvegarder avant de modifier !**

```bash
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.backup
```

**Vérifier la sauvegarde :**

```bash
ls -lh /etc/vsftpd.conf*
```

**Résultat :**

```
-rw-r--r-- 1 root root 5.5K Dec 16 10:00 /etc/vsftpd.conf
-rw-r--r-- 1 root root 5.5K Dec 16 10:01 /etc/vsftpd.conf.backup
```

**[OK] Backup créé !**

---

### ÉTAPE 4 : Créer des utilisateurs de test

**Créons 2 utilisateurs pour tester FTP :**

```bash
# Créer l'utilisateur ftpuser1
sudo useradd -m -s /bin/bash ftpuser1

# Définir un mot de passe
sudo passwd ftpuser1
```

**Entre un mot de passe :** `FtpPass123!`

**Explication de `useradd` :**

**`useradd`** = Créer un utilisateur Linux

**`-m`** = Create home directory (créer /home/ftpuser1)

**`-s /bin/bash`** = Shell par défaut

**Sans `-m`, aucun répertoire home ne serait créé !**

---

**Créer le deuxième utilisateur :**

```bash
sudo useradd -m -s /bin/bash ftpuser2
sudo passwd ftpuser2
```

**Mot de passe :** `FtpPass456!`

---

**Vérifier que les répertoires home existent :**

```bash
ls -ld /home/ftpuser1 /home/ftpuser2
```

**Résultat :**

```
drwxr-x--- 2 ftpuser1 ftpuser1 4096 Dec 16 10:05 /home/ftpuser1
drwxr-x--- 2 ftpuser2 ftpuser2 4096 Dec 16 10:05 /home/ftpuser2
```

**Permissions `drwxr-x---` :**
- `d` = Directory (répertoire)
- `rwx` = Propriétaire (ftpuser1) : lecture, écriture, exécution
- `r-x` = Groupe (ftpuser1) : lecture, exécution
- `---` = Autres : aucun accès

**[OK] Utilisateurs créés avec leurs répertoires home !**

---

**Créer quelques fichiers de test :**

```bash
# Dans le home de ftpuser1
sudo su - ftpuser1 -c "echo 'Fichier test 1' > ~/test1.txt"
sudo su - ftpuser1 -c "echo 'Document confidentiel' > ~/confidentiel.txt"
sudo su - ftpuser1 -c "mkdir ~/documents"
sudo su - ftpuser1 -c "echo 'Document important' > ~/documents/important.txt"
```

**Explication de `sudo su - ftpuser1 -c "..."`** :

**`sudo su`** = Switch User (changer d'utilisateur)

**`-`** = Charge l'environnement complet de l'utilisateur

**`ftpuser1`** = Utilisateur cible

**`-c "..."`** = Execute command (exécuter une commande)

**Résultat : La commande s'exécute en tant que ftpuser1**

---

**Vérifier les fichiers créés :**

```bash
sudo ls -lh /home/ftpuser1/
```

**Résultat :**

```
drwxr-xr-x 2 ftpuser1 ftpuser1 4.0K Dec 16 10:10 documents
-rw-r--r-- 1 ftpuser1 ftpuser1   23 Dec 16 10:10 confidentiel.txt
-rw-r--r-- 1 ftpuser1 ftpuser1   16 Dec 16 10:10 test1.txt
```

**[OK] Fichiers de test créés !**

---

### ÉTAPE 5 : Configurer vsftpd pour les utilisateurs locaux

**Éditer le fichier de configuration :**

```bash
sudo nano /etc/vsftpd.conf
```

**Chercher et modifier/ajouter ces lignes :**

```conf
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION VSFTPD - UTILISATEURS LOCAUX
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# ÉCOUTE ET CONNEXIONS
# ───────────────────────────────────────────────────────────────

# Exécuter vsftpd en mode standalone (pas via inetd/xinetd)
listen=YES

# NE PAS écouter en IPv6 (sinon conflit avec listen=YES)
listen_ipv6=NO

# Explication :
# listen=YES signifie que vsftpd tourne comme un service permanent
# Alternative : listen=NO et utiliser inetd/xinetd (obsolète)
# 
# listen_ipv6=NO car on ne peut pas avoir les deux en même temps
# Si tu veux IPv6 : listen=NO et listen_ipv6=YES

# ───────────────────────────────────────────────────────────────
# ACCÈS ANONYME (DÉSACTIVÉ)
# ───────────────────────────────────────────────────────────────

# Désactiver l'accès anonyme (sans authentification)
anonymous_enable=NO

# Explication :
# anonymous_enable=YES permettrait à n'importe qui de se connecter
# avec l'utilisateur "anonymous" et un email comme mot de passe
# 
# [X] DANGEREUX en production !
# Utilisé seulement pour des serveurs publics de téléchargement
# (ex: mirrors Linux)

# ───────────────────────────────────────────────────────────────
# UTILISATEURS LOCAUX (ACTIVÉ)
# ───────────────────────────────────────────────────────────────

# Autoriser les utilisateurs locaux Linux à se connecter
local_enable=YES

# Explication :
# local_enable=YES permet aux utilisateurs du système (/etc/passwd)
# de se connecter avec leur login/password Linux
# 
# ftpuser1 (créé avec useradd) peut se connecter via FTP
# 
# Sans cette option, PERSONNE ne peut se connecter
# (sauf si anonymous_enable=YES)

# ───────────────────────────────────────────────────────────────
# PERMISSIONS D'ÉCRITURE
# ───────────────────────────────────────────────────────────────

# Autoriser les commandes d'écriture (STOR, DELE, MKD, etc.)
write_enable=YES

# Explication :
# write_enable=YES permet :
# - Upload de fichiers (STOR)
# - Suppression de fichiers (DELE)
# - Création de dossiers (MKD)
# - Renommage (RNFR/RNTO)
# 
# write_enable=NO = Mode lecture seule (download uniquement)
# 
# En production, souvent NO sauf pour des utilisateurs spécifiques

# ───────────────────────────────────────────────────────────────
# UMASK (PERMISSIONS DES FICHIERS CRÉÉS)
# ───────────────────────────────────────────────────────────────

# Umask pour les fichiers uploadés
local_umask=022

# Explication COMPLÈTE de l'umask :
# 
# Umask = Masque inversé pour les permissions par défaut
# 
# Permissions par défaut sans umask :
# - Fichiers : 666 (rw-rw-rw-)
# - Dossiers : 777 (rwxrwxrwx)
# 
# Umask 022 signifie : Retirer 022 des permissions par défaut
# 
# Pour les FICHIERS :
# 666 (base)
# -022 (umask)
# ────
# 644 (résultat) = rw-r--r--
# 
# Propriétaire : rw- (lecture + écriture)
# Groupe : r-- (lecture seule)
# Autres : r-- (lecture seule)
# 
# Pour les DOSSIERS :
# 777 (base)
# -022 (umask)
# ────
# 755 (résultat) = rwxr-xr-x
# 
# Propriétaire : rwx (tout)
# Groupe : r-x (lecture + traversée)
# Autres : r-x (lecture + traversée)
# 
# Exemples d'autres umask :
# 
# umask=077 -> Fichiers 600, Dossiers 700
# (Personne d'autre ne peut rien faire)
# 
# umask=002 -> Fichiers 664, Dossiers 775
# (Groupe peut écrire)
# 
# umask=027 -> Fichiers 640, Dossiers 750
# (Groupe lecture, autres rien)

# ───────────────────────────────────────────────────────────────
# MESSAGES ET BANNIÈRES
# ───────────────────────────────────────────────────────────────

# Message de bienvenue (bannière)
ftpd_banner=Bienvenue sur le serveur FTP de l'entreprise

# Explication :
# Message affiché lors de la connexion AVANT authentification
# 
# Exemple de ce que voit l'utilisateur :
# $ ftp 192.168.1.100
# Connected to 192.168.1.100.
# 220 Bienvenue sur le serveur FTP de l'entreprise
# Name (192.168.1.100:user):
# 
# [ATTENTION] Ne pas révéler d'infos sensibles dans la bannière !
# (version, OS, etc.)

# Afficher un message depuis un fichier (optionnel)
# dirmessage_enable=YES
# message_file=.message

# Explication :
# Si activé, affiche le contenu du fichier .message
# quand l'utilisateur entre dans un répertoire
# 
# Utile pour laisser des instructions ou avertissements

# ───────────────────────────────────────────────────────────────
# LOGS ET MONITORING
# ───────────────────────────────────────────────────────────────

# Activer les logs des connexions
xferlog_enable=YES

# Fichier de log standard
xferlog_file=/var/log/vsftpd.log

# Format de log standard (compatible avec wu-ftpd)
xferlog_std_format=YES

# Explication :
# xferlog_enable=YES active le logging des transferts
# 
# Format du log (xferlog_std_format=YES) :
# 
# Exemple de ligne de log :
# Mon Dec 16 10:30:00 2024 1 192.168.1.50 1234 /home/ftpuser1/test.txt b _ o r ftpuser1 ftp 0 * c
# 
# Décomposition :
# - Date et heure : Mon Dec 16 10:30:00 2024
# - Durée (secondes) : 1
# - IP du client : 192.168.1.50
# - Taille (bytes) : 1234
# - Fichier : /home/ftpuser1/test.txt
# - Type transfert : b (binaire) ou a (ASCII)
# - Action spéciale : _ (aucune)
# - Direction : o (out = download) ou i (in = upload)
# - Mode accès : r (real = utilisateur local)
# - Utilisateur : ftpuser1
# - Service : ftp
# - Méthode auth : 0 (aucune)
# - ID utilisateur : *
# - Status : c (complete = succès)

# Activer les logs vsftpd (plus détaillés)
log_ftp_protocol=YES

# Explication :
# log_ftp_protocol=YES log TOUTES les commandes FTP
# Très verbeux mais utile pour le debug
# 
# Exemple :
# [pid 12345] [ftpuser1] FTP command: PASS <password>
# [pid 12345] [ftpuser1] FTP response: 230 Login successful.
# [pid 12345] [ftpuser1] FTP command: PWD
# [pid 12345] [ftpuser1] FTP response: 257 "/home/ftpuser1"
# 
# [ATTENTION] Désactiver en production (consomme de l'espace disque)

# ───────────────────────────────────────────────────────────────
# RESTRICTIONS DE SÉCURITÉ DE BASE
# ───────────────────────────────────────────────────────────────

# Empêcher les utilisateurs de sortir de leur home (chroot jail)
chroot_local_user=YES

# Explication DÉTAILLÉE du chroot :
# 
# chroot = Change Root (changer la racine)
# 
# Sans chroot (chroot_local_user=NO) :
# ftpuser1 se connecte -> Voit /home/ftpuser1
# Peut faire "cd .." -> Voit /home
# Peut faire "cd .." -> Voit / (TOUTE l'arborescence !)
# [X] Peut lire /etc/passwd, /etc/shadow, etc.
# 
# Avec chroot (chroot_local_user=YES) :
# ftpuser1 se connecte -> Voit / (mais c'est en fait /home/ftpuser1)
# Ne peut PAS sortir de /home/ftpuser1
# [OK] Isolation complète !
# 
# Schéma sans chroot :
# /
# ├── home
# │   ├── ftpuser1  <- Utilisateur ici
# │   └── ftpuser2
# ├── etc
# │   └── passwd    <- Peut accéder ! [X]
# └── var
# 
# Schéma avec chroot :
# / (en fait /home/ftpuser1)
# ├── test1.txt
# ├── documents
# └── confidentiel.txt
# 
# L'utilisateur ne sait même pas qu'il y a un système en dehors !

# Autoriser l'écriture dans le chroot (nécessaire avec chroot)
allow_writeable_chroot=YES

# Explication :
# Depuis vsftpd 2.3.5, pour des raisons de sécurité,
# l'écriture est interdite dans un répertoire chroot
# SAUF si on active explicitement allow_writeable_chroot
# 
# Sans cette option, erreur :
# 500 OOPS: vsftpd: refusing to run with writable root inside chroot()
# 
# Pourquoi cette restriction ?
# Prévenir une faille de sécurité où un utilisateur pourrait
# créer des liens symboliques pour échapper du chroot
# 
# allow_writeable_chroot=YES désactive cette protection
# [ATTENTION] En production, mieux vaut créer une structure avec
# un répertoire racine non-writable et des sous-dossiers writables

# ───────────────────────────────────────────────────────────────
# LISTE DES UTILISATEURS AUTORISÉS/INTERDITS (OPTIONNEL)
# ───────────────────────────────────────────────────────────────

# Utiliser une liste d'utilisateurs autorisés
# userlist_enable=YES
# userlist_file=/etc/vsftpd.userlist
# userlist_deny=NO

# Explication :
# userlist_enable=YES active la gestion de liste
# 
# Deux modes possibles :
# 
# 1. WHITELIST (userlist_deny=NO) :
#    Seuls les utilisateurs dans le fichier PEUVENT se connecter
#    Tous les autres sont REFUSÉS
# 
# 2. BLACKLIST (userlist_deny=YES, par défaut) :
#    Les utilisateurs dans le fichier sont REFUSÉS
#    Tous les autres PEUVENT se connecter
# 
# Exemple de /etc/vsftpd.userlist (whitelist) :
# ftpuser1
# ftpuser2
# admin
# 
# Seuls ces 3 utilisateurs pourront se connecter
# 
# [ATTENTION] Par défaut, la blacklist contient "root"
# (root ne peut JAMAIS se connecter en FTP, c'est bien !)

# ───────────────────────────────────────────────────────────────
# PERFORMANCE ET LIMITES
# ───────────────────────────────────────────────────────────────

# Nombre maximum de clients connectés
max_clients=50

# Nombre maximum de connexions depuis une même IP
max_per_ip=5

# Explication :
# max_clients=50 : 50 utilisateurs simultanés maximum
# Si le 51ème tente de se connecter : refusé
# 
# max_per_ip=5 : Une IP peut avoir max 5 connexions
# Protection contre les attaques par force brute
# 
# Valeurs recommandées :
# - Petit serveur : max_clients=10, max_per_ip=2
# - Serveur moyen : max_clients=50, max_per_ip=5
# - Gros serveur : max_clients=200+, max_per_ip=10+

# Timeout de connexion inactve (secondes)
idle_session_timeout=600

# Timeout de transfert de données (secondes)
data_connection_timeout=120

# Explication :
# idle_session_timeout=600 :
# Si un utilisateur est connecté mais ne fait RIEN pendant 10 min
# -> Déconnexion automatique
# 
# data_connection_timeout=120 :
# Si un transfert de fichier se bloque pendant 2 min
# -> Abandon du transfert
# 
# Libère des ressources serveur

# ═══════════════════════════════════════════════════════════════
# FIN DE LA CONFIGURATION
# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde : `Ctrl + O`, `Entrée`, `Ctrl + X`**

---

**Vérifier la syntaxe (pas d'outil officiel, mais on peut tester) :**

```bash
sudo vsftpd /etc/vsftpd.conf
```

**Si aucune erreur n'apparaît immédiatement, c'est bon signe.**

**Stopper avec `Ctrl + C`.**

---

**Redémarrer vsftpd pour appliquer la configuration :**

```bash
sudo systemctl restart vsftpd
```

---

**Vérifier que le service redémarre correctement :**

```bash
sudo systemctl status vsftpd
```

**Résultat :**

```
[BLACK_CIRCLE] vsftpd.service - vsftpd FTP server
     Loaded: loaded
     Active: active (running) since Mon 2024-12-16 10:45:00 UTC; 5s ago
```

**[OK] Configuration appliquée !**

---

### ÉTAPE 6 : Tester la connexion FTP

**Il existe plusieurs façons de tester FTP :**

1. **Client en ligne de commande** (`ftp`)
2. **Client graphique** (FileZilla)
3. **Client avancé** (`lftp`)
4. **Navigateur web** (lecture seule)

---

#### Test 1 : Avec le client FTP en ligne de commande

**Installer le client FTP (s'il n'est pas déjà installé) :**

```bash
sudo apt install ftp -y
```

---

**Se connecter localement :**

```bash
ftp localhost
```

**Ou avec l'IP du serveur :**

```bash
ftp 192.168.1.100
```

**Résultat :**

```
Connected to localhost.
220 Bienvenue sur le serveur FTP de l'entreprise
Name (localhost:user):
```

**[OK] Le serveur répond ! La bannière s'affiche.**

---

**Entrer le nom d'utilisateur :**

```
Name (localhost:user): ftpuser1
```

**Enter.**

**Résultat :**

```
331 Please specify the password.
Password:
```

---

**Entrer le mot de passe :**

```
Password: FtpPass123!
```

**(Le mot de passe ne s'affiche pas)**

**Enter.**

**Résultat :**

```
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
```

**[OK] Authentification réussie ! Prompt `ftp>` = tu es connecté.**

---

**Tester quelques commandes FTP :**

**Afficher le répertoire actuel :**

```
ftp> pwd
```

**Résultat :**

```
257 "/" is the current directory
```

**`/` = Racine du chroot (/home/ftpuser1)**

---

**Lister les fichiers :**

```
ftp> ls
```

**Résultat :**

```
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 1001     1001         4096 Dec 16 10:10 documents
-rw-r--r--    1 1001     1001           23 Dec 16 10:10 confidentiel.txt
-rw-r--r--    1 1001     1001           16 Dec 16 10:10 test1.txt
226 Directory send OK.
```

**[OK] Les fichiers sont visibles !**

**Note : `1001 1001` = UID et GID de ftpuser1**

---

**Télécharger un fichier (download) :**

```
ftp> get test1.txt
```

**Résultat :**

```
local: test1.txt remote: test1.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for test1.txt (16 bytes).
226 Transfer complete.
16 bytes received in 0.00 secs (156.25 kB/s)
```

**[OK] Fichier téléchargé !**

**Le fichier est maintenant dans le répertoire actuel de ta machine.**

---

**Vérifier :**

```
ftp> !ls test1.txt
```

**`!ls` exécute `ls` sur la machine LOCALE (pas le serveur)**

**Résultat :**

```
test1.txt
```

**[OK] Fichier bien téléchargé localement !**

---

**Envoyer un fichier (upload) :**

**D'abord, créer un fichier local :**

```
ftp> !echo "Test upload" > upload_test.txt
```

**Envoyer au serveur :**

```
ftp> put upload_test.txt
```

**Résultat :**

```
local: upload_test.txt remote: upload_test.txt
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
12 bytes sent in 0.00 secs (117.19 kB/s)
```

**[OK] Upload réussi !**

---

**Vérifier que le fichier est bien sur le serveur :**

```
ftp> ls upload_test.txt
```

**Résultat :**

```
-rw-r--r--    1 1001     1001           12 Dec 16 10:50 upload_test.txt
```

**[OK] Fichier présent sur le serveur !**

---

**Changer de répertoire :**

```
ftp> cd documents
```

**Résultat :**

```
250 Directory successfully changed.
```

---

**Lister :**

```
ftp> ls
```

**Résultat :**

```
-rw-r--r--    1 1001     1001           19 Dec 16 10:10 important.txt
```

**[OK] Navigation dans les dossiers OK !**

---

**Tenter de sortir du chroot :**

```
ftp> cd /etc
```

**Résultat :**

```
550 Failed to change directory.
```

**[OK] Chroot fonctionne ! Impossible de sortir de /home/ftpuser1.**

---

**Quitter :**

```
ftp> quit
```

**Ou `bye` ou `exit`**

**Résultat :**

```
221 Goodbye.
```

**[OK] Déconnexion propre.**

---

#### Test 2 : Avec FileZilla (client graphique)

**Installer FileZilla sur ton PC (pas sur le serveur) :**

**Windows/Mac :**
- Télécharge depuis https://filezilla-project.org/
- Installe normalement

**Linux (Ubuntu/Debian) :**

```bash
sudo apt install filezilla -y
```

---

**Lancer FileZilla.**

**En haut, remplir :**

```
Hôte : ftp://192.168.1.100
Identifiant : ftpuser1
Mot de passe : FtpPass123!
Port : 21
```

**Cliquer sur "Connexion rapide"**

---

**Résultats attendus :**

**Fenêtre "État" (log) :**

```
Statut :    Connexion à 192.168.1.100:21...
Statut :    Connexion établie, attente du message de bienvenue...
Réponse :   220 Bienvenue sur le serveur FTP de l'entreprise
Commande :  AUTH TLS
Réponse :   530 Please login with USER and PASS.
Commande :  AUTH SSL
Réponse :   530 Please login with USER and PASS.
Statut :    Serveur non sécurisé, il ne supporte pas FTP sur TLS.
Commande :  USER ftpuser1
Réponse :   331 Please specify the password.
Commande :  PASS **********
Réponse :   230 Login successful.
Commande :  SYST
Réponse :   215 UNIX Type: L8
Commande :  PWD
Réponse :   257 "/" is the current directory
Statut :    Connecté
Statut :    Récupération du contenu du dossier...
Commande :  CWD /
Réponse :   250 Directory successfully changed.
Commande :  PWD
Réponse :   257 "/" is the current directory
Commande :  PASV
Réponse :   227 Entering Passive Mode (192,168,1,100,195,123).
Commande :  MLSD
Réponse :   150 Here comes the directory listing.
Réponse :   226 Directory send OK.
Statut :    Contenu du dossier "/" affiché avec succès
```

**Panneau de droite (Serveur distant) :**

```
documents/
confidentiel.txt
test1.txt
upload_test.txt
```

**[OK] Connexion FileZilla réussie !**

---

**Tu peux maintenant :**
- **Glisser-déposer** des fichiers pour les uploader
- **Double-cliquer** sur un fichier pour le télécharger
- **Clic droit** -> Options (renommer, supprimer, etc.)

---

#### Test 3 : Consulter les logs

**Sur le serveur, consulter les logs de connexion :**

```bash
sudo tail -20 /var/log/vsftpd.log
```

**Résultat (exemple) :**

```
Mon Dec 16 10:50:00 2024 1 192.168.1.50 16 /test1.txt b _ o r ftpuser1 ftp 0 * c
Mon Dec 16 10:50:15 2024 0 192.168.1.50 12 /upload_test.txt b _ i r ftpuser1 ftp 0 * c
```

**Décryptage de la 1ère ligne :**

- **Mon Dec 16 10:50:00 2024** = Date et heure
- **1** = Durée du transfert (1 seconde)
- **192.168.1.50** = IP du client
- **16** = Taille du fichier (16 bytes)
- **/test1.txt** = Fichier transféré
- **b** = Mode binaire (binary)
- **_** = Action spéciale (none)
- **o** = Direction : `o` = out = download (depuis le serveur vers le client)
- **r** = Mode accès : `r` = real user (utilisateur local)
- **ftpuser1** = Nom d'utilisateur
- **ftp** = Service
- **0** = Méthode d'authentification
- ***** = ID utilisateur
- **c** = Statut : `c` = complete (succès)

**Décryptage de la 2ème ligne :**

- **i** = Direction : `i` = in = upload (du client vers le serveur)

**[OK] Les logs tracent toutes les opérations !**

---

### [OK] TESTS DE VALIDATION

**1. Connexion utilisateur local**

- [ ] Se connecter en FTP avec ftpuser1
- [ ] Authentification réussie (230 Login successful)
- [ ] Prompt FTP accessible

---

**2. Navigation dans le chroot**

- [ ] Lister les fichiers (ls)
- [ ] Changer de répertoire (cd documents)
- [ ] Afficher le répertoire actuel (pwd)
- [ ] Impossible de sortir du chroot (cd /etc -> Erreur 550)

---

**3. Download (téléchargement)**

- [ ] Télécharger un fichier (get test1.txt)
- [ ] Fichier reçu et intact
- [ ] Vérifier le contenu (cat test1.txt)

---

**4. Upload (envoi)**

- [ ] Créer un fichier local
- [ ] Envoyer au serveur (put newfile.txt)
- [ ] Vérifier présence sur le serveur (ls)

---

**5. Permissions et propriété**

```bash
# Sur le serveur, vérifier les permissions du fichier uploadé
sudo ls -l /home/ftpuser1/upload_test.txt
```

**Résultat attendu :**

```
-rw-r--r-- 1 ftpuser1 ftpuser1 12 Dec 16 10:50 upload_test.txt
```

**Permissions `644` (définies par umask 022) [OK]**

---

**6. Logs fonctionnent**

```bash
sudo tail -5 /var/log/vsftpd.log
```

- [ ] Logs présents
- [ ] Uploads et downloads tracés
- [ ] IP du client visible

---

**7. Connexion d'un second utilisateur**

```bash
ftp localhost
```

**User : `ftpuser2`, Pass : `FtpPass456!`**

- [ ] Connexion réussie
- [ ] Répertoire /home/ftpuser2 accessible
- [ ] Ne voit PAS les fichiers de ftpuser1 (isolation [OK])

---

**8. Sécurité chroot**

```bash
ftp localhost
# Connexion avec ftpuser1
ftp> cd ../../etc
```

**Résultat attendu : `550 Failed to change directory`**

- [ ] Impossible de sortir du home
- [ ] Impossible d'accéder à /etc
- [ ] Isolation complète [OK]

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "500 OOPS: vsftpd: refusing to run with writable root inside chroot()"

**Symptôme :**

```
Réponse :   500 OOPS: vsftpd: refusing to run with writable root inside chroot()
Réponse :   421 Service not available, remote server has closed connection
```

**Cause :** vsftpd refuse d'exécuter avec un répertoire chroot writable (depuis version 2.3.5)

**Solution :**

**Méthode 1 (simple mais moins sécurisée) :**

Ajouter dans `/etc/vsftpd.conf` :

```conf
allow_writeable_chroot=YES
```

Redémarrer :

```bash
sudo systemctl restart vsftpd
```

---

**Méthode 2 (plus sécurisée) :**

Créer une structure avec racine non-writable :

```bash
# Créer un utilisateur FTP spécial
sudo useradd -m -s /bin/bash ftpuser3

# Retirer les permissions d'écriture sur le home
sudo chmod a-w /home/ftpuser3

# Créer un sous-dossier writable
sudo mkdir /home/ftpuser3/files
sudo chown ftpuser3:ftpuser3 /home/ftpuser3/files
sudo chmod 755 /home/ftpuser3/files
```

**Résultat :**

```
/home/ftpuser3/  (r-xr-xr-x, non-writable)
└── files/       (rwxr-xr-x, writable)
```

L'utilisateur ne peut pas écrire dans `/`, mais peut écrire dans `/files`.

---

#### Erreur 2 : "530 Login incorrect"

**Symptôme :**

```
Réponse :   530 Login incorrect.
```

**Causes possibles :**

**1. Mauvais mot de passe**

Réinitialiser :

```bash
sudo passwd ftpuser1
```

---

**2. L'utilisateur est dans la blacklist**

Vérifier `/etc/ftpusers` :

```bash
cat /etc/ftpusers
```

**Ce fichier contient les utilisateurs INTERDITS.**

Si ftpuser1 est dedans, le retirer :

```bash
sudo nano /etc/ftpusers
# Supprimer la ligne "ftpuser1"
```

---

**3. `local_enable=NO` dans la config**

Vérifier :

```bash
grep "local_enable" /etc/vsftpd.conf
```

**Doit être :**

```
local_enable=YES
```

---

#### Erreur 3 : "500 OOPS: cannot change directory"

**Symptôme :**

```
Réponse :   500 OOPS: cannot change directory:/home/ftpuser1
```

**Cause :** Le répertoire home de l'utilisateur n'existe pas

**Solution :**

```bash
# Créer le home directory
sudo mkdir -p /home/ftpuser1

# Définir la propriété
sudo chown ftpuser1:ftpuser1 /home/ftpuser1

# Définir les permissions
sudo chmod 755 /home/ftpuser1
```

---

#### Erreur 4 : Impossible de se connecter (timeout)

**Symptôme :**

```
Erreur :    Le délai de connexion a expiré après 20 secondes d'inactivité
Erreur :    Impossible de se connecter au serveur
```

**Causes possibles :**

**1. vsftpd ne tourne pas**

```bash
sudo systemctl status vsftpd
```

Si inactif :

```bash
sudo systemctl start vsftpd
```

---

**2. Firewall bloque le port 21**

Vérifier :

```bash
sudo ufw status
```

Si actif, autoriser FTP :

```bash
sudo ufw allow 21/tcp
```

---

**3. vsftpd n'écoute pas sur la bonne interface**

Vérifier :

```bash
sudo netstat -tulpn | grep :21
```

Si aucune sortie, vsftpd n'écoute pas.

Dans `/etc/vsftpd.conf`, vérifier :

```conf
listen=YES
```

---

#### Erreur 5 : "550 Permission denied"

**Symptôme lors d'un upload :**

```
Commande :  STOR newfile.txt
Réponse :   550 Permission denied.
```

**Causes possibles :**

**1. `write_enable=NO`**

Dans `/etc/vsftpd.conf`, vérifier :

```conf
write_enable=YES
```

---

**2. Permissions insuffisantes sur le répertoire**

```bash
# Vérifier les permissions
sudo ls -ld /home/ftpuser1

# Si nécessaire, donner l'accès en écriture
sudo chmod 755 /home/ftpuser1
```

---

**3. SELinux bloque (sur CentOS/RedHat)**

```bash
# Vérifier SELinux
sudo getenforce

# Si "Enforcing", configurer SELinux pour FTP
sudo setsebool -P ftp_home_dir on
```

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. Architecture FTP**
- 2 connexions : contrôle (port 21) + données (port 20 ou aléatoire)
- Mode actif (obsolète) vs mode passif (standard aujourd'hui)
- Codes de réponse : 2xx = succès, 4xx = erreur temporaire, 5xx = erreur permanente

**2. vsftpd**
- Serveur FTP sécurisé et performant
- Configuration dans `/etc/vsftpd.conf`
- Service géré par systemd (`systemctl`)

**3. Authentification**
- `local_enable=YES` pour utilisateurs Linux
- `anonymous_enable=NO` pour désactiver l'accès anonyme
- Fichiers `/etc/ftpusers` et `/etc/vsftpd.userlist` pour restreindre

**4. Chroot jail**
- `chroot_local_user=YES` isole chaque utilisateur dans son home
- Empêche de naviguer hors de /home/username
- `allow_writeable_chroot=YES` nécessaire avec vsftpd 2.3.5+

**5. Permissions**
- `write_enable=YES` pour autoriser upload/delete
- `local_umask=022` définit les permissions des fichiers créés
- Fichiers uploadés : 644 (rw-r--r--), Dossiers : 755 (rwxr-xr-x)

**6. Logs**
- `/var/log/vsftpd.log` trace tous les transferts
- `xferlog_std_format=YES` pour format standard
- `log_ftp_protocol=YES` pour logs détaillés (debug)

**7. Sécurité de base**
- Toujours désactiver l'accès anonyme
- Toujours activer le chroot
- Limiter les connexions (max_clients, max_per_ip)
- Configurer des timeouts

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Ajouter un utilisateur à la whitelist**

```bash
# Activer la whitelist
sudo nano /etc/vsftpd.conf
```

**Ajouter :**

```conf
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
```

**Créer le fichier de whitelist :**

```bash
sudo nano /etc/vsftpd.userlist
```

**Contenu :**

```
ftpuser1
ftpuser2
```

**Résultat : Seuls ftpuser1 et ftpuser2 peuvent se connecter.**

---

**2. Quotas de disque**

```bash
# Installer quota
sudo apt install quota -y

# Activer les quotas sur /home
sudo nano /etc/fstab
```

**Modifier la ligne de /home :**

```
/dev/sda2 /home ext4 defaults,usrquota,grpquota 0 2
```

**Remonter et initialiser :**

```bash
sudo mount -o remount /home
sudo quotacheck -cugm /home
sudo quotaon /home
```

**Définir un quota pour un utilisateur :**

```bash
sudo edquota ftpuser1
```

**Définir :**

```
Blocks soft = 100000  (100 MB soft limit)
Blocks hard = 150000  (150 MB hard limit)
```

---

**3. Bannir des IP avec Fail2Ban**

Voir Exercice 5 pour Fail2Ban détaillé.

**Bref aperçu :**

```bash
sudo apt install fail2ban -y

sudo nano /etc/fail2ban/jail.local
```

**Ajouter :**

```ini
[vsftpd]
enabled = true
port = ftp
logpath = /var/log/vsftpd.log
maxretry = 3
bantime = 3600
```

**Redémarrer :**

```bash
sudo systemctl restart fail2ban
```

**Après 3 échecs d'authentification, l'IP est bannie pendant 1h.**

---

**4. Surveillance avec Monit**

```bash
sudo apt install monit -y

sudo nano /etc/monit/conf.d/vsftpd
```

**Contenu :**

```
check process vsftpd with pidfile /run/vsftpd/vsftpd.pid
  start program = "/usr/bin/systemctl start vsftpd"
  stop program = "/usr/bin/systemctl stop vsftpd"
  if failed port 21 protocol ftp then restart
  if 5 restarts within 5 cycles then timeout
```

**Redémarrer Monit :**

```bash
sudo systemctl restart monit
```

**Monit vérifie toutes les minutes que vsftpd tourne.**

---

## [COURS] CONCLUSION DE L'EXERCICE 1

**[OK] Félicitations ! Tu as installé et configuré vsftpd avec succès !**

**Ce que tu as appris :**
- Architecture et fonctionnement de FTP (2 canaux, modes actif/passif)
- Installer vsftpd sur Linux
- Configurer vsftpd pour les utilisateurs locaux
- Activer le chroot jail pour la sécurité
- Gérer les permissions et umask
- Tester avec clients FTP (ligne de commande et FileZilla)
- Lire et interpréter les logs FTP
- Diagnostiquer les erreurs courantes

**Compétences acquises :**
- [OK] FTP (niveau débutant-intermédiaire)
- [OK] vsftpd (configuration de base)
- [OK] Sécurité FTP (chroot, restrictions)
- [OK] Gestion utilisateurs Linux pour FTP
- [OK] Logs et monitoring FTP

**Temps moyen de réalisation :** 1-2 heures

**Prochaine étape :** Exercice 2 - Utilisateurs virtuels et isolation avancée ! [SECURISE]

---

---

# [JAUNE] EXERCICE 2 : UTILISATEURS VIRTUELS FTP ET CHROOT AVANCÉ

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système dans une agence web. L'agence héberge les sites de 50+ clients. Chaque client doit pouvoir accéder EN FTP à son site web pour :
- Uploader des fichiers
- Modifier le code
- Télécharger des backups

**Problèmes avec des utilisateurs Linux réels :**
- [X] Créer 50+ comptes Linux = lourd à gérer
- [X] Chaque compte a un shell -> risque de sécurité
- [X] Mélange entre utilisateurs système et utilisateurs FTP

**Solution : Utilisateurs virtuels FTP**

Les utilisateurs virtuels :
- [OK] N'existent PAS dans `/etc/passwd`
- [OK] Pas de shell, pas d'accès SSH
- [OK] Stockés dans une base de données séparée
- [OK] Isolation complète par client
- [OK] Gestion centralisée

### Objectifs techniques

- Créer des utilisateurs virtuels FTP avec PAM
- Utiliser une base de données Berkeley DB (ou MySQL)
- Mapper tous les utilisateurs virtuels vers un seul UID/GID
- Configurer un chroot différent par utilisateur virtuel
- Gérer les permissions par répertoire client
- Logger toutes les actions

### Architecture cible

```
Structure des dossiers :
/srv/ftp/
├── client1/
│   ├── www/          <- Site web du client 1
│   └── backups/      <- Backups
├── client2/
│   ├── www/
│   └── backups/
└── client3/
    ├── www/
    └── backups/

Utilisateurs virtuels :
- client1 -> chroot dans /srv/ftp/client1
- client2 -> chroot dans /srv/ftp/client2
- client3 -> chroot dans /srv/ftp/client3

Tous mappés vers l'utilisateur Linux "ftpvirtual" (UID 2001)
```

### Contraintes

- vsftpd avec PAM (Pluggable Authentication Modules)
- Base de données Berkeley DB pour les mots de passe
- Isolation stricte (un client ne voit pas les autres)
- Permissions correctes (clients peuvent écrire dans www/)
- Temps estimé : 2-3 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre les utilisateurs virtuels vs utilisateurs réels
- [OK] Configurer PAM pour l'authentification personnalisée
- [OK] Créer une base de données Berkeley DB
- [OK] Mapper des utilisateurs virtuels vers un UID unique
- [OK] Configurer des chroots différents par utilisateur
- [OK] Gérer les permissions complexes pour FTP
- [OK] Automatiser la création d'utilisateurs virtuels
- [OK] Utiliser `user_config_dir` pour des configs par utilisateur

---

## [DOCS] PRÉREQUIS

- Exercice 1 terminé (vsftpd fonctionnel)
- Compréhension des utilisateurs et groupes Linux
- Notions de PAM
- Notions de bases de données

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Comprendre les utilisateurs virtuels

#### Utilisateurs réels vs Utilisateurs virtuels

**UTILISATEURS RÉELS (comme dans l'Exercice 1) :**

```
/etc/passwd :
ftpuser1:x:1001:1001::/home/ftpuser1:/bin/bash

Caractéristiques :
- Existe dans /etc/passwd
- A un UID et GID
- A un répertoire home (/home/ftpuser1)
- A un shell (/bin/bash)
- Peut se connecter en SSH (si autorisé)
- Peut exécuter des commandes système
```

**Problèmes pour un hébergeur :**
- [X] 100 clients = 100 comptes Linux
- [X] Si compromis, accès SSH possible
- [X] Lourde gestion (useradd, passwd, userdel)
- [X] Mélange avec les vrais utilisateurs système

---

**UTILISATEURS VIRTUELS :**

```
Base de données séparée (Berkeley DB ou MySQL) :
client1 -> mot_de_passe_hashé
client2 -> mot_de_passe_hashé
client3 -> mot_de_passe_hashé

Caractéristiques :
- N'existent PAS dans /etc/passwd
- Tous mappés vers UN SEUL utilisateur Linux (ex: ftpvirtual)
- Pas de shell
- Pas d'accès SSH (pas de compte Linux)
- Authentification via PAM + base de données
- Chroot configuré par utilisateur virtuel
```

**Avantages :**
- [OK] Séparation totale entre système et FTP
- [OK] Aucun risque d'accès SSH
- [OK] Gestion centralisée (BDD)
- [OK] Scalabilité (1000+ utilisateurs facile)
- [OK] Isolation par client

---

#### Comment ça fonctionne ?

**Flux d'authentification :**

```
1. Client FTP se connecte avec "client1" / "password"
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] vsftpd reçoit les identifiants
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] vsftpd appelle PAM pour vérifier
   │   (pam_userdb.so lit la base Berkeley DB)
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] PAM vérifie : "client1" existe ? Mot de passe correct ?
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] Si OK, vsftpd mappe "client1" vers l'utilisateur Linux "ftpvirtual"
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] vsftpd lit la config spécifique de "client1"
   │   (dans /etc/vsftpd/user_conf/client1)
   │
   ├─[BLACK_RIGHT-POINTING_POINTER] vsftpd définit le chroot : /srv/ftp/client1
   │
   └─[BLACK_RIGHT-POINTING_POINTER] Client connecté et isolé dans /srv/ftp/client1
```

**Schéma :**

```
┌──────────────────────────────────────────────────┐
│ Base de données (Berkeley DB)                    │
│                                                  │
│ client1 -> $6$...hash...                         │
│ client2 -> $6$...hash...                         │
│ client3 -> $6$...hash...                         │
└──────────────────────────────────────────────────┘
           ^
           │ PAM (pam_userdb.so)
           │
┌──────────┴───────────────────────────────────────┐
│ vsftpd                                           │
│                                                  │
│ Utilisateur virtuel "client1"                   │
│ -> Mappé vers UID 2001 (ftpvirtual)              │
│ -> Chroot: /srv/ftp/client1                      │
│ -> Config: /etc/vsftpd/user_conf/client1         │
└──────────────────────────────────────────────────┘
           │
           v
┌──────────────────────────────────────────────────┐
│ /srv/ftp/client1/  (chroot)                     │
│ ├── www/                                         │
│ └── backups/                                     │
└──────────────────────────────────────────────────┘
```

---

### ÉTAPE 2 : Créer l'utilisateur Linux de mapping

**Tous les utilisateurs virtuels seront mappés vers cet utilisateur.**

```bash
# Créer l'utilisateur "ftpvirtual" sans shell et sans home login
sudo useradd --system --no-create-home --shell /bin/false ftpvirtual
```

**Explication des options :**

**`--system`** : Crée un utilisateur système (UID < 1000)

**`--no-create-home`** : Ne crée PAS de /home/ftpvirtual

**`--shell /bin/false`** : Shell impossible (aucune connexion interactive)

**Résultat : Utilisateur technique, pas un vrai utilisateur.**

---

**Vérifier la création :**

```bash
grep ftpvirtual /etc/passwd
```

**Résultat :**

```
ftpvirtual:x:2001:2001::/nonexistent:/bin/false
```

**Décryptage :**
- `ftpvirtual` = Nom d'utilisateur
- `x` = Mot de passe (dans /etc/shadow)
- `2001` = UID
- `2001` = GID
- `::/nonexistent:` = Pas de home directory
- `/bin/false` = Shell impossible

**[OK] Utilisateur ftpvirtual créé !**

---

**Vérifier l'UID :**

```bash
id ftpvirtual
```

**Résultat :**

```
uid=2001(ftpvirtual) gid=2001(ftpvirtual) groups=2001(ftpvirtual)
```

**Note bien l'UID : 2001 (on en aura besoin plus tard)**

---

### ÉTAPE 3 : Créer la structure de dossiers

```bash
# Créer le dossier racine pour tous les clients
sudo mkdir -p /srv/ftp

# Créer les dossiers pour 3 clients de test
sudo mkdir -p /srv/ftp/client1/{www,backups}
sudo mkdir -p /srv/ftp/client2/{www,backups}
sudo mkdir -p /srv/ftp/client3/{www,backups}
```

**Explication de `{www,backups}` :**

Expansion de brace (accolades) :

```bash
mkdir -p /srv/ftp/client1/{www,backups}
```

Est équivalent à :

```bash
mkdir -p /srv/ftp/client1/www
mkdir -p /srv/ftp/client1/backups
```

**Économise du temps !**

---

**Définir les permissions :**

```bash
# Donner la propriété à ftpvirtual
sudo chown -R ftpvirtual:ftpvirtual /srv/ftp

# Permissions :
# - Racine du client (ex: /srv/ftp/client1) : 555 (r-xr-xr-x)
# - Sous-dossiers (www, backups) : 755 (rwxr-xr-x)

# Racines clients en lecture seule
sudo chmod 555 /srv/ftp/client1
sudo chmod 555 /srv/ftp/client2
sudo chmod 555 /srv/ftp/client3

# Sous-dossiers en lecture-écriture
sudo chmod 755 /srv/ftp/client1/www
sudo chmod 755 /srv/ftp/client1/backups
sudo chmod 755 /srv/ftp/client2/www
sudo chmod 755 /srv/ftp/client2/backups
sudo chmod 755 /srv/ftp/client3/www
sudo chmod 755 /srv/ftp/client3/backups
```

**Pourquoi cette structure de permissions ?**

**Racine du chroot (`/srv/ftp/client1`) : 555 (r-xr-xr-x)**
- Lecture seule pour ftpvirtual
- **Empêche** l'upload de fichiers directement à la racine
- **Force** l'utilisateur à uploader dans www/ ou backups/

**Sous-dossiers (`www/`, `backups/`) : 755 (rwxr-xr-x)**
- Lecture + écriture pour ftpvirtual
- Permet upload, suppression, etc.

**Cette structure est la recommandation vsftpd pour éviter :**

```
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
```

---

**Vérifier la structure :**

```bash
tree -L 2 /srv/ftp
```

**Résultat :**

```
/srv/ftp
├── client1
│   ├── backups
│   └── www
├── client2
│   ├── backups
│   └── www
└── client3
    ├── backups
    └── www
```

**[OK] Structure créée !**

---

**Vérifier les permissions :**

```bash
ls -lR /srv/ftp
```

**Résultat :**

```
/srv/ftp:
dr-xr-xr-x 4 ftpvirtual ftpvirtual 4096 Dec 16 11:00 client1
dr-xr-xr-x 4 ftpvirtual ftpvirtual 4096 Dec 16 11:00 client2
dr-xr-xr-x 4 ftpvirtual ftpvirtual 4096 Dec 16 11:00 client3

/srv/ftp/client1:
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 backups
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 www

/srv/ftp/client2:
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 backups
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 www

/srv/ftp/client3:
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 backups
drwxr-xr-x 2 ftpvirtual ftpvirtual 4096 Dec 16 11:00 www
```

**Note les permissions :**
- `dr-xr-xr-x` pour client1, client2, client3 (555 [OK])
- `drwxr-xr-x` pour www/ et backups/ (755 [OK])

**[OK] Permissions correctes !**

---

**Créer quelques fichiers de test :**

```bash
# Client 1
sudo -u ftpvirtual touch /srv/ftp/client1/www/index.html
sudo -u ftpvirtual bash -c 'echo "<h1>Site Client 1</h1>" > /srv/ftp/client1/www/index.html'
sudo -u ftpvirtual touch /srv/ftp/client1/backups/backup_2024-12-16.tar.gz

# Client 2
sudo -u ftpvirtual touch /srv/ftp/client2/www/index.html
sudo -u ftpvirtual bash -c 'echo "<h1>Site Client 2</h1>" > /srv/ftp/client2/www/index.html'

# Client 3
sudo -u ftpvirtual touch /srv/ftp/client3/www/index.html
sudo -u ftpvirtual bash -c 'echo "<h1>Site Client 3</h1>" > /srv/ftp/client3/www/index.html'
```

**`sudo -u ftpvirtual` exécute la commande en tant que ftpvirtual**

---

### ÉTAPE 4 : Installer les outils pour la base de données

**On va utiliser Berkeley DB pour stocker les utilisateurs virtuels.**

```bash
# Installer db-util (outils Berkeley DB)
sudo apt install db-util -y

# Installer libpam-pwdfile (module PAM pour fichiers de mots de passe)
sudo apt install libpam-pwdfile -y
```

**Explication :**

**Berkeley DB** = Base de données clé-valeur très rapide

**db-util** = Outils en ligne de commande pour manipuler Berkeley DB

**libpam-pwdfile** = Module PAM qui peut lire des fichiers de mots de passe ou Berkeley DB

---

### ÉTAPE 5 : Créer les utilisateurs virtuels dans la base de données

**Méthode 1 : Avec un fichier texte puis conversion en Berkeley DB**

**Créer un fichier texte avec les utilisateurs :**

```bash
sudo nano /etc/vsftpd/virtual_users.txt
```

**Contenu (format : ligne impaire = username, ligne paire = password) :**

```
client1
ClientPass1!
client2
ClientPass2!
client3
ClientPass3!
```

**[ATTENTION] Attention au format !**
- Ligne 1 : username
- Ligne 2 : password
- Ligne 3 : username
- Ligne 4 : password
- etc.

**Sauvegarde.**

---

**Créer la base de données Berkeley DB :**

```bash
# Créer le dossier pour la base de données
sudo mkdir -p /etc/vsftpd

# Convertir le fichier texte en Berkeley DB
sudo db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db
```

**Explication de `db_load` :**

**`db_load`** = Charge des données dans Berkeley DB

**`-T`** = Utilise un fichier texte en entrée

**`-t hash`** = Type de base de données (hash table)

**`-f /etc/vsftpd/virtual_users.txt`** = Fichier source (input)

**`/etc/vsftpd/virtual_users.db`** = Fichier de sortie (output)

**Résultat : Fichier binaire `/etc/vsftpd/virtual_users.db` créé**

---

**Sécuriser les fichiers :**

```bash
# Le fichier texte contient les mots de passe en clair !
# Le supprimer après conversion
sudo rm /etc/vsftpd/virtual_users.txt

# Protéger la base de données
sudo chmod 600 /etc/vsftpd/virtual_users.db
sudo chown root:root /etc/vsftpd/virtual_users.db
```

**Permissions 600 :**
- root : rw- (lecture/écriture)
- groupe : --- (aucun accès)
- autres : --- (aucun accès)

**[OK] Seul root peut lire la base de données !**

---

**Vérifier la base de données (optionnel) :**

```bash
sudo db_dump /etc/vsftpd/virtual_users.db
```

**Résultat :**

```
VERSION=3
format=print
type=hash
 client1
 ClientPass1!
 client2
 ClientPass2!
 client3
 ClientPass3!
DATA=END
```

**[OK] Les 3 utilisateurs sont bien dans la BDD !**

---

**Alternative : Méthode 2 avec htpasswd (optionnel)**

**Si tu préfères utiliser htpasswd (comme pour Apache) :**

```bash
# Créer le fichier de mots de passe
sudo htpasswd -c -B /etc/vsftpd/virtual_users client1
# Entre le mot de passe: ClientPass1!

# Ajouter d'autres utilisateurs (SANS -c)
sudo htpasswd -B /etc/vsftpd/virtual_users client2
sudo htpasswd -B /etc/vsftpd/virtual_users client3
```

**`-B` = bcrypt (algorithme de hashage sécurisé)**

**Dans ce cas, utiliser `libpam-pwdfile` au lieu de `pam_userdb.so`**

**Pour cet exercice, on continue avec Berkeley DB.**

---

### ÉTAPE 6 : Configurer PAM pour l'authentification

**PAM (Pluggable Authentication Modules) gère l'authentification sur Linux.**

**Créer un fichier PAM spécifique pour vsftpd virtual users :**

```bash
sudo nano /etc/pam.d/vsftpd_virtual
```

**Contenu :**

```
#%PAM-1.0
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION PAM POUR UTILISATEURS VIRTUELS VSFTPD
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# AUTHENTIFICATION
# ───────────────────────────────────────────────────────────────

# Authentifier via la base de données Berkeley DB
auth required pam_userdb.so db=/etc/vsftpd/virtual_users

# Explication :
# auth = Type de module (authentification)
# required = Ce module DOIT réussir (obligatoire)
# pam_userdb.so = Module PAM pour lire Berkeley DB
# db=/etc/vsftpd/virtual_users = Chemin de la BDD (SANS .db)
# 
# PAM cherche automatiquement /etc/vsftpd/virtual_users.db
# 
# Processus :
# 1. Utilisateur envoie username + password
# 2. PAM ouvre /etc/vsftpd/virtual_users.db
# 3. Cherche la clé "username"
# 4. Compare le password
# 5. Si match -> auth réussie
# 6. Sinon -> auth échouée

# ───────────────────────────────────────────────────────────────
# GESTION DES COMPTES (ACCOUNT)
# ───────────────────────────────────────────────────────────────

# Autoriser tous les comptes virtuels
account required pam_permit.so

# Explication :
# account = Type de module (vérification du compte)
# required = Obligatoire
# pam_permit.so = Module qui autorise TOUT
# 
# On utilise pam_permit.so car les utilisateurs virtuels
# n'ont PAS de compte dans /etc/passwd
# 
# Sans cette ligne, vsftpd refuserait la connexion même
# si l'authentification réussit
# 
# pam_permit.so dit : "OK, le compte est valide"

# ───────────────────────────────────────────────────────────────
# SESSION
# ───────────────────────────────────────────────────────────────

# Créer une session PAM (nécessaire pour certaines opérations)
session required pam_loginuid.so

# Explication :
# session = Type de module (gestion de session)
# pam_loginuid.so = Définit le loginuid (ID de connexion)
# 
# Nécessaire pour l'audit et le logging
# Lie la session à un utilisateur pour les logs système

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

**Explication complète de PAM :**

**PAM = Couche d'abstraction pour l'authentification**

**Au lieu de :**
```
vsftpd -> /etc/passwd (hard-coded)
```

**Avec PAM :**
```
vsftpd -> PAM -> [module au choix]
                ├─ pam_unix.so (/etc/passwd)
                ├─ pam_userdb.so (Berkeley DB)
                ├─ pam_mysql.so (MySQL)
                ├─ pam_ldap.so (LDAP)
                └─ etc.
```

**Avantages :**
- [OK] Changement de méthode d'auth sans recompiler vsftpd
- [OK] Modularité
- [OK] Plusieurs backends possibles

---

**Types de modules PAM :**

| Type | Rôle | Exemples |
|------|------|----------|
| **auth** | Vérifier l'identité | Mot de passe, biométrie |
| **account** | Vérifier que le compte est valide | Expiré ? Accès autorisé ? |
| **password** | Changer le mot de passe | Gérer la complexité |
| **session** | Configurer la session | Créer /tmp, monter home |

**Contrôles possibles :**

| Contrôle | Signification |
|----------|---------------|
| **required** | DOIT réussir, continue même si échec |
| **requisite** | DOIT réussir, arrête immédiatement si échec |
| **sufficient** | Si réussit, OK (ignore les modules suivants) |
| **optional** | Résultat ignoré |

---

### ÉTAPE 7 : Configurer vsftpd pour les utilisateurs virtuels

**Éditer la configuration vsftpd :**

```bash
sudo nano /etc/vsftpd.conf
```

**Ajouter/modifier ces lignes (EN PLUS de la config de l'Exercice 1) :**

```conf
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION UTILISATEURS VIRTUELS
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# ACTIVER LES UTILISATEURS VIRTUELS
# ───────────────────────────────────────────────────────────────

# Désactiver les utilisateurs locaux (on utilise maintenant les virtuels)
local_enable=NO

# Activer les utilisateurs virtuels
guest_enable=YES

# Explication :
# guest_enable=YES active le mode "guest"
# 
# En mode guest, TOUS les utilisateurs (virtuels ou non)
# sont mappés vers un seul utilisateur Linux
# 
# C'est exactement ce qu'on veut !
# client1, client2, client3 -> tous deviennent "ftpvirtual"

# Définir l'utilisateur Linux de mapping
guest_username=ftpvirtual

# Explication :
# guest_username=ftpvirtual :
# Tous les utilisateurs virtuels sont exécutés avec l'UID de "ftpvirtual"
# 
# Quand client1 se connecte :
# 1. PAM valide "client1"
# 2. vsftpd le mappe vers "ftpvirtual" (UID 2001)
# 3. Tous les fichiers créés appartiennent à ftpvirtual

# ───────────────────────────────────────────────────────────────
# FICHIER PAM PERSONNALISÉ
# ───────────────────────────────────────────────────────────────

# Utiliser le fichier PAM spécifique pour les utilisateurs virtuels
pam_service_name=vsftpd_virtual

# Explication :
# Par défaut : pam_service_name=vsftpd
# vsftpd lit /etc/pam.d/vsftpd
# 
# Maintenant : pam_service_name=vsftpd_virtual
# vsftpd lit /etc/pam.d/vsftpd_virtual (créé à l'étape précédente)

# ───────────────────────────────────────────────────────────────
# CONFIGURATION PAR UTILISATEUR VIRTUEL
# ───────────────────────────────────────────────────────────────

# Activer les configurations spécifiques par utilisateur
user_config_dir=/etc/vsftpd/user_conf

# Explication DÉTAILLÉE :
# user_config_dir=/etc/vsftpd/user_conf
# 
# Pour chaque utilisateur virtuel, vsftpd cherche un fichier :
# /etc/vsftpd/user_conf/[username]
# 
# Exemple pour client1 :
# /etc/vsftpd/user_conf/client1
# 
# Ce fichier peut contenir des directives spécifiques :
# - local_root=/srv/ftp/client1  (chroot différent)
# - upload_max_rate=1000000      (limite vitesse upload)
# - download_max_rate=2000000    (limite vitesse download)
# - max_clients=5                (nombre max de connexions)
# - etc.
# 
# Permet une CONFIGURATION GRANULAIRE par utilisateur !

# ───────────────────────────────────────────────────────────────
# CHROOT POUR UTILISATEURS VIRTUELS
# ───────────────────────────────────────────────────────────────

# Activer le chroot pour les utilisateurs virtuels
chroot_local_user=YES

# Autoriser l'écriture dans le chroot (nécessaire)
allow_writeable_chroot=YES

# Explication :
# Ces directives s'appliquent maintenant aux utilisateurs virtuels
# (grâce à guest_enable=YES)
# 
# Chaque utilisateur sera chrooté dans SON répertoire
# (défini par local_root dans user_conf/)

# ───────────────────────────────────────────────────────────────
# PERMISSIONS ET SÉCURITÉ
# ───────────────────────────────────────────────────────────────

# Permettre l'écriture
write_enable=YES

# Umask pour les fichiers uploadés
local_umask=022

# Masquer les IDs utilisateur dans les listings
hide_ids=YES

# Explication de hide_ids :
# Sans hide_ids, la commande LIST affiche :
# -rw-r--r-- 1 2001 2001 1234 Dec 16 10:00 file.txt
#                ^    ^
#              UID  GID
# 
# Avec hide_ids=YES, affiche :
# -rw-r--r-- 1 ftp ftp 1234 Dec 16 10:00 file.txt
# 
# Plus propre pour le client FTP
# Cache le fait que tous les fichiers appartiennent au même UID

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

### ÉTAPE 8 : Créer les configurations par utilisateur

**Créer le dossier pour les configurations par utilisateur :**

```bash
sudo mkdir -p /etc/vsftpd/user_conf
```

---

**Créer la configuration pour client1 :**

```bash
sudo nano /etc/vsftpd/user_conf/client1
```

**Contenu :**

```conf
# Configuration spécifique pour client1

# Répertoire racine (chroot) pour cet utilisateur
local_root=/srv/ftp/client1

# Explication :
# Quand client1 se connecte, il sera chrooté dans /srv/ftp/client1
# Il verra :
# /              (en fait /srv/ftp/client1)
# ├── www/
# └── backups/
# 
# Il ne peut PAS sortir de /srv/ftp/client1

# Limiter la vitesse d'upload (optionnel)
# local_max_rate=1000000  (1 MB/s)

# Limiter la vitesse de download (optionnel)
# anon_max_rate=2000000  (2 MB/s)

# Note : Ces limites sont optionnelles
# Utile pour éviter qu'un client sature la bande passante
```

**Sauvegarde.**

---

**Créer les configurations pour client2 et client3 :**

```bash
# Client2
sudo nano /etc/vsftpd/user_conf/client2
```

**Contenu :**

```conf
local_root=/srv/ftp/client2
```

---

```bash
# Client3
sudo nano /etc/vsftpd/user_conf/client3
```

**Contenu :**

```conf
local_root=/srv/ftp/client3
```

---

**Vérifier la structure :**

```bash
ls -l /etc/vsftpd/user_conf/
```

**Résultat :**

```
-rw-r--r-- 1 root root 123 Dec 16 11:30 client1
-rw-r--r-- 1 root root  32 Dec 16 11:30 client2
-rw-r--r-- 1 root root  32 Dec 16 11:30 client3
```

**[OK] Configurations par utilisateur créées !**

---

### ÉTAPE 9 : Redémarrer vsftpd et tester

**Redémarrer vsftpd pour appliquer la configuration :**

```bash
sudo systemctl restart vsftpd
```

---

**Vérifier que vsftpd redémarre correctement :**

```bash
sudo systemctl status vsftpd
```

**Résultat :**

```
[BLACK_CIRCLE] vsftpd.service - vsftpd FTP server
     Active: active (running) since Mon 2024-12-16 11:35:00 UTC; 5s ago
```

**[OK] vsftpd redémarré !**

---

**Tester la connexion avec client1 :**

```bash
ftp localhost
```

**Entrer :**

```
Name: client1
Password: ClientPass1!
```

**Résultat :**

```
Connected to localhost.
220 Bienvenue sur le serveur FTP de l'entreprise
Name (localhost:user): client1
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
```

**[OK] Authentification réussie !**

---

**Vérifier le chroot :**

```
ftp> pwd
```

**Résultat :**

```
257 "/" is the current directory
```

**[OK] Chroot actif (/ = /srv/ftp/client1)**

---

**Lister les fichiers :**

```
ftp> ls
```

**Résultat :**

```
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 backups
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 www
226 Directory send OK.
```

**[OK] Les dossiers www/ et backups/ sont visibles !**

**Note : `ftp ftp` grâce à `hide_ids=YES`**

---

**Tenter de sortir du chroot :**

```
ftp> cd ../client2
```

**Résultat :**

```
550 Failed to change directory.
```

**[OK] Impossible d'accéder aux autres clients !**

---

**Naviguer dans www/ :**

```
ftp> cd www
250 Directory successfully changed.

ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp            25 Dec 16 11:00 index.html
226 Directory send OK.
```

**[OK] Fichiers visibles !**

---

**Télécharger un fichier :**

```
ftp> get index.html
local: index.html remote: index.html
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for index.html (25 bytes).
226 Transfer complete.
25 bytes received in 0.00 secs (243.16 kB/s)
```

**[OK] Download OK !**

---

**Envoyer un fichier :**

```
ftp> !echo "Nouveau fichier" > newfile.txt
ftp> put newfile.txt
local: newfile.txt remote: newfile.txt
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
16 bytes sent in 0.00 secs (156.25 kB/s)
```

**[OK] Upload OK !**

---

**Vérifier sur le serveur :**

```bash
sudo ls -lh /srv/ftp/client1/www/
```

**Résultat :**

```
-rw-r--r-- 1 ftpvirtual ftpvirtual   25 Dec 16 11:00 index.html
-rw-r--r-- 1 ftpvirtual ftpvirtual   16 Dec 16 11:40 newfile.txt
```

**[OK] Fichier uploadé appartient bien à ftpvirtual !**

---

**Quitter :**

```
ftp> quit
221 Goodbye.
```

---

**Tester avec client2 :**

```bash
ftp localhost
```

**Entrer :**

```
Name: client2
Password: ClientPass2!
```

**Résultat :**

```
230 Login successful.
ftp> pwd
257 "/" is the current directory

ftp> ls
200 PORT command successful.
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 backups
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 www
226 Directory send OK.
```

**[OK] client2 voit SON répertoire (/srv/ftp/client2)**

**[X] Ne voit PAS /srv/ftp/client1**

**[OK] Isolation complète !**

---

### [OK] TESTS DE VALIDATION

**1. Authentification des utilisateurs virtuels**

- [ ] Se connecter avec client1 : Succès
- [ ] Se connecter avec client2 : Succès
- [ ] Se connecter avec client3 : Succès
- [ ] Se connecter avec un utilisateur inexistant : Refusé (530 Login incorrect)

---

**2. Chroot et isolation**

- [ ] client1 voit /srv/ftp/client1 (et seulement ça)
- [ ] client2 voit /srv/ftp/client2 (et seulement ça)
- [ ] Impossible de faire `cd ../client2` depuis client1
- [ ] `pwd` affiche `/` (chroot actif)

---

**3. Permissions**

- [ ] Upload dans www/ : Succès
- [ ] Upload dans backups/ : Succès
- [ ] Tentative d'upload à la racine (/) : Échoue (550 Permission denied)
- [ ] Fichiers uploadés appartiennent à ftpvirtual (UID 2001)

---

**4. Vérifier le mapping vers ftpvirtual**

```bash
# Pendant qu'un utilisateur est connecté, vérifier les processus
sudo ps aux | grep vsftpd
```

**Résultat :**

```
root      12345  vsftpd: LISTENER
ftpvirt+  12346  vsftpd: [client1]
```

**[OK] Le processus FTP de client1 tourne sous ftpvirtual !**

---

**5. Logs**

```bash
sudo tail -20 /var/log/vsftpd.log
```

**Résultat (exemple) :**

```
Mon Dec 16 11:40:00 2024 1 192.168.1.50 25 /www/index.html b _ o r client1 ftp 0 * c
Mon Dec 16 11:40:15 2024 0 192.168.1.50 16 /www/newfile.txt b _ i r client1 ftp 0 * c
```

**[OK] Les logs affichent "client1", pas "ftpvirtual"**

**vsftpd log le nom de l'utilisateur virtuel, pas l'utilisateur mappé.**

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "530 Login incorrect" avec un utilisateur virtuel

**Symptôme :**

```
Name: client1
Password: ClientPass1!
530 Login incorrect.
```

**Causes possibles :**

**1. Base de données Berkeley DB introuvable ou corrompue**

Vérifier :

```bash
sudo ls -lh /etc/vsftpd/virtual_users.db
```

Si absent, recréer la BDD (voir ÉTAPE 5).

---

**2. Fichier PAM incorrect**

Vérifier :

```bash
cat /etc/pam.d/vsftpd_virtual
```

Doit contenir :

```
auth required pam_userdb.so db=/etc/vsftpd/virtual_users
```

**[ATTENTION] SANS .db à la fin !**

---

**3. vsftpd n'utilise pas le bon fichier PAM**

Dans `/etc/vsftpd.conf`, vérifier :

```conf
pam_service_name=vsftpd_virtual
```

Redémarrer :

```bash
sudo systemctl restart vsftpd
```

---

**4. Mot de passe incorrect dans la BDD**

Recréer la BDD avec le bon mot de passe.

---

#### Erreur 2 : "500 OOPS: cannot change directory"

**Symptôme :**

```
230 Login successful.
500 OOPS: cannot change directory:/srv/ftp/client1
```

**Causes possibles :**

**1. Le répertoire n'existe pas**

```bash
sudo ls -ld /srv/ftp/client1
```

Si absent :

```bash
sudo mkdir -p /srv/ftp/client1/{www,backups}
sudo chown -R ftpvirtual:ftpvirtual /srv/ftp/client1
```

---

**2. Permissions incorrectes**

```bash
sudo chmod 555 /srv/ftp/client1
sudo chmod 755 /srv/ftp/client1/www
sudo chmod 755 /srv/ftp/client1/backups
```

---

**3. `local_root` incorrect dans user_conf**

Vérifier `/etc/vsftpd/user_conf/client1` :

```conf
local_root=/srv/ftp/client1
```

---

#### Erreur 3 : "550 Permission denied" lors d'un upload

**Symptôme :**

```
ftp> put file.txt
550 Permission denied.
```

**Causes possibles :**

**1. Tentative d'upload à la racine du chroot**

La racine (/srv/ftp/client1) est en lecture seule (555).

**Solution : Uploader dans www/ ou backups/**

```
ftp> cd www
ftp> put file.txt
```

---

**2. Permissions insuffisantes sur le sous-dossier**

```bash
sudo chmod 755 /srv/ftp/client1/www
sudo chown ftpvirtual:ftpvirtual /srv/ftp/client1/www
```

---

**3. `write_enable=NO` dans la config**

Dans `/etc/vsftpd.conf`, vérifier :

```conf
write_enable=YES
```

---

#### Erreur 4 : Les utilisateurs virtuels peuvent voir les fichiers des autres

**Symptôme :**

client1 peut faire `cd ../client2`

**Cause : Chroot non configuré ou désactivé**

**Solution :**

Dans `/etc/vsftpd.conf` :

```conf
chroot_local_user=YES
guest_enable=YES
```

Dans `/etc/vsftpd/user_conf/client1` :

```conf
local_root=/srv/ftp/client1
```

Redémarrer vsftpd.

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. Utilisateurs virtuels**
- N'existent PAS dans /etc/passwd
- Stockés dans une base de données séparée (Berkeley DB, MySQL, etc.)
- Tous mappés vers un seul UID/GID Linux
- Aucun accès SSH (pas de shell)

**2. PAM (Pluggable Authentication Modules)**
- Couche d'abstraction pour l'authentification
- Permet d'utiliser différents backends (BDD, LDAP, etc.)
- Fichiers dans `/etc/pam.d/`
- Modules : auth, account, session, password

**3. Guest mode**
- `guest_enable=YES` active le mapping
- `guest_username=ftpvirtual` définit l'utilisateur de mapping
- Tous les utilisateurs virtuels deviennent ftpvirtual (UID unique)

**4. user_config_dir**
- Permet des configurations spécifiques par utilisateur
- `/etc/vsftpd/user_conf/[username]`
- Directives possibles : local_root, max_rate, etc.

**5. Structure de permissions**
- Racine chroot : 555 (lecture seule)
- Sous-dossiers : 755 (lecture-écriture)
- Évite l'erreur "writable root inside chroot"

**6. Berkeley DB**
- Base de données clé-valeur très rapide
- Format binaire (pas texte)
- Outils : db_load, db_dump
- TOUJOURS protéger (chmod 600)

**7. Isolation**
- Chaque utilisateur virtuel a son propre chroot
- Ne peut PAS voir les autres clients
- Fichiers appartiennent tous à ftpvirtual mais isolés par répertoire

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Utiliser MySQL au lieu de Berkeley DB**

**Installer les modules nécessaires :**

```bash
sudo apt install libpam-mysql -y
```

**Créer une base de données MySQL :**

```sql
CREATE DATABASE vsftpd;
USE vsftpd;

CREATE TABLE users (
    username VARCHAR(50) NOT NULL PRIMARY KEY,
    password VARCHAR(255) NOT NULL
);

INSERT INTO users VALUES
('client1', MD5('ClientPass1!')),
('client2', MD5('ClientPass2!')),
('client3', MD5('ClientPass3!'));
```

**Configurer PAM :**

```bash
sudo nano /etc/pam.d/vsftpd_virtual
```

```
auth required pam_mysql.so user=vsftpd_user passwd=password host=localhost db=vsftpd table=users usercolumn=username passwdcolumn=password crypt=1
account required pam_permit.so
```

**Avantages :**
- [OK] Gestion centralisée (interface web possible)
- [OK] Réplication MySQL pour haute disponibilité
- [OK] Intégration avec d'autres applications

---

**2. Quotas de disque par utilisateur virtuel**

**Avec des utilisateurs réels, on utiliserait les quotas Linux.**

**Avec des utilisateurs virtuels, on peut utiliser vsftpd's `quota` :**

Dans `/etc/vsftpd/user_conf/client1` :

```conf
local_root=/srv/ftp/client1
quota_enabled=YES
quota_soft_limit=100000000   # 100 MB soft
quota_hard_limit=150000000   # 150 MB hard
```

**Ou utiliser un script externe qui vérifie la taille avec `du` :**

```bash
#!/bin/bash
SIZE=$(du -sb /srv/ftp/client1 | cut -f1)
MAX=150000000  # 150 MB

if [ $SIZE -gt $MAX ]; then
    echo "Quota dépassé pour client1"
    # Désactiver temporairement l'upload
fi
```

---

**3. Automatiser la création d'utilisateurs virtuels**

**Script de création :**

```bash
#!/bin/bash
# add_ftp_user.sh

USERNAME=$1
PASSWORD=$2

if [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
    echo "Usage: $0 <username> <password>"
    exit 1
fi

# Créer la structure de dossiers
mkdir -p /srv/ftp/$USERNAME/{www,backups}
chmod 555 /srv/ftp/$USERNAME
chmod 755 /srv/ftp/$USERNAME/www
chmod 755 /srv/ftp/$USERNAME/backups
chown -R ftpvirtual:ftpvirtual /srv/ftp/$USERNAME

# Ajouter à la base de données Berkeley DB
echo "$USERNAME" >> /tmp/virtual_users.txt
echo "$PASSWORD" >> /tmp/virtual_users.txt
db_load -T -t hash -f /tmp/virtual_users.txt /etc/vsftpd/virtual_users.db
rm /tmp/virtual_users.txt
chmod 600 /etc/vsftpd/virtual_users.db

# Créer la config spécifique
echo "local_root=/srv/ftp/$USERNAME" > /etc/vsftpd/user_conf/$USERNAME

# Redémarrer vsftpd
systemctl restart vsftpd

echo "Utilisateur $USERNAME créé avec succès !"
```

**Utilisation :**

```bash
sudo ./add_ftp_user.sh client4 ClientPass4!
```

---

**4. Logs détaillés par utilisateur**

**Créer un dossier de logs par utilisateur :**

Dans `/etc/vsftpd/user_conf/client1` :

```conf
local_root=/srv/ftp/client1
xferlog_file=/var/log/vsftpd/client1.log
```

**Créer le dossier :**

```bash
sudo mkdir -p /var/log/vsftpd
sudo chown root:root /var/log/vsftpd
sudo chmod 755 /var/log/vsftpd
```

**Chaque client aura son propre fichier de log.**

---

**5. Interface web de gestion**

**Créer une interface web (PHP + MySQL) pour :**
- Créer/supprimer des utilisateurs virtuels
- Réinitialiser les mots de passe
- Voir les statistiques d'utilisation
- Gérer les quotas

**Frameworks possibles :**
- Laravel (PHP)
- Django (Python)
- Flask (Python)

---

## [COURS] CONCLUSION DE L'EXERCICE 2

**[OK] Félicitations ! Tu maîtrises maintenant les utilisateurs virtuels FTP !**

**Ce que tu as appris :**
- Différence entre utilisateurs réels et virtuels
- Créer une base de données Berkeley DB
- Configurer PAM pour l'authentification personnalisée
- Mapper des utilisateurs virtuels vers un UID unique
- Configurer des chroots différents par utilisateur avec `user_config_dir`
- Gérer les permissions complexes pour FTP
- Isoler complètement les clients

**Compétences acquises :**
- [OK] FTP (niveau intermédiaire-avancé)
- [OK] Utilisateurs virtuels vsftpd
- [OK] PAM (Pluggable Authentication Modules)
- [OK] Berkeley DB
- [OK] Architecture multi-tenants
- [OK] Gestion de permissions avancée

**Temps moyen de réalisation :** 2-3 heures

**Prochaine étape :** Exercice 3 - FTPS (FTP sécurisé avec SSL/TLS) ! [VERROUILLE]

---

---

(Le document continue avec les exercices 3, 4 et 5... Veux-tu que je continue avec les 3 derniers exercices dans le même niveau de détail ?)


# [JAUNE] EXERCICE 3 : FTPS (FTP SÉCURISÉ AVEC SSL/TLS)

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système dans une entreprise qui manipule des données sensibles (documents financiers, données clients, propriété intellectuelle). L'audit de sécurité vient de révéler une **faille critique** :

> [ATTENTION] "Le serveur FTP transmet les identifiants et les données EN CLAIR sur le réseau. N'importe qui peut intercepter les mots de passe avec Wireshark !"

Le RSSI (Responsable Sécurité) exige immédiatement :
- Chiffrement de TOUTES les communications FTP
- Authentification sécurisée (pas de mots de passe en clair)
- Certificats SSL/TLS valides
- Conformité aux standards de sécurité

**Solution : FTPS (FTP over SSL/TLS)**

### Différence FTP vs FTPS vs SFTP

**Attention : FTPS ≠ SFTP !**

| Protocole | Port(s) | Chiffrement | Base | Utilisation |
|-----------|---------|-------------|------|-------------|
| **FTP** | 21 (contrôle)<br>20 (données) | [X] Aucun | Protocole FTP | [X] Obsolète |
| **FTPS** | 21 (contrôle)<br>20 ou passif (données) | [OK] SSL/TLS | FTP + SSL/TLS | [OK] Recommandé |
| **SFTP** | 22 | [OK] SSH | SSH | [OK] Alternative (SSH) |

**FTPS = FTP + SSL/TLS** (comme HTTPS = HTTP + SSL/TLS)

**SFTP = SSH File Transfer Protocol** (protocole complètement différent)

**Dans cet exercice, on configure FTPS (pas SFTP) !**

---

### Modes FTPS

**Il existe 2 modes FTPS :**

**1. FTPS Explicite (FTPES - FTP Explicit SSL)**
```
Client -> Serveur (port 21, non chiffré)
Client : "AUTH TLS" (demande chiffrement)
Serveur -> Client : "234 Proceed with negotiation"
[Négociation SSL/TLS]
-> Canal de contrôle chiffré établi
-> Canal de données chiffré
```

**Avantages :**
- [OK] Compatible avec FTP classique (même port 21)
- [OK] Le client choisit (SSL ou pas)
- [OK] Plus flexible

**2. FTPS Implicite (FTPIS - FTP Implicit SSL)**
```
Client -> Serveur (port 990, chiffré dès le début)
[Connexion SSL/TLS immédiate]
-> Tout est chiffré depuis la première byte
```

**Avantages :**
- [OK] Plus sécurisé (chiffrement obligatoire)
- [OK] Pas de phase non chiffrée

**[ATTENTION] Déprécié ! FTPS Explicite est le standard moderne.**

**Dans cet exercice : FTPS Explicite (AUTH TLS)**

---

### Objectifs techniques

- Créer un certificat SSL auto-signé pour le serveur
- Configurer vsftpd pour FTPS Explicite (AUTH TLS)
- Forcer le chiffrement (interdire FTP plain)
- Configurer les suites de chiffrement sécurisées
- Tester avec FileZilla et clients CLI
- Vérifier le chiffrement avec Wireshark/tcpdump

### Cahier des charges

**Sécurité :**
- Certificat SSL valide (auto-signé pour l'exercice)
- TLS 1.2+ uniquement (pas SSLv2/SSLv3/TLS 1.0)
- Chiffrement AES-256 minimum
- Forcer SSL pour toutes les connexions
- Pas de fallback en FTP plain

**Fonctionnalités :**
- FTPS Explicite (port 21 + AUTH TLS)
- Mode passif SSL
- Compatible FileZilla et autres clients FTPS
- Utilisateurs virtuels (de l'Exercice 2)

**Contraintes :**
- vsftpd avec support SSL
- OpenSSL pour les certificats
- Tests avec Wireshark pour vérifier le chiffrement
- Temps estimé : 2-3 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre les failles de sécurité de FTP plain
- [OK] Différencier FTPS, SFTP, FTP
- [OK] Créer un certificat SSL auto-signé avec OpenSSL
- [OK] Configurer vsftpd pour FTPS Explicite
- [OK] Configurer les protocoles SSL/TLS sécurisés
- [OK] Forcer le chiffrement (interdire FTP plain)
- [OK] Tester FTPS avec FileZilla
- [OK] Vérifier le chiffrement avec tcpdump/Wireshark
- [OK] Diagnostiquer les problèmes SSL/TLS

---

## [DOCS] PRÉREQUIS

- Exercices 1 et 2 terminés (vsftpd fonctionnel)
- Compréhension de base de SSL/TLS
- Notions de cryptographie asymétrique
- Client FTP supportant FTPS (FileZilla)

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Comprendre les failles de sécurité de FTP

#### Démonstration : Capture de mot de passe FTP en clair

**Avant de sécuriser, démontrons pourquoi FTP est dangereux.**

**Installer tcpdump (si pas déjà installé) :**

```bash
sudo apt install tcpdump -y
```

---

**Terminal 1 : Capturer le trafic FTP**

```bash
# Capturer tout le trafic sur le port 21
sudo tcpdump -i any -A 'port 21'
```

**Explication :**
- `-i any` = Toutes les interfaces réseau
- `-A` = Afficher le contenu en ASCII (lisible)
- `'port 21'` = Filtrer seulement le port 21 (FTP)

---

**Terminal 2 : Se connecter en FTP classique**

```bash
ftp localhost
```

**Entrer :**
```
Name: ftpuser1
Password: FtpPass123!
```

---

**Résultat dans Terminal 1 (tcpdump) :**

```
10:00:00.123456 IP localhost.54321 > localhost.ftp: Flags [P.], seq 1:14, ack 1, win 512, length 13
USER ftpuser1

10:00:02.234567 IP localhost.54321 > localhost.ftp: Flags [P.], seq 14:30, ack 2, win 512, length 16
PASS FtpPass123!
```

**[SKULL] LE MOT DE PASSE EST VISIBLE EN CLAIR ! [SKULL]**

**N'importe qui sur le réseau peut voir :**
- Le nom d'utilisateur : `ftpuser1`
- Le mot de passe : `FtpPass123!`
- Les fichiers transférés
- Le contenu des fichiers

**C'est comme envoyer une carte postale : tout le monde peut lire !**

---

#### Pourquoi c'est dangereux en production ?

**Scénarios d'attaque :**

**1. Sniffing sur réseau Wi-Fi public**
```
[Attaquant] <- Wi-Fi public -> [Victime]
           v
    Wireshark actif
    Capture : USER admin
              PASS SuperSecret2024!
```

**2. Man-in-the-Middle (MITM)**
```
[Client] -> [Attaquant] -> [Serveur]
              v
        Enregistre tout
        Peut modifier les fichiers !
```

**3. Réseau d'entreprise compromis**
```
[Employé] -> [Switch réseau] -> [Serveur FTP]
                v
            [Attaquant]
        (accès physique ou malware)
```

---

**Solution : FTPS (chiffrement de bout en bout)**

```
[Client] <-── SSL/TLS (chiffré) ──-> [Serveur]

Attaquant voit :
�x�2�f�@��K�~���H���...
(Données chiffrées = illisibles)
```

---

### ÉTAPE 2 : Vérifier que vsftpd supporte SSL

**vsftpd est compilé avec le support SSL sur Ubuntu/Debian par défaut.**

**Vérifier :**

```bash
ldd /usr/sbin/vsftpd | grep ssl
```

**Résultat attendu :**

```
libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3
```

**[OK] vsftpd est lié à libssl (support SSL présent)**

**Si aucune sortie, vsftpd doit être recompilé avec SSL (rare).**

---

### ÉTAPE 3 : Créer le certificat SSL auto-signé

**Pour FTPS, on a besoin de :**
1. **Clé privée** (.key) - Gardée secrète sur le serveur
2. **Certificat SSL** (.crt) - Envoyé aux clients

**Créer le dossier pour les certificats :**

```bash
sudo mkdir -p /etc/ssl/private
```

---

**Générer la clé privée + certificat en une commande :**

```bash
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt
```

**Décortiquons cette commande complexe :**

---

**`openssl`**
- Outil de cryptographie en ligne de commande

**`req`**
- Sous-commande pour créer des demandes de certificat (CSR)
- Ou des certificats auto-signés (avec `-x509`)

**`-x509`**
- Génère un certificat X.509 auto-signé
- X.509 = Standard pour les certificats SSL/TLS
- Sans `-x509`, génère une CSR (Certificate Signing Request)

**`-nodes`**
- NO DES (Data Encryption Standard)
- La clé privée ne sera PAS protégée par mot de passe
- Nécessaire pour vsftpd (démarrage automatique)
- Sinon, il faudrait entrer le mot de passe à chaque redémarrage

**`-days 365`**
- Validité du certificat : 365 jours (1 an)
- Après 1 an, le certificat expire
- En production : Let's Encrypt (90 jours, renouvellement auto)

**`-newkey rsa:2048`**
- Génère une NOUVELLE clé RSA de 2048 bits
- RSA = Rivest-Shamir-Adleman (algorithme de chiffrement asymétrique)
- 2048 bits = Sécurité suffisante (recommandation NIST)
- Aujourd'hui, 4096 bits est encore mieux

**`-keyout /etc/ssl/private/vsftpd.key`**
- Chemin de sortie de la clé PRIVÉE
- `/etc/ssl/private/` = Emplacement standard pour les clés privées

**`-out /etc/ssl/certs/vsftpd.crt`**
- Chemin de sortie du CERTIFICAT
- `/etc/ssl/certs/` = Emplacement standard pour les certificats

---

**OpenSSL demande des informations pour le certificat :**

```
Country Name (2 letter code) [AU]:
```

**Entre :** `SN` (Sénégal) ou ton code pays

---

```
State or Province Name (full name) [Some-State]:
```

**Entre :** `Dakar`

---

```
Locality Name (eg, city) []:
```

**Entre :** `Dakar`

---

```
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
```

**Entre :** `Mon Entreprise` ou nom de ton organisation

---

```
Organizational Unit Name (eg, section) []:
```

**Entre :** `IT` ou laisse vide (Entrée)

---

```
Common Name (e.g. server FQDN or YOUR name) []:
```

**[ATTENTION] LE PLUS IMPORTANT !**

**Entre le nom de domaine ou l'IP du serveur :**

```
ftp.example.com
```

**Ou si pas de domaine :**

```
192.168.1.100
```

**Le Common Name (CN) DOIT correspondre à l'adresse utilisée par les clients.**

**Si le client se connecte à `ftp.example.com`, le CN doit être `ftp.example.com`**

**Sinon : Erreur de certificat dans le client FTP.**

---

```
Email Address []:
```

**Entre :** `admin@example.com` ou laisse vide

---

**Résultat :**

```
Generating a RSA private key
....+++++
.............+++++
writing new private key to '/etc/ssl/private/vsftpd.key'
-----
```

**[OK] Certificat et clé créés !**

---

**Vérifier les fichiers créés :**

```bash
ls -lh /etc/ssl/private/vsftpd.key /etc/ssl/certs/vsftpd.crt
```

**Résultat :**

```
-rw-r--r-- 1 root root 1.3K Dec 16 12:00 /etc/ssl/certs/vsftpd.crt
-rw------- 1 root root 1.7K Dec 16 12:00 /etc/ssl/private/vsftpd.key
```

**Permissions de la clé privée : 600 (rw-------)** [OK]

**SEUL root peut lire la clé privée !**

---

**Examiner le certificat :**

```bash
sudo openssl x509 -in /etc/ssl/certs/vsftpd.crt -text -noout
```

**Résultat (extrait) :**

```
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            xx:xx:xx:xx:xx:xx:xx:xx
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = SN, ST = Dakar, L = Dakar, O = Mon Entreprise, CN = ftp.example.com
        Validity
            Not Before: Dec 16 12:00:00 2024 GMT
            Not After : Dec 16 12:00:00 2025 GMT
        Subject: C = SN, ST = Dakar, L = Dakar, O = Mon Entreprise, CN = ftp.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:xx:xx:xx:...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                xx:xx:xx:...
    Signature Algorithm: sha256WithRSAEncryption
         xx:xx:xx:...
```

**Points importants :**

**Issuer = Subject**
```
Issuer: ... CN = ftp.example.com
Subject: ... CN = ftp.example.com
```

**Identiques = Certificat auto-signé** [OK]

**Validité :**
```
Not Before: Dec 16 12:00:00 2024 GMT
Not After : Dec 16 12:00:00 2025 GMT
```

**Valide pendant 1 an** [OK]

**Clé publique :**
```
RSA Public-Key: (2048 bit)
```

**Taille : 2048 bits** [OK]

---

### ÉTAPE 4 : Configurer vsftpd pour FTPS Explicite

**Éditer la configuration vsftpd :**

```bash
sudo nano /etc/vsftpd.conf
```

**Ajouter ces lignes à la fin :**

```conf
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION FTPS (FTP OVER SSL/TLS)
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# ACTIVER SSL/TLS
# ───────────────────────────────────────────────────────────────

# Activer le support SSL
ssl_enable=YES

# Explication :
# ssl_enable=YES active le support SSL/TLS dans vsftpd
# Sans cette directive, FTPS est impossible
# 
# Le serveur acceptera maintenant la commande AUTH TLS

# ───────────────────────────────────────────────────────────────
# CERTIFICATS SSL
# ───────────────────────────────────────────────────────────────

# Chemin du certificat RSA (clé publique)
rsa_cert_file=/etc/ssl/certs/vsftpd.crt

# Chemin de la clé privée RSA
rsa_private_key_file=/etc/ssl/private/vsftpd.key

# Explication :
# rsa_cert_file = Certificat SSL (envoyé aux clients)
# rsa_private_key_file = Clé privée (gardée secrète)
# 
# Ces deux fichiers DOIVENT correspondre !
# Le certificat contient la clé publique
# dérivée de la clé privée
# 
# Workflow SSL/TLS :
# 1. Client se connecte
# 2. Serveur envoie rsa_cert_file (certificat)
# 3. Client vérifie le certificat
# 4. Génération d'une clé de session (chiffrement symétrique)
# 5. Chiffrement avec la clé de session (AES-256, etc.)

# ───────────────────────────────────────────────────────────────
# FORCER LE CHIFFREMENT
# ───────────────────────────────────────────────────────────────

# Forcer SSL pour les connexions de données (upload/download)
force_local_data_ssl=YES

# Explication :
# force_local_data_ssl=YES :
# Le canal de DONNÉES (transfert de fichiers) DOIT être chiffré
# 
# Si un client tente d'envoyer des données sans SSL :
# 522 SSL connection failed; session reuse required
# 
# Sans cette directive (=NO) :
# Le canal de contrôle peut être SSL
# Mais les données peuvent être en clair (FAILLE !)

# Forcer SSL pour les commandes (canal de contrôle)
force_local_logins_ssl=YES

# Explication :
# force_local_logins_ssl=YES :
# L'AUTHENTIFICATION DOIT se faire via SSL
# 
# Le client DOIT envoyer "AUTH TLS" avant USER/PASS
# Sinon : connexion refusée
# 
# Empêche l'envoi de mots de passe en clair

# ───────────────────────────────────────────────────────────────
# PROTOCOLES SSL/TLS
# ───────────────────────────────────────────────────────────────

# Versions TLS autorisées (désactiver SSLv2/SSLv3/TLS 1.0/1.1)
ssl_tlsv1_2=YES
ssl_tlsv1_3=YES
ssl_sslv2=NO
ssl_sslv3=NO
ssl_tlsv1=NO
ssl_tlsv1_1=NO

# Explication COMPLÈTE :
# 
# Histoire des protocoles SSL/TLS :
# 
# SSLv2 (1995) :
# [X] Obsolète, TRÈS vulnérable
# [X] Attaques : DROWN, etc.
# [X] Désactivé partout depuis 2011
# 
# SSLv3 (1996) :
# [X] Obsolète, vulnérable
# [X] Attaque POODLE (2014)
# [X] Désactivé partout depuis 2015
# 
# TLS 1.0 (1999) :
# [ATTENTION] Obsolète mais encore utilisé
# [ATTENTION] Vulnérabilités connues
# [X] PCI-DSS l'interdit depuis 2018
# 
# TLS 1.1 (2006) :
# [ATTENTION] Obsolète
# [X] Navigateurs modernes le désactivent
# [X] PCI-DSS l'interdit depuis 2018
# 
# TLS 1.2 (2008) :
# [OK] Sécurisé (si bien configuré)
# [OK] Standard actuel
# [OK] Support universel
# 
# TLS 1.3 (2018) :
# [OK] Plus sécurisé et plus rapide
# [OK] Handshake simplifié
# [OK] Pas de cipher suites faibles
# [ATTENTION] Pas encore supporté partout
# 
# Configuration recommandée 2024 :
# - Minimum : TLS 1.2
# - Idéal : TLS 1.2 + TLS 1.3
# 
# Notre config :
# ssl_tlsv1_2=YES   [OK]
# ssl_tlsv1_3=YES   [OK]
# ssl_sslv2=NO      [OK]
# ssl_sslv3=NO      [OK]
# ssl_tlsv1=NO      [OK]
# ssl_tlsv1_1=NO    [OK]

# ───────────────────────────────────────────────────────────────
# SUITES DE CHIFFREMENT (CIPHER SUITES)
# ───────────────────────────────────────────────────────────────

# Définir les cipher suites autorisées (sécurisées uniquement)
ssl_ciphers=HIGH:!aNULL:!MD5:!3DES:!RC4:!DES

# Explication DÉTAILLÉE des cipher suites :
# 
# Une cipher suite définit 4 algorithmes :
# 1. Échange de clés (ex: ECDHE, RSA)
# 2. Authentification (ex: RSA, ECDSA)
# 3. Chiffrement symétrique (ex: AES-256-GCM)
# 4. Fonction de hachage (ex: SHA256, SHA384)
# 
# Exemple de cipher suite complète :
# ECDHE-RSA-AES256-GCM-SHA384
# ├─ ECDHE : Échange de clés (Elliptic Curve Diffie-Hellman Ephemeral)
# ├─ RSA : Authentification
# ├─ AES256-GCM : Chiffrement symétrique (AES 256 bits, mode GCM)
# └─ SHA384 : Fonction de hachage
# 
# Notre configuration : ssl_ciphers=HIGH:!aNULL:!MD5:!3DES:!RC4:!DES
# 
# HIGH :
# Utilise UNIQUEMENT les cipher suites "HIGH" (fort chiffrement)
# Généralement : AES-256, AES-128, ChaCha20
# 
# !aNULL :
# Interdit les cipher suites sans authentification (aNULL)
# aNULL = Anonymous NULL (pas d'authentification du serveur)
# [X] TRÈS DANGEREUX (Man-in-the-Middle facile)
# 
# !MD5 :
# Interdit MD5 (Message Digest 5)
# MD5 est cassé (collisions possibles)
# [X] Ne plus utiliser depuis 2004
# 
# !3DES :
# Interdit 3DES (Triple DES)
# 3DES est lent et vulnérable (attaque Sweet32)
# [X] Obsolète depuis 2016
# 
# !RC4 :
# Interdit RC4 (Rivest Cipher 4)
# RC4 a des faiblesses cryptographiques
# [X] Interdit par RFC 7465 (2015)
# 
# !DES :
# Interdit DES (Data Encryption Standard)
# DES utilise des clés de 56 bits (TRÈS faible)
# [X] Cassable en quelques heures
# 
# Résultat de notre config :
# Cipher suites autorisées (exemples) :
# - ECDHE-RSA-AES256-GCM-SHA384
# - ECDHE-RSA-AES128-GCM-SHA256
# - ECDHE-RSA-CHACHA20-POLY1305
# - DHE-RSA-AES256-GCM-SHA384
# 
# Cipher suites REFUSÉES :
# - NULL-MD5                     (aNULL)
# - DES-CBC-SHA                  (DES)
# - RC4-SHA                      (RC4)
# - DES-CBC3-SHA                 (3DES)
# 
# Configuration avancée (optionnelle) :
# ssl_ciphers=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305

# ───────────────────────────────────────────────────────────────
# AUTRES OPTIONS SSL
# ───────────────────────────────────────────────────────────────

# Demander le certificat client (optionnel, pour authentification mutuelle)
# require_cert=NO

# Explication :
# require_cert=YES :
# Le CLIENT doit aussi présenter un certificat SSL
# Authentification mutuelle (mTLS)
# 
# Utile pour :
# - Sécurité maximale (double authentification)
# - Restreindre l'accès à des clients spécifiques
# 
# Inconvénient :
# Complexe à gérer (distribuer des certificats aux clients)
# 
# Pour cet exercice : require_cert=NO (pas nécessaire)

# Valider le certificat client (si require_cert=YES)
# validate_cert=NO

# Explication :
# validate_cert=YES :
# Vérifie que le certificat client est signé par une CA reconnue
# 
# validate_cert=NO :
# Accepte n'importe quel certificat client (même auto-signé)

# Autoriser la réutilisation de session SSL
ssl_reuse=YES

# Explication :
# ssl_reuse=YES :
# Les sessions SSL peuvent être réutilisées
# 
# Workflow sans ssl_reuse :
# 1. Connexion contrôle : Handshake SSL (coûteux)
# 2. Connexion données : NOUVEAU handshake SSL (coûteux)
# 3. Transfert
# 4. Fermeture données
# 5. Nouvelle connexion données : ENCORE un handshake !
# 
# Workflow avec ssl_reuse :
# 1. Connexion contrôle : Handshake SSL
# 2. Connexion données : Réutilise la session SSL (rapide !)
# 3. Transfert
# 4. Fermeture données
# 5. Nouvelle connexion données : Réutilise toujours !
# 
# Avantages :
# [OK] Plus rapide (pas de handshake répété)
# [OK] Moins de CPU
# 
# Recommandation : ssl_reuse=YES

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde : `Ctrl + O`, `Entrée`, `Ctrl + X`**

---

### ÉTAPE 5 : Redémarrer vsftpd et tester

**Redémarrer vsftpd :**

```bash
sudo systemctl restart vsftpd
```

---

**Vérifier que vsftpd démarre correctement :**

```bash
sudo systemctl status vsftpd
```

**Résultat :**

```
[BLACK_CIRCLE] vsftpd.service - vsftpd FTP server
     Active: active (running) since Mon 2024-12-16 12:30:00 UTC; 5s ago
```

**[OK] vsftpd redémarré avec succès !**

---

**Si vsftpd refuse de démarrer, vérifier les logs :**

```bash
sudo journalctl -u vsftpd -n 50
```

**Erreurs possibles :**
- Chemin du certificat incorrect
- Permissions du certificat incorrectes
- Erreur de syntaxe dans vsftpd.conf

---

### ÉTAPE 6 : Tester FTPS avec le client FTP en ligne de commande

**[ATTENTION] Le client `ftp` classique ne supporte PAS SSL !**

**Installer `lftp` (client FTP avancé avec support SSL) :**

```bash
sudo apt install lftp -y
```

---

**Se connecter en FTPS avec lftp :**

```bash
lftp -u client1,ClientPass1! -e "set ftp:ssl-force true; set ssl:verify-certificate no; ls; quit" localhost
```

**Décortiquons cette commande :**

**`lftp`**
- Client FTP en ligne de commande avancé

**`-u client1,ClientPass1!`**
- Username : client1
- Password : ClientPass1!

**`-e "..."`**
- Exécute des commandes lftp

**`set ftp:ssl-force true`**
- Force l'utilisation de SSL/TLS (FTPS)
- Refuse les connexions FTP plain

**`set ssl:verify-certificate no`**
- Ne vérifie PAS le certificat SSL
- Nécessaire car notre certificat est auto-signé
- En production : `yes` avec un vrai certificat (Let's Encrypt)

**`ls`**
- Liste les fichiers

**`quit`**
- Quitte

**`localhost`**
- Serveur cible

---

**Résultat :**

```
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 backups
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:40 www
```

**[OK] Connexion FTPS réussie !**

**Pas de logs d'erreur SSL = FTPS fonctionne !**

---

**Mode interactif avec lftp :**

```bash
lftp
```

**Prompt `lftp :~>`**

**Commandes :**

```
lftp :~> set ftp:ssl-force true
lftp :~> set ssl:verify-certificate no
lftp :~> open -u client1,ClientPass1! localhost
lftp client1@localhost:~> ls
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 backups
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:40 www
lftp client1@localhost:~> cd www
lftp client1@localhost:/www> ls
-rw-r--r--    1 ftp      ftp            25 Dec 16 11:00 index.html
-rw-r--r--    1 ftp      ftp            16 Dec 16 11:40 newfile.txt
lftp client1@localhost:/www> quit
```

**[OK] Navigation et commandes OK !**

---

### ÉTAPE 7 : Tester FTPS avec FileZilla

**Installer FileZilla sur ton PC (pas sur le serveur).**

**Lancer FileZilla.**

**Configuration de connexion :**

```
Hôte : ftps://192.168.1.100
Identifiant : client1
Mot de passe : ClientPass1!
Port : 21
```

**[ATTENTION] Important : Utiliser `ftps://` (pas `ftp://`) !**

**Cliquer sur "Connexion rapide"**

---

**Fenêtre de certificat apparaît :**

```
┌─────────────────────────────────────────────────┐
│ Certificat inconnu                              │
│                                                 │
│ Le serveur a présenté un certificat auto-signé │
│                                                 │
│ Émetteur : CN=ftp.example.com                  │
│ Sujet : CN=ftp.example.com                     │
│ Validité : Dec 16 2024 - Dec 16 2025           │
│                                                 │
│ [ATTENTION] Ce certificat n'est pas approuvé            │
│                                                 │
│ [Annuler] [Toujours faire confiance] [Une fois]│
└─────────────────────────────────────────────────┘
```

**Cliquer sur "Toujours faire confiance"**

**(En production avec Let's Encrypt, cette fenêtre n'apparaît pas)**

---

**Logs FileZilla :**

```
Statut :    Connexion à 192.168.1.100:21...
Statut :    Connexion établie, attente du message de bienvenue...
Réponse :   220 Bienvenue sur le serveur FTP de l'entreprise
Commande :  AUTH TLS
Réponse :   234 Proceed with negotiation.
Statut :    Initialisation de TLS...
Statut :    Vérification du certificat...
Statut :    TLS connection established.
Commande :  USER client1
Réponse :   331 Please specify the password.
Commande :  PASS **********
Réponse :   230 Login successful.
Commande :  SYST
Réponse :   215 UNIX Type: L8
Commande :  PWD
Réponse :   257 "/" is the current directory
Statut :    Connecté
Commande :  TYPE I
Réponse :   200 Switching to Binary mode.
Commande :  PASV
Réponse :   227 Entering Passive Mode (192,168,1,100,195,123).
Commande :  MLSD
Statut :    Initialisation de TLS...
Statut :    TLS connection established.
Réponse :   150 Here comes the directory listing.
Réponse :   226 Directory send OK.
Statut :    Contenu du dossier "/" affiché avec succès
```

**[OK] FTPS Explicite fonctionne !**

**Points importants dans les logs :**

**1. Négociation TLS :**
```
Commande :  AUTH TLS
Réponse :   234 Proceed with negotiation.
```

**Le client demande TLS, le serveur accepte.**

**2. Handshake TLS :**
```
Statut :    Initialisation de TLS...
Statut :    TLS connection established.
```

**Connexion chiffrée établie.**

**3. Authentification chiffrée :**
```
Commande :  USER client1
Commande :  PASS **********
```

**Le mot de passe est chiffré (pas visible en clair) !**

**4. Connexion de données TLS :**
```
Commande :  MLSD
Statut :    Initialisation de TLS...
Statut :    TLS connection established.
```

**Le canal de données est AUSSI chiffré.**

---

**Panneau de droite (Serveur distant) :**

```
backups/
www/
```

**[OK] Fichiers visibles !**

**Tu peux maintenant :**
- Uploader/downloader des fichiers (chiffrés)
- Naviguer dans les dossiers
- Tous les transferts sont sécurisés

---

### ÉTAPE 8 : Vérifier le chiffrement avec tcpdump

**Prouvons que les données sont maintenant chiffrées.**

**Terminal 1 : Capturer le trafic FTPS**

```bash
sudo tcpdump -i any -A 'port 21'
```

---

**Terminal 2 : Se connecter en FTPS**

```bash
lftp -u client1,ClientPass1! -e "set ftp:ssl-force true; set ssl:verify-certificate no; ls; quit" localhost
```

---

**Résultat dans Terminal 1 (tcpdump) :**

```
12:30:00.123456 IP localhost.54321 > localhost.ftp: Flags [P.], length 10
AUTH TLS

12:30:00.234567 IP localhost.ftp > localhost.54321: Flags [P.], length 32
234 Proceed with negotiation.

12:30:00.345678 IP localhost.54321 > localhost.ftp: Flags [P.], length 517
.....V.....h.}...f.......Q....E.u.K...i.
.9....p.F...j.X..A.G....b...V.....D
....(..%.$...#.......=...;...5.../...+...
...'...........g.@...9.8.7.3...-.....,.0..
...........

12:30:00.456789 IP localhost.ftp > localhost.54321: Flags [P.], length 1234
...H...K.....m.n.....z.....x........A.....
.......F....g.h.....y.z.....E.....b.....
```

**[OK] DONNÉES CHIFFRÉES !**

**On ne voit PLUS :**
- [X] Le mot de passe en clair
- [X] Les commandes USER/PASS
- [X] Le contenu des fichiers

**On voit :**
- [OK] `AUTH TLS` (négociation SSL en clair)
- [OK] Données binaires illisibles (chiffrées)

**Comparaison :**

**FTP plain :**
```
USER client1
PASS ClientPass1!   <- [SKULL] Visible !
```

**FTPS :**
```
AUTH TLS
.....V.....h.}...f.......Q....E.u.K...i.   <- [OK] Chiffré !
```

---

### [OK] TESTS DE VALIDATION

**1. Connexion FTPS Explicite**

- [ ] Se connecter avec lftp en FTPS : Succès
- [ ] Se connecter avec FileZilla en FTPS : Succès
- [ ] Logs montrent "AUTH TLS" suivi de "234 Proceed"
- [ ] Certificat SSL accepté (avec avertissement auto-signé)

---

**2. Forcer SSL (interdire FTP plain)**

**Tester une connexion FTP classique (sans SSL) :**

```bash
ftp localhost
```

**Entrer :**
```
Name: client1
Password: ClientPass1!
```

**Résultat attendu :**

```
530 Non-anonymous sessions must use encryption.
Login failed.
```

**[OK] FTP plain est REFUSÉ !**

**Grâce à `force_local_logins_ssl=YES`**

---

**3. Chiffrement du canal de données**

**Avec lftp, uploader un fichier :**

```bash
lftp -u client1,ClientPass1! localhost <<EOF
set ftp:ssl-force true
set ssl:verify-certificate no
cd www
put /etc/hostname
quit
EOF
```

**Pendant le transfert, dans tcpdump :**

```
[Données chiffrées illisibles]
```

**[OK] Upload chiffré !**

---

**4. Protocoles SSL/TLS**

**Vérifier les protocoles acceptés :**

**Tester TLS 1.2 (doit fonctionner) :**

```bash
openssl s_client -connect localhost:21 -starttls ftp -tls1_2
```

**Résultat :**

```
CONNECTED(00000003)
[Certificat SSL affiché]
---
SSL handshake has read 1234 bytes
SSL handshake has written 5678 bytes
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
```

**[OK] TLS 1.2 accepté !**

---

**Tester TLS 1.0 (doit échouer) :**

```bash
openssl s_client -connect localhost:21 -starttls ftp -tls1
```

**Résultat :**

```
CONNECTED(00000003)
[...]
SSL handshake failure
```

**[OK] TLS 1.0 REFUSÉ (comme souhaité) !**

---

**5. Cipher suites sécurisées**

**Vérifier les cipher suites disponibles :**

```bash
nmap --script ssl-enum-ciphers -p 21 localhost
```

**Résultat (exemple) :**

```
PORT   STATE SERVICE
21/tcp open  ftp
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.3: 
|     ciphers: 
|       TLS_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_AES_128_GCM_SHA256 (secp256r1) - A
|     cipher preference: server
|_  least strength: A
```

**[OK] Seulement des cipher suites "A" (excellentes) !**

**Pas de :**
- [X] RC4
- [X] 3DES
- [X] DES
- [X] MD5
- [X] NULL

---

**6. Logs**

```bash
sudo tail -20 /var/log/vsftpd.log
```

**Les logs affichent les transferts normalement (pas les mots de passe) :**

```
Mon Dec 16 12:45:00 2024 1 192.168.1.50 25 /www/index.html b _ o r client1 ftp 0 * c
```

**[OK] Logs fonctionnent avec FTPS !**

---

### [ROUGE] ERREURS COURANTES ET SOLUTIONS

#### Erreur 1 : "TLS connection failed: A TLS fatal alert has been received"

**Symptôme dans FileZilla :**

```
Erreur :    TLS connection failed: A TLS fatal alert has been received
Erreur :    FATAL alert: Handshake failure
```

**Causes possibles :**

**1. Protocoles SSL/TLS incompatibles**

**Le client demande TLS 1.0, mais le serveur n'accepte que TLS 1.2+**

**Solution :**

**Option A : Autoriser TLS 1.0 temporairement (déconseillé)**

Dans `/etc/vsftpd.conf` :

```conf
ssl_tlsv1=YES
```

**Option B : Forcer le client à utiliser TLS 1.2+**

Dans FileZilla : Paramètres -> FTP -> Chiffrement -> Exiger TLS 1.2 minimum

---

**2. Cipher suites incompatibles**

**Le client ne supporte aucune cipher suite proposée par le serveur.**

**Solution :**

Assouplir les cipher suites (temporairement) :

```conf
ssl_ciphers=HIGH
```

Au lieu de :

```conf
ssl_ciphers=HIGH:!aNULL:!MD5:!3DES:!RC4:!DES
```

---

#### Erreur 2 : "530 Non-anonymous sessions must use encryption"

**Symptôme :**

```
530 Non-anonymous sessions must use encryption.
Login failed.
```

**Cause : Le client tente de se connecter en FTP plain (sans SSL)**

**Solutions :**

**1. Utiliser FTPS dans le client**

FileZilla : Utiliser `ftps://192.168.1.100` (pas `ftp://`)

lftp : `set ftp:ssl-force true`

---

**2. Autoriser FTP plain temporairement (développement uniquement)**

```conf
force_local_logins_ssl=NO
force_local_data_ssl=NO
```

**[ATTENTION] DANGEREUX ! Ne jamais faire en production.**

---

#### Erreur 3 : "Certificate verification failed"

**Symptôme dans FileZilla :**

```
Erreur :    Le certificat est auto-signé
```

**Cause : Certificat auto-signé (normal pour cet exercice)**

**Solution :**

**FileZilla :** Cliquer sur "Toujours faire confiance"

**lftp :** `set ssl:verify-certificate no`

**En production :** Utiliser un vrai certificat (Let's Encrypt)

---

#### Erreur 4 : "500 OOPS: SSL: cannot read RSA private key"

**Symptôme dans les logs :**

```
500 OOPS: SSL: cannot read RSA private key
```

**Causes possibles :**

**1. Chemin du certificat incorrect**

Vérifier dans `/etc/vsftpd.conf` :

```conf
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
```

Vérifier que les fichiers existent :

```bash
ls -l /etc/ssl/certs/vsftpd.crt
ls -l /etc/ssl/private/vsftpd.key
```

---

**2. Permissions incorrectes**

```bash
sudo chmod 644 /etc/ssl/certs/vsftpd.crt
sudo chmod 600 /etc/ssl/private/vsftpd.key
sudo chown root:root /etc/ssl/certs/vsftpd.crt
sudo chown root:root /etc/ssl/private/vsftpd.key
```

---

**3. Clé privée protégée par mot de passe**

**Si la clé a été créée AVEC mot de passe, vsftpd ne peut pas démarrer automatiquement.**

**Solution : Recréer la clé SANS mot de passe (-nodes)**

```bash
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt
```

---

#### Erreur 5 : Les données ne sont pas chiffrées (mode passif)

**Symptôme :**

Canal de contrôle chiffré, mais canal de données en clair.

**Cause : `force_local_data_ssl=NO`**

**Solution :**

Dans `/etc/vsftpd.conf` :

```conf
force_local_data_ssl=YES
```

Redémarrer vsftpd.

---

### [IMPORTANT] POINTS CLÉS À RETENIR

**1. FTPS vs SFTP**
- FTPS = FTP + SSL/TLS (port 21)
- SFTP = SSH File Transfer Protocol (port 22)
- Ce sont deux protocoles DIFFÉRENTS !

**2. FTPS Explicite vs Implicite**
- Explicite (port 21) : `AUTH TLS` puis chiffrement (standard moderne)
- Implicite (port 990) : Chiffrement immédiat (obsolète)

**3. SSL/TLS**
- TLS 1.2 et 1.3 = Sécurisés
- SSLv2, SSLv3, TLS 1.0, TLS 1.1 = Obsolètes et dangereux
- Toujours désactiver les anciens protocoles

**4. Certificats**
- Auto-signés : OK pour développement/intranet
- Let's Encrypt : Gratuit pour production
- Clé privée : TOUJOURS protéger (chmod 600)

**5. Forcer le chiffrement**
- `force_local_logins_ssl=YES` : Authentification chiffrée obligatoire
- `force_local_data_ssl=YES` : Transferts chiffrés obligatoires
- Sans ces directives, risque de fallback en FTP plain

**6. Cipher suites**
- Utiliser HIGH (AES-256, ChaCha20)
- Interdire aNULL, MD5, 3DES, RC4, DES
- Vérifier avec `nmap --script ssl-enum-ciphers`

**7. Vérification**
- tcpdump/Wireshark pour voir que les données sont chiffrées
- openssl s_client pour tester les protocoles
- Logs vsftpd continuent de fonctionner normalement

---

### [RAPIDE] POUR ALLER PLUS LOIN

**1. Certificat Let's Encrypt (production)**

**Installer Certbot :**

```bash
sudo apt install certbot -y
```

**Obtenir un certificat (mode standalone) :**

```bash
sudo certbot certonly --standalone -d ftp.example.com
```

**Certificats créés dans :**
```
/etc/letsencrypt/live/ftp.example.com/fullchain.pem
/etc/letsencrypt/live/ftp.example.com/privkey.pem
```

**Configurer vsftpd :**

```conf
rsa_cert_file=/etc/letsencrypt/live/ftp.example.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/ftp.example.com/privkey.pem
```

**Renouvellement automatique :**

```bash
sudo certbot renew --dry-run
```

**Cron pour redémarrer vsftpd après renouvellement :**

```bash
sudo nano /etc/letsencrypt/renewal-hooks/post/vsftpd-reload.sh
```

**Contenu :**

```bash
#!/bin/bash
systemctl reload vsftpd
```

**Rendre exécutable :**

```bash
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/vsftpd-reload.sh
```

---

**2. FTPS Implicite (port 990)**

**Ajouter dans `/etc/vsftpd.conf` :**

```conf
implicit_ssl=YES
listen_port=990
```

**Ouvrir le port dans le firewall :**

```bash
sudo ufw allow 990/tcp
```

**Redémarrer vsftpd.**

**Connexion client :**

FileZilla : `ftps://ftp.example.com:990` avec mode "Exiger FTP implicite sur TLS"

**[ATTENTION] Moins compatible que FTPS Explicite.**

---

**3. Authentification mutuelle (mTLS)**

**Créer un certificat client :**

```bash
# Générer clé privée client
openssl genrsa -out client.key 2048

# Créer CSR client
openssl req -new -key client.key -out client.csr

# Signer avec le certificat serveur (auto-signé)
openssl x509 -req -in client.csr -CA /etc/ssl/certs/vsftpd.crt \
  -CAkey /etc/ssl/private/vsftpd.key -CAcreateserial \
  -out client.crt -days 365
```

**Configurer vsftpd :**

```conf
require_cert=YES
validate_cert=YES
ca_certs_file=/etc/ssl/certs/vsftpd.crt
```

**Le client doit présenter `client.crt` + `client.key`**

**FileZilla :** Paramètres -> FTP -> Certificat client

---

**4. FTPS avec IPv6**

```conf
listen_ipv6=YES
ssl_enable=YES
```

**Connexion :**

```bash
lftp -u client1 [2001:db8::1]
```

---

**5. Monitoring SSL avec Nagios/Zabbix**

**Script pour vérifier l'expiration du certificat :**

```bash
#!/bin/bash
CERT="/etc/ssl/certs/vsftpd.crt"
EXPIRY=$(openssl x509 -enddate -noout -in $CERT | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW) / 86400 ))

if [ $DAYS_LEFT -lt 30 ]; then
    echo "WARNING: Certificat expire dans $DAYS_LEFT jours"
    exit 1
else
    echo "OK: Certificat valide ($DAYS_LEFT jours restants)"
    exit 0
fi
```

**Intégrer dans Nagios/Zabbix/Monit.**

---

## [COURS] CONCLUSION DE L'EXERCICE 3

**[OK] Félicitations ! Tu maîtrises maintenant FTPS et la sécurisation FTP avec SSL/TLS !**

**Ce que tu as appris :**
- Les failles de sécurité de FTP plain (mots de passe en clair)
- Différence entre FTPS et SFTP
- Créer un certificat SSL auto-signé avec OpenSSL
- Configurer vsftpd pour FTPS Explicite (AUTH TLS)
- Forcer le chiffrement pour l'authentification et les données
- Configurer les protocoles SSL/TLS sécurisés (TLS 1.2+)
- Configurer les cipher suites sécurisées
- Tester FTPS avec lftp et FileZilla
- Vérifier le chiffrement avec tcpdump

**Compétences acquises :**
- [OK] FTPS (niveau intermédiaire-avancé)
- [OK] SSL/TLS (configuration serveur)
- [OK] OpenSSL (création certificats)
- [OK] Sécurité FTP (chiffrement, authentification)
- [OK] Diagnostic SSL/TLS

**Temps moyen de réalisation :** 2-3 heures

**Prochaine étape :** Exercice 4 - FTP passif, NAT et automatisation ! [RAPIDE]

---

---

# [ROUGE] EXERCICE 4 : FTP PASSIF, NAT, FIREWALL ET AUTOMATISATION

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système dans une entreprise avec une infrastructure complexe :

**Architecture réseau actuelle :**
```
Internet
   │
   v
[Firewall/NAT] (IP publique : 203.0.113.100)
   │
   v
[Réseau privé 192.168.1.0/24]
   │
   ├─ Serveur FTP (192.168.1.10)
   ├─ Serveur Web (192.168.1.20)
   └─ Serveur DB (192.168.1.30)
```

**Problèmes actuels :**

1. **Clients externes ne peuvent pas se connecter au serveur FTP**
   - Le serveur est derrière un NAT
   - Mode actif FTP ne fonctionne jamais (firewall bloque)
   - Mode passif mal configuré (serveur annonce IP privée)

2. **Gestion manuelle fastidieuse**
   - Création d'utilisateurs virtuels : commandes manuelles à chaque fois
   - Pas de sauvegarde automatique des configs
   - Pas de rotation des logs

3. **Sécurité insuffisante**
   - Pas de fail2ban configuré pour FTP
   - Pas de limitation de connexions par IP
   - Ports FTP passifs non restreints

**Mission :**
- Configurer FTP passif correctement (avec NAT)
- Automatiser la création d'utilisateurs virtuels
- Mettre en place des sauvegardes automatiques
- Sécuriser avec fail2ban et iptables
- Rotation des logs automatique
- Monitoring et alertes

### Objectifs techniques

**FTP Passif avec NAT :**
- Configurer une plage de ports passifs (ex: 40000-50000)
- Annoncer l'IP publique aux clients (masq_address)
- Configurer le firewall/NAT pour rediriger les ports

**Automatisation :**
- Script de création d'utilisateurs virtuels
- Script de sauvegarde (configs + base de données)
- Cron jobs pour automatisation
- Script de nettoyage (vieux fichiers, logs)

**Sécurité :**
- Fail2ban pour bloquer les attaques par force brute
- iptables/ufw pour limiter les connexions
- Rate limiting (connexions par IP, bande passante)
- Alertes par email

**Monitoring :**
- Script de monitoring (espace disque, connexions)
- Logs détaillés
- Rotation automatique des logs
- Dashboard simple (optionnel)

### Contraintes

- Serveur derrière NAT (IP privée)
- vsftpd + FTPS (Exercices 2 et 3)
- Bash scripting pour l'automatisation
- Fail2ban + iptables/ufw
- Logrotate pour les logs
- Temps estimé : 3-4 heures

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Comprendre le mode passif FTP en profondeur
- [OK] Configurer FTP passif avec NAT/firewall
- [OK] Utiliser `masq_address` pour annoncer l'IP publique
- [OK] Automatiser la gestion d'utilisateurs virtuels
- [OK] Créer des scripts Bash pour l'administration FTP
- [OK] Configurer fail2ban pour FTP/FTPS
- [OK] Utiliser iptables/ufw pour sécuriser FTP
- [OK] Mettre en place la rotation de logs
- [OK] Créer un système de monitoring FTP
- [OK] Automatiser les sauvegardes

---

## [DOCS] PRÉREQUIS

- Exercices 1, 2 et 3 terminés
- Compréhension du NAT et des firewalls
- Notions de scripting Bash
- Connaissances réseau (ports, IP publique/privée)

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Comprendre le mode passif FTP

#### Rappel : Mode actif vs Passif

**MODE ACTIF (ne fonctionne presque jamais) :**

```
1. Client -> Serveur (port 21)
   "Bonjour, je suis 192.168.1.50:54321"

2. Client <- Serveur
   "OK, je vais me connecter à toi"

3. Client <- Serveur (port 20 -> client:54321)
   [BLOQUÉ PAR LE FIREWALL DU CLIENT]

Problème : Le serveur doit SE CONNECTER au client
-> Impossible si le client est derrière NAT/firewall
```

---

**MODE PASSIF (standard aujourd'hui) :**

```
1. Client -> Serveur (port 21)
   "Bonjour, je veux le mode passif"

2. Client <- Serveur
   "OK, connecte-toi sur mon port 42345"

3. Client -> Serveur (port 42345)
   [Le CLIENT initie = OK]

Avantage : C'est le CLIENT qui initie les deux connexions
-> Fonctionne même si le client est derrière NAT
```

---

#### Problème avec le mode passif et le NAT

**Scénario problématique :**

```
Client externe (IP publique : 203.0.113.200)
   │
   v Internet
   │
[Firewall/NAT] (IP publique : 203.0.113.100)
   │
   v Réseau privé
   │
Serveur FTP (IP privée : 192.168.1.10)
```

**Ce qui se passe SANS configuration correcte :**

```
1. Client -> Serveur (via NAT)
   Commande : PASV

2. Serveur -> Client
   Réponse : 227 Entering Passive Mode (192,168,1,10,165,123)
                                         └───────┬──────┘
                                           IP PRIVÉE !

3. Client tente de se connecter à 192.168.1.10:42363
   [X] ÉCHEC : IP privée non routable sur Internet !
```

**Le serveur annonce son IP PRIVÉE (192.168.1.10)**

**Le client externe ne peut pas se connecter à une IP privée !**

---

**Solution : `masq_address` (masquerade address)**

```
vsftpd.conf :
pasv_address=203.0.113.100  <- IP PUBLIQUE
```

**Maintenant :**

```
1. Client -> Serveur
   Commande : PASV

2. Serveur -> Client
   Réponse : 227 Entering Passive Mode (203,0,113,100,165,123)
                                         └─────┬────┘
                                          IP PUBLIQUE !

3. Client se connecte à 203.0.113.100:42363
   v
   [Firewall/NAT redirige vers 192.168.1.10:42363]
   v
   [OK] Connexion réussie !
```

---

#### Plage de ports passifs

**Par défaut, vsftpd utilise des ports aléatoires (1024-65535)**

**Problème :** Il faudrait ouvrir 64 000+ ports dans le firewall !

**Solution :** Définir une plage restreinte (ex: 40000-50000)

```
vsftpd.conf :
pasv_min_port=40000
pasv_max_port=50000
```

**Avantage :** Seulement 10 000 ports à ouvrir (plus gérable)

**Firewall :**
```bash
sudo ufw allow 40000:50000/tcp
```

---

### ÉTAPE 2 : Configurer le mode passif dans vsftpd

**Éditer la configuration :**

```bash
sudo nano /etc/vsftpd.conf
```

**Ajouter ces lignes :**

```conf
# ═══════════════════════════════════════════════════════════════
# CONFIGURATION MODE PASSIF (PASV)
# ═══════════════════════════════════════════════════════════════

# Activer le mode passif (déjà activé par défaut)
pasv_enable=YES

# Explication :
# pasv_enable=YES permet aux clients de demander PASV
# Par défaut : YES
# 
# pasv_enable=NO forcerait le mode actif uniquement (rare)

# ───────────────────────────────────────────────────────────────
# PLAGE DE PORTS PASSIFS
# ───────────────────────────────────────────────────────────────

# Port minimum pour le mode passif
pasv_min_port=40000

# Port maximum pour le mode passif
pasv_max_port=50000

# Explication :
# vsftpd choisira un port ALÉATOIRE dans cette plage
# pour chaque connexion de données passive
# 
# Plage : 40000-50000 = 10 001 ports disponibles
# 
# Calcul du nombre de connexions simultanées :
# - Chaque connexion passive = 1 port
# - Avec 10 001 ports, on peut avoir 10 001 connexions de données
#   en simultané
# 
# Recommandations :
# - Petit serveur (10-50 users) : 40000-40100 (101 ports)
# - Serveur moyen (50-200 users) : 40000-41000 (1001 ports)
# - Gros serveur (200+ users) : 40000-50000 (10001 ports)
# 
# [ATTENTION] Plus la plage est grande, plus il faut ouvrir de ports
# dans le firewall !

# ───────────────────────────────────────────────────────────────
# ANNONCER L'IP PUBLIQUE (POUR NAT)
# ───────────────────────────────────────────────────────────────

# IP publique à annoncer dans la réponse PASV
pasv_address=203.0.113.100

# Explication DÉTAILLÉE :
# 
# pasv_address = L'IP que le serveur annonce aux clients
# dans la réponse "227 Entering Passive Mode (...)"
# 
# [ATTENTION] À ADAPTER selon ta situation :
# 
# CAS 1 : Serveur avec IP publique directe (pas de NAT)
# pasv_address=[ton IP publique]
# Exemple : pasv_address=203.0.113.100
# 
# CAS 2 : Serveur derrière NAT avec IP publique fixe
# pasv_address=[IP publique du firewall/routeur]
# Exemple : pasv_address=203.0.113.100
# 
# CAS 3 : Serveur derrière NAT avec IP publique dynamique
# Utiliser pasv_addr_resolve=YES au lieu de pasv_address
# (voir plus bas)
# 
# CAS 4 : Serveur accessible seulement en local (intranet)
# NE PAS mettre pasv_address
# vsftpd annoncera automatiquement l'IP locale
# 
# Pour trouver ton IP publique :
# curl ifconfig.me
# ou
# curl api.ipify.org

# Alternative pour IP publique dynamique (DNS dynamique)
# pasv_addr_resolve=YES
# pasv_address=monserveur.dyndns.org

# Explication de pasv_addr_resolve :
# 
# pasv_addr_resolve=YES :
# vsftpd résout le nom de domaine (DNS) à chaque connexion PASV
# 
# Utile si :
# - Tu as une IP publique qui change (ADSL résidentiel)
# - Tu utilises un service DNS dynamique (DynDNS, No-IP, etc.)
# 
# Exemple :
# 1. Ton IP publique change de 203.0.113.100 à 203.0.113.200
# 2. Le service DNS dynamique met à jour : monserveur.dyndns.org -> 203.0.113.200
# 3. vsftpd résout monserveur.dyndns.org -> 203.0.113.200
# 4. vsftpd annonce 203.0.113.200 dans PASV
# 
# [ATTENTION] Sans pasv_addr_resolve, vsftpd résout seulement au DÉMARRAGE
# Si l'IP change après, vsftpd annoncera l'ancienne IP !

# ───────────────────────────────────────────────────────────────
# DÉSACTIVER LE MODE ACTIF (OPTIONNEL)
# ───────────────────────────────────────────────────────────────

# Désactiver complètement le mode actif
port_enable=NO

# Explication :
# port_enable=NO désactive le mode actif (PORT)
# 
# Avantages :
# [OK] Force les clients à utiliser le mode passif
# [OK] Simplifie la configuration firewall
# [OK] Plus sécurisé (pas de connexions sortantes du serveur)
# 
# Inconvénients :
# [X] Les TRÈS vieux clients FTP (années 90) pourraient ne pas fonctionner
# 
# Recommandation en 2024 : port_enable=NO (mode passif uniquement)

# Désactiver les connexions de données depuis le port 20 (mode actif)
connect_from_port_20=NO

# Explication :
# connect_from_port_20=YES (par défaut) :
# Les connexions de données en mode actif proviennent du port 20
# 
# connect_from_port_20=NO :
# Les connexions de données proviennent d'un port aléatoire > 1024
# 
# Avec port_enable=NO, cette directive n'a pas d'effet

# ═══════════════════════════════════════════════════════════════
```

**[ATTENTION] IMPORTANT : Remplace `203.0.113.100` par TON IP publique !**

**Pour trouver ton IP publique :**

```bash
curl ifconfig.me
```

**Ou :**

```bash
curl api.ipify.org
```

**Exemple :** Si le résultat est `45.67.89.123`, utilise :

```conf
pasv_address=45.67.89.123
```

**Sauvegarde.**

---

**Redémarrer vsftpd :**

```bash
sudo systemctl restart vsftpd
```

---

### ÉTAPE 3 : Configurer le firewall (ufw)

**Installer ufw (si pas déjà fait) :**

```bash
sudo apt install ufw -y
```

---

**Autoriser SSH (IMPORTANT pour ne pas se bloquer !) :**

```bash
sudo ufw allow 22/tcp
```

---

**Autoriser FTP (port de contrôle) :**

```bash
sudo ufw allow 21/tcp
```

---

**Autoriser la plage de ports passifs :**

```bash
sudo ufw allow 40000:50000/tcp
```

**Explication :**
- `40000:50000` = Plage de ports (du port 40000 au port 50000 inclus)
- `/tcp` = Protocole TCP
- Ouvre 10 001 ports en une seule commande

---

**Activer le firewall :**

```bash
sudo ufw enable
```

**Confirmation :**

```
Command may disrupt existing ssh connections. Proceed with operation (y|n)?
```

**Taper `y` et Entrée.**

---

**Vérifier les règles :**

```bash
sudo ufw status verbose
```

**Résultat :**

```
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
21/tcp                     ALLOW IN    Anywhere
40000:50000/tcp            ALLOW IN    Anywhere
```

**[OK] Firewall configuré !**

---

**Alternative avec iptables (si tu préfères) :**

```bash
# Autoriser FTP
sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT

# Autoriser plage passive
sudo iptables -A INPUT -p tcp --dport 40000:50000 -j ACCEPT

# Sauvegarder (Ubuntu/Debian)
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
```

---

### ÉTAPE 4 : Configurer le NAT sur le routeur/firewall

**[ATTENTION] Cette étape dépend de TON routeur/firewall.**

**Principe : Redirection de ports (Port Forwarding)**

**Exemple avec un routeur domestique :**

```
Configuration -> NAT / Port Forwarding

Règle 1 :
  Port externe : 21
  IP interne : 192.168.1.10
  Port interne : 21
  Protocole : TCP

Règle 2 :
  Ports externes : 40000-50000
  IP interne : 192.168.1.10
  Ports internes : 40000-50000
  Protocole : TCP
```

**Exemple avec iptables (sur le routeur/firewall Linux) :**

```bash
# Sur la machine routeur/firewall (PAS le serveur FTP)

# Redirection port 21
sudo iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.10:21

# Redirection plage passive
sudo iptables -t nat -A PREROUTING -p tcp --dport 40000:50000 -j DNAT --to-destination 192.168.1.10:40000-50000

# Autoriser le forwarding
sudo iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 21 -j ACCEPT
sudo iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 40000:50000 -j ACCEPT

# Sauvegarder
sudo netfilter-persistent save
```

**Remplace `192.168.1.10` par l'IP de TON serveur FTP.**

---

**Si tu utilises AWS/GCP/Azure :**

**AWS Security Groups :**
```
Inbound Rules :
- Type: Custom TCP, Port: 21, Source: 0.0.0.0/0
- Type: Custom TCP, Port Range: 40000-50000, Source: 0.0.0.0/0
```

**GCP Firewall Rules :**
```
gcloud compute firewall-rules create allow-ftp \
  --allow tcp:21,tcp:40000-50000 \
  --source-ranges 0.0.0.0/0
```

---

### ÉTAPE 5 : Tester le mode passif

**Depuis un client externe (ou en local pour tester) :**

```bash
lftp -u client1,ClientPass1! -d localhost <<EOF
set ftp:ssl-force true
set ssl:verify-certificate no
set ftp:passive-mode true
ls
quit
EOF
```

**Explication :**
- `-d` = Mode debug (affiche toutes les commandes)
- `set ftp:passive-mode true` = Force le mode passif

---

**Résultat (debug) :**

```
<--- 227 Entering Passive Mode (203,0,113,100,156,64).
---> MLSD
<--- 150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:00 backups
drwxr-xr-x    2 ftp      ftp          4096 Dec 16 11:40 www
<--- 226 Directory send OK.
```

**Points importants :**

**`227 Entering Passive Mode (203,0,113,100,156,64)`**

**Décryptage de l'IP et du port :**

```
(203,0,113,100,156,64)
 └─┬─┘ └─┬─┘ └┬┘ └┬┘
  IP1  IP2  P1  P2

IP = IP1.IP2.IP3.IP4 = 203.0.113.100 [OK] (IP publique)
Port = (P1 × 256) + P2 = (156 × 256) + 64 = 39936 + 64 = 40000 [OK]
```

**Le serveur annonce bien :**
- [OK] L'IP publique (203.0.113.100) grâce à `pasv_address`
- [OK] Un port dans la plage 40000-50000

---

**Avec FileZilla (mode debug) :**

FileZilla -> Paramètres -> FTP -> Mode de transfert passif -> Utiliser le mode passif

**Logs :**

```
Commande :  PASV
Réponse :   227 Entering Passive Mode (203,0,113,100,156,64).
Statut :    Connexion de données établie
```

**[OK] Mode passif fonctionne !**

---

### ÉTAPE 6 : Créer un script d'ajout d'utilisateurs virtuels

**Automatisons la création d'utilisateurs virtuels.**

```bash
sudo nano /usr/local/bin/add-ftp-user.sh
```

**Contenu :**

```bash
#!/bin/bash
# ═══════════════════════════════════════════════════════════════
# SCRIPT D'AJOUT D'UTILISATEUR VIRTUEL FTP
# ═══════════════════════════════════════════════════════════════
# 
# Usage : add-ftp-user.sh <username> <password>
# Exemple : add-ftp-user.sh client4 SecurePass123!
# 
# ═══════════════════════════════════════════════════════════════

# Couleurs pour l'affichage
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Fonction d'affichage avec couleurs
echo_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

echo_error() {
    echo -e "${RED}[ERREUR]${NC} $1"
}

echo_warn() {
    echo -e "${YELLOW}[ATTENTION]${NC} $1"
}

# ───────────────────────────────────────────────────────────────
# VÉRIFICATIONS PRÉLIMINAIRES
# ───────────────────────────────────────────────────────────────

# Vérifier qu'on est root
if [ "$EUID" -ne 0 ]; then 
    echo_error "Ce script doit être exécuté en tant que root (sudo)"
    exit 1
fi

# Vérifier le nombre d'arguments
if [ "$#" -ne 2 ]; then
    echo_error "Usage : $0 <username> <password>"
    echo_error "Exemple : $0 client4 SecurePass123!"
    exit 1
fi

# Récupérer les arguments
USERNAME=$1
PASSWORD=$2

# Vérifier que le username contient seulement des caractères valides
if ! [[ "$USERNAME" =~ ^[a-zA-Z0-9_-]+$ ]]; then
    echo_error "Le nom d'utilisateur doit contenir uniquement : a-z, A-Z, 0-9, _ ou -"
    exit 1
fi

# Vérifier la longueur du username
if [ ${#USERNAME} -lt 3 ] || [ ${#USERNAME} -gt 20 ]; then
    echo_error "Le nom d'utilisateur doit faire entre 3 et 20 caractères"
    exit 1
fi

# Vérifier la force du mot de passe (minimum 8 caractères)
if [ ${#PASSWORD} -lt 8 ]; then
    echo_error "Le mot de passe doit contenir au moins 8 caractères"
    exit 1
fi

# ───────────────────────────────────────────────────────────────
# CONFIGURATION
# ───────────────────────────────────────────────────────────────

FTP_ROOT="/srv/ftp"
DB_FILE="/etc/vsftpd/virtual_users.db"
TEMP_DB_FILE="/tmp/virtual_users.txt"
USER_CONF_DIR="/etc/vsftpd/user_conf"
FTP_USER="ftpvirtual"
FTP_GROUP="ftpvirtual"

# ───────────────────────────────────────────────────────────────
# VÉRIFIER SI L'UTILISATEUR EXISTE DÉJÀ
# ───────────────────────────────────────────────────────────────

if [ -f "$USER_CONF_DIR/$USERNAME" ]; then
    echo_error "L'utilisateur '$USERNAME' existe déjà !"
    echo_info "Pour le supprimer : remove-ftp-user.sh $USERNAME"
    exit 1
fi

# ───────────────────────────────────────────────────────────────
# CRÉER LA STRUCTURE DE DOSSIERS
# ───────────────────────────────────────────────────────────────

echo_info "Création de la structure de dossiers pour '$USERNAME'..."

# Créer le répertoire utilisateur
mkdir -p "$FTP_ROOT/$USERNAME"/{www,backups}

# Permissions :
# - Racine (555) : lecture + exécution (pas d'écriture)
# - Sous-dossiers (755) : lecture + écriture + exécution
chmod 555 "$FTP_ROOT/$USERNAME"
chmod 755 "$FTP_ROOT/$USERNAME/www"
chmod 755 "$FTP_ROOT/$USERNAME/backups"

# Propriétaire : ftpvirtual
chown -R $FTP_USER:$FTP_GROUP "$FTP_ROOT/$USERNAME"

echo_info "Structure créée : $FTP_ROOT/$USERNAME/"

# ───────────────────────────────────────────────────────────────
# AJOUTER À LA BASE DE DONNÉES BERKELEY DB
# ───────────────────────────────────────────────────────────────

echo_info "Ajout de '$USERNAME' à la base de données..."

# Exporter la base existante en texte (si elle existe)
if [ -f "$DB_FILE" ]; then
    db_dump "$DB_FILE" > "$TEMP_DB_FILE.old"
    # Extraire seulement les données (sans les headers)
    sed -n '/^DATA=END$/q;p' "$TEMP_DB_FILE.old" | grep -v '^VERSION\|^format\|^type\|^h\|^ ' > "$TEMP_DB_FILE"
fi

# Ajouter le nouvel utilisateur
echo " $USERNAME" >> "$TEMP_DB_FILE"
echo " $PASSWORD" >> "$TEMP_DB_FILE"

# Recréer la base de données
db_load -T -t hash -f "$TEMP_DB_FILE" "$DB_FILE"

# Sécuriser la base
chmod 600 "$DB_FILE"
chown root:root "$DB_FILE"

# Nettoyer les fichiers temporaires
rm -f "$TEMP_DB_FILE" "$TEMP_DB_FILE.old"

echo_info "Utilisateur ajouté à la base de données"

# ───────────────────────────────────────────────────────────────
# CRÉER LA CONFIGURATION SPÉCIFIQUE
# ───────────────────────────────────────────────────────────────

echo_info "Création de la configuration spécifique..."

cat > "$USER_CONF_DIR/$USERNAME" <<EOF
# Configuration pour $USERNAME
# Créé le : $(date +"%Y-%m-%d %H:%M:%S")

# Répertoire racine (chroot)
local_root=$FTP_ROOT/$USERNAME

# Limites de bande passante (optionnel, en bytes/sec)
# local_max_rate=1048576     # 1 MB/s upload
# anon_max_rate=2097152      # 2 MB/s download

# Nombre max de connexions simultanées (optionnel)
# max_per_ip=3
EOF

echo_info "Configuration créée : $USER_CONF_DIR/$USERNAME"

# ───────────────────────────────────────────────────────────────
# CRÉER UN FICHIER README DANS LE RÉPERTOIRE
# ───────────────────────────────────────────────────────────────

cat > "$FTP_ROOT/$USERNAME/README.txt" <<EOF
Bienvenue $USERNAME !

Ce répertoire FTP vous est dédié.

Structure :
/www/      - Déposez ici les fichiers de votre site web
/backups/  - Stockez vos sauvegardes ici

Informations de connexion :
Serveur : $(hostname)
Protocole : FTPS (FTP over SSL/TLS)
Port : 21
Utilisateur : $USERNAME

Support : admin@example.com

Créé le : $(date +"%Y-%m-%d %H:%M:%S")
EOF

chown $FTP_USER:$FTP_GROUP "$FTP_ROOT/$USERNAME/README.txt"
chmod 644 "$FTP_ROOT/$USERNAME/README.txt"

# ───────────────────────────────────────────────────────────────
# RÉSUMÉ
# ───────────────────────────────────────────────────────────────

echo ""
echo_info "═══════════════════════════════════════════════════════"
echo_info "  Utilisateur FTP créé avec succès !"
echo_info "═══════════════════════════════════════════════════════"
echo ""
echo_info "Utilisateur : $USERNAME"
echo_info "Mot de passe : [masqué]"
echo_info "Répertoire : $FTP_ROOT/$USERNAME/"
echo ""
echo_info "Informations de connexion :"
echo_info "  Serveur : ftps://$(curl -s ifconfig.me 2>/dev/null || echo 'VOTRE_IP'):21"
echo_info "  Utilisateur : $USERNAME"
echo_info "  Protocole : FTPS (SSL/TLS obligatoire)"
echo ""
echo_info "Test de connexion :"
echo_info "  lftp -u $USERNAME,'***' -e 'set ftp:ssl-force true; set ssl:verify-certificate no; ls; quit' localhost"
echo ""
echo_info "═══════════════════════════════════════════════════════"

exit 0
```

**Sauvegarde.**

---

**Rendre exécutable :**

```bash
sudo chmod +x /usr/local/bin/add-ftp-user.sh
```

---

**Tester le script :**

```bash
sudo add-ftp-user.sh client4 SuperSecure2024!
```

**Résultat :**

```
[INFO] Création de la structure de dossiers pour 'client4'...
[INFO] Structure créée : /srv/ftp/client4/
[INFO] Ajout de 'client4' à la base de données...
[INFO] Utilisateur ajouté à la base de données
[INFO] Création de la configuration spécifique...
[INFO] Configuration créée : /etc/vsftpd/user_conf/client4

[INFO] ═══════════════════════════════════════════════════════
[INFO]   Utilisateur FTP créé avec succès !
[INFO] ═══════════════════════════════════════════════════════

[INFO] Utilisateur : client4
[INFO] Mot de passe : [masqué]
[INFO] Répertoire : /srv/ftp/client4/

[INFO] Informations de connexion :
[INFO]   Serveur : ftps://45.67.89.123:21
[INFO]   Utilisateur : client4
[INFO]   Protocole : FTPS (SSL/TLS obligatoire)

[INFO] Test de connexion :
[INFO]   lftp -u client4,'***' -e 'set ftp:ssl-force true; set ssl:verify-certificate no; ls; quit' localhost

[INFO] ═══════════════════════════════════════════════════════
```

**[OK] Utilisateur créé automatiquement !**

---

**Vérifier :**

```bash
# Structure créée
ls -lR /srv/ftp/client4/

# Config créée
cat /etc/vsftpd/user_conf/client4

# Base de données mise à jour
sudo db_dump /etc/vsftpd/virtual_users.db | grep client4
```

---

**Tester la connexion :**

```bash
lftp -u client4,SuperSecure2024! -e "set ftp:ssl-force true; set ssl:verify-certificate no; ls; quit" localhost
```

**[OK] Connexion OK !**

---

### ÉTAPE 7 : Script de suppression d'utilisateurs

```bash
sudo nano /usr/local/bin/remove-ftp-user.sh
```

**Contenu :**

```bash
#!/bin/bash
# Script de suppression d'utilisateur virtuel FTP

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
echo_error() { echo -e "${RED}[ERREUR]${NC} $1"; }
echo_warn() { echo -e "${YELLOW}[ATTENTION]${NC} $1"; }

if [ "$EUID" -ne 0 ]; then 
    echo_error "Ce script doit être exécuté en tant que root"
    exit 1
fi

if [ "$#" -ne 1 ]; then
    echo_error "Usage : $0 <username>"
    exit 1
fi

USERNAME=$1
FTP_ROOT="/srv/ftp"
DB_FILE="/etc/vsftpd/virtual_users.db"
USER_CONF_DIR="/etc/vsftpd/user_conf"

# Vérifier que l'utilisateur existe
if [ ! -f "$USER_CONF_DIR/$USERNAME" ]; then
    echo_error "L'utilisateur '$USERNAME' n'existe pas"
    exit 1
fi

# Demander confirmation
echo_warn "Vous allez supprimer l'utilisateur '$USERNAME'"
echo_warn "TOUS les fichiers dans $FTP_ROOT/$USERNAME/ seront supprimés !"
read -p "Êtes-vous sûr ? (oui/non) : " CONFIRM

if [ "$CONFIRM" != "oui" ]; then
    echo_info "Suppression annulée"
    exit 0
fi

# Supprimer les fichiers
echo_info "Suppression des fichiers..."
rm -rf "$FTP_ROOT/$USERNAME"

# Supprimer la config
echo_info "Suppression de la configuration..."
rm -f "$USER_CONF_DIR/$USERNAME"

# Mettre à jour la base de données
echo_info "Mise à jour de la base de données..."
TEMP_FILE="/tmp/virtual_users_temp.txt"

# Exporter la base et filtrer l'utilisateur
db_dump "$DB_FILE" | grep -v "^ $USERNAME\$" | grep -v "^DATA=END\$" > "$TEMP_FILE"

# Recréer la base
db_load -T -t hash -f "$TEMP_FILE" "$DB_FILE"
chmod 600 "$DB_FILE"
rm -f "$TEMP_FILE"

echo_info "Utilisateur '$USERNAME' supprimé avec succès"
```

**Rendre exécutable :**

```bash
sudo chmod +x /usr/local/bin/remove-ftp-user.sh
```

---

### ÉTAPE 8 : Configurer Fail2Ban pour FTP

**Installer Fail2Ban :**

```bash
sudo apt install fail2ban -y
```

---

**Créer la jail FTP :**

```bash
sudo nano /etc/fail2ban/jail.d/vsftpd.conf
```

**Contenu :**

```ini
[vsftpd]
enabled = true
port = ftp,ftps
logpath = /var/log/vsftpd.log
maxretry = 3
bantime = 3600
findtime = 600
```

**Explication :**
- **maxretry = 3** : 3 échecs d'authentification
- **bantime = 3600** : Bannir 1 heure (3600 secondes)
- **findtime = 600** : Dans une fenêtre de 10 minutes

---

**Redémarrer Fail2Ban :**

```bash
sudo systemctl restart fail2ban
```

---

**Vérifier :**

```bash
sudo fail2ban-client status vsftpd
```

**[OK] Fail2Ban surveille vsftpd !**

---

### ÉTAPE 9 : Script de sauvegarde automatique

```bash
sudo nano /usr/local/bin/backup-ftp.sh
```

**Contenu :**

```bash
#!/bin/bash
# Sauvegarde automatique FTP

BACKUP_DIR="/var/backups/ftp"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/ftp_backup_$DATE.tar.gz"

mkdir -p "$BACKUP_DIR"

# Sauvegarder
tar -czf "$BACKUP_FILE" \
  /etc/vsftpd/ \
  /srv/ftp/ \
  --exclude='/srv/ftp/*/www/*' \
  --exclude='/srv/ftp/*/backups/*'

# Nettoyer les vieilles sauvegardes (> 30 jours)
find "$BACKUP_DIR" -name "ftp_backup_*.tar.gz" -mtime +30 -delete

echo "Sauvegarde créée : $BACKUP_FILE"
```

**Rendre exécutable et planifier :**

```bash
sudo chmod +x /usr/local/bin/backup-ftp.sh
sudo crontab -e
```

**Ajouter :**

```
# Sauvegarde FTP tous les jours à 3h
0 3 * * * /usr/local/bin/backup-ftp.sh
```

---

## [COURS] CONCLUSION DES EXERCICES 3, 4

**Félicitations ! Tu maîtrises maintenant FTP/FTPS de A à Z !**

**L'Exercice 5 (Sécurisation complète et audit) sera fourni dans un message séparé pour respecter les limites de longueur.**

**Veux-tu que je continue avec l'Exercice 5 maintenant ?**


# [ROUGE] EXERCICE 5 : SÉCURISATION COMPLÈTE, AUDIT ET PRODUCTION

## [LISTE] ÉNONCÉ

### Contexte professionnel

Tu es administrateur système senior dans une entreprise qui traite des données hautement sensibles (données bancaires, informations médicales, propriété intellectuelle). L'entreprise doit **impérativement** :

1. **Passer un audit de sécurité** (PCI-DSS, ISO 27001)
2. **Garantir une disponibilité 99.9%** (SLA clients)
3. **Tracer toutes les activités** (conformité légale)
4. **Détecter et bloquer les attaques** en temps réel
5. **Optimiser les performances** (1000+ utilisateurs simultanés)

**Le serveur FTP actuel (Exercices 1-4) fonctionne, mais :**

[X] Pas d'analyse de logs en temps réel  
[X] Pas de détection d'anomalies  
[X] Pas de limitation de bande passante par utilisateur  
[X] Pas de monitoring avancé (CPU, RAM, connexions)  
[X] Pas de tests de charge effectués  
[X] Pas de plan de disaster recovery  
[X] Pas d'audit de sécurité réalisé  
[X] Pas de conformité démontrée  

**Mission finale :**

Transformer le serveur FTP en **infrastructure de production enterprise-grade** avec :
- Sécurité maximale (hardening complet)
- Monitoring en temps réel
- Alertes automatiques
- Audit de sécurité complet
- Documentation pour certification
- Tests de charge et optimisation
- Plan de disaster recovery

---

### Objectifs techniques

**Sécurisation avancée :**
- Fail2ban avec règles personnalisées
- Rate limiting intelligent
- IP whitelisting/blacklisting
- Protection DDoS
- Chiffrement renforcé (cipher suites modernes)
- Rotation automatique des certificats SSL

**Monitoring et alertes :**
- Monitoring temps réel (connexions, transferts, erreurs)
- Alertes par email/SMS/Slack
- Dashboards de visualisation
- Analyse des logs avec outils
- Détection d'anomalies

**Audit et conformité :**
- Scan de vulnérabilités (nmap, nikto, lynis)
- Rapport d'audit complet
- Checklist PCI-DSS/OWASP
- Documentation de conformité

**Performance :**
- Tests de charge (1000+ utilisateurs)
- Optimisation vsftpd
- Tuning système (kernel, TCP)
- Limitation de bande passante intelligente

**Disaster Recovery :**
- Sauvegarde complète automatisée
- Procédure de restauration testée
- Haute disponibilité (optionnel)
- Documentation complète

---

## [OBJECTIF] OBJECTIFS PÉDAGOGIQUES

À la fin de cet exercice, tu sauras :

- [OK] Effectuer un hardening complet de vsftpd
- [OK] Configurer fail2ban avec règles avancées
- [OK] Créer un système de monitoring complet
- [OK] Analyser les logs FTP avec des outils
- [OK] Effectuer un audit de sécurité professionnel
- [OK] Optimiser les performances pour production
- [OK] Créer un plan de disaster recovery
- [OK] Documenter pour conformité réglementaire
- [OK] Tester la charge et la résilience
- [OK] Détecter et bloquer les attaques en temps réel

---

## [DOCS] PRÉREQUIS

- Exercices 1, 2, 3 et 4 terminés
- Compréhensions avancées Linux
- Notions de sécurité (PCI-DSS, OWASP)
- Scripting Bash avancé
- Bases monitoring (optionnel)

---

## [OK] SOLUTION COMPLÈTE

### ÉTAPE 1 : Hardening vsftpd (sécurisation maximale)

**Éditer la configuration pour durcir la sécurité :**

```bash
sudo nano /etc/vsftpd.conf
```

**Ajouter/modifier ces directives :**

```conf
# ═══════════════════════════════════════════════════════════════
# HARDENING VSFTPD - SÉCURITÉ MAXIMALE
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# LIMITATIONS DE CONNEXIONS
# ───────────────────────────────────────────────────────────────

# Nombre maximum de clients simultanés (tous utilisateurs confondus)
max_clients=200

# Explication :
# max_clients limite le nombre TOTAL de connexions simultanées
# 
# Calcul recommandé :
# - Petit serveur (1-2 CPU, 2 GB RAM) : 50-100
# - Serveur moyen (4 CPU, 8 GB RAM) : 200-500
# - Gros serveur (8+ CPU, 16+ GB RAM) : 500-1000+
# 
# Impact :
# - Trop bas : Les utilisateurs légitimes sont refusés
# - Trop haut : Risque de saturation CPU/RAM
# 
# Protection contre :
# [OK] Attaques DoS (saturation de connexions)
# [OK] Épuisement des ressources
# 
# Formule empirique :
# max_clients = (RAM_GB * 100) - 100
# Exemple : 8 GB RAM -> max_clients = 700

# Nombre maximum de connexions par IP source
max_per_ip=3

# Explication :
# max_per_ip limite le nombre de connexions SIMULTANÉES
# depuis une MÊME IP
# 
# Valeurs recommandées :
# - Utilisateurs individuels : 2-3
# - Entreprises (NAT) : 10-20
# - Services automatisés : 5-10
# 
# Protection contre :
# [OK] Attaques par force brute (connexions multiples)
# [OK] Abus de ressources par un seul client
# [OK] Scans de ports automatisés
# 
# Exemple de blocage :
# IP 192.168.1.50 :
# - Connexion 1 : OK
# - Connexion 2 : OK
# - Connexion 3 : OK
# - Connexion 4 : REFUSÉE (421 Too many connections)

# Nombre maximum de tentatives de login échouées
max_login_fails=3

# Explication :
# Après 3 échecs d'authentification, la connexion est fermée
# 
# Le client doit SE RECONNECTER pour réessayer
# 
# Protection contre :
# [OK] Attaques par force brute
# [OK] Devine-mots de passe automatisés
# 
# Workflow :
# 1. Client : USER baduser -> 530 Login incorrect
# 2. Client : USER baduser2 -> 530 Login incorrect
# 3. Client : USER baduser3 -> 530 Login incorrect
# 4. Serveur : 421 Login incorrect, closing connection
# 
# Combiné avec fail2ban :
# fail2ban bannit l'IP après 3 CONNEXIONS échouées

# ───────────────────────────────────────────────────────────────
# TIMEOUTS (DÉLAIS D'EXPIRATION)
# ───────────────────────────────────────────────────────────────

# Timeout de session inactive (en secondes)
idle_session_timeout=600

# Explication :
# Si aucune commande pendant 600 secondes (10 minutes),
# la connexion est fermée automatiquement
# 
# Protection contre :
# [OK] Connexions zombies (consommation ressources)
# [OK] Sessions oubliées par les clients
# [OK] Saturation de connexions
# 
# Valeurs recommandées :
# - Serveur public : 300-600 (5-10 minutes)
# - Intranet : 900-1800 (15-30 minutes)
# 
# Trop court : Les utilisateurs sont déconnectés souvent
# Trop long : Ressources gaspillées

# Timeout de connexion de données (en secondes)
data_connection_timeout=300

# Explication :
# Délai max pour établir/compléter un transfert de données
# 
# Si un transfert prend plus de 300 secondes sans activité,
# il est annulé
# 
# Protection contre :
# [OK] Transferts bloqués (clients déconnectés)
# [OK] Connexions de données suspendues
# 
# Recommandations :
# - Fichiers petits/moyens : 120-300
# - Gros fichiers (GB) : 600-1800
# 
# Note : Ce n'est PAS la durée totale du transfert,
# mais le délai SANS ACTIVITÉ

# Timeout d'acceptation de connexion PASV
accept_timeout=60

# Explication :
# Temps max pour qu'un client se connecte après PASV
# 
# Workflow PASV :
# 1. Client : PASV
# 2. Serveur : 227 Entering Passive Mode (IP,PORT)
# 3. Client doit se connecter à IP:PORT
# 
# Si le client ne se connecte pas dans les 60 secondes,
# timeout
# 
# Protection contre :
# [OK] Réservation de ports PASV non utilisés

# Timeout pour établir une connexion
connect_timeout=60

# Explication :
# Délai max pour établir une connexion TCP
# 
# Si le handshake TCP prend > 60 secondes, abandon

# ───────────────────────────────────────────────────────────────
# BANNIÈRE ET ANONYMISATION
# ───────────────────────────────────────────────────────────────

# Bannière de bienvenue personnalisée
ftpd_banner=Serveur FTP sécurisé - Accès autorisé uniquement

# Explication :
# Message affiché lors de la connexion
# 
# Par défaut, vsftpd affiche :
# "220 (vsFTPd 3.0.5)"
# [X] Révèle la version (faille de sécurité !)
# 
# Avec ftpd_banner :
# "220 Serveur FTP sécurisé - Accès autorisé uniquement"
# [OK] Version masquée
# 
# Bonnes pratiques :
# - Ne PAS révéler la version du logiciel
# - Avertir que l'accès est surveillé
# - Message professionnel
# 
# Exemples :
# ftpd_banner=FTP Server Ready
# ftpd_banner=Accès réservé - Toute tentative d'intrusion sera poursuivie

# Cacher les UID/GID réels (afficher "ftp" à la place)
hide_ids=YES

# Explication :
# hide_ids=YES masque les vrais UID/GID dans les listings
# 
# Sans hide_ids (NO) :
# -rw-r--r--    1 2001     2001           25 Dec 16 file.txt
#                 └─ UID   └─ GID
# [X] Révèle les IDs système
# 
# Avec hide_ids (YES) :
# -rw-r--r--    1 ftp      ftp            25 Dec 16 file.txt
# [OK] UID/GID masqués
# 
# Sécurité :
# [OK] Masque la structure interne du système
# [OK] Information gathering plus difficile

# ───────────────────────────────────────────────────────────────
# LOGGING AVANCÉ
# ───────────────────────────────────────────────────────────────

# Activer le logging détaillé
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES

# Explication DÉTAILLÉE du logging :
# 
# xferlog_enable=YES :
# Active l'enregistrement des transferts dans /var/log/vsftpd.log
# 
# xferlog_std_format=NO :
# Utilise le format vsftpd (plus détaillé) au lieu du format xferlog
# 
# Format xferlog (standard) :
# Mon Dec 16 12:00:00 2024 1 192.168.1.50 25 /file.txt b _ o r client1 ftp 0 * c
# 
# Format vsftpd (xferlog_std_format=NO) :
# Mon Dec 16 12:00:00 2024 [pid 1234] [client1] OK UPLOAD: Client "192.168.1.50", "/file.txt", 25 bytes, 123.45Kbyte/sec
# 
# Le format vsftpd inclut :
# [OK] Nom d'utilisateur
# [OK] IP client
# [OK] Commande FTP
# [OK] Chemin complet
# [OK] Vitesse de transfert
# [OK] Taille
# [OK] Code de résultat (OK/FAIL)
# 
# log_ftp_protocol=YES :
# Enregistre TOUTES les commandes FTP (verbose)
# 
# Exemple :
# [pid 1234] [client1] FTP command: USER client1
# [pid 1234] [client1] FTP response: 331 Please specify the password
# [pid 1234] [client1] FTP command: PASS ******
# [pid 1234] [client1] FTP response: 230 Login successful
# [pid 1234] [client1] FTP command: CWD /www
# [pid 1234] [client1] FTP response: 250 Directory successfully changed
# 
# [ATTENTION] Attention : log_ftp_protocol=YES génère BEAUCOUP de logs
# Utiliser uniquement pour :
# - Debugging
# - Audit de sécurité
# - Conformité réglementaire
# 
# En production normale, désactiver (=NO) pour économiser de l'espace

# Fichier de log (par défaut /var/log/vsftpd.log)
vsftpd_log_file=/var/log/vsftpd.log

# Dual logging (vsftpd + xferlog format)
dual_log_enable=YES

# Explication :
# dual_log_enable=YES crée DEUX fichiers de logs :
# 1. /var/log/vsftpd.log (format vsftpd détaillé)
# 2. /var/log/xferlog (format xferlog compatible)
# 
# Avantage :
# [OK] Compatibilité avec des outils d'analyse existants (Webalizer, etc.)
# [OK] Logs détaillés ET standardisés
# 
# Inconvénient :
# [X] Double espace disque consommé

# ───────────────────────────────────────────────────────────────
# RESTRICTIONS SUPPLÉMENTAIRES
# ───────────────────────────────────────────────────────────────

# Interdire les commandes dangereuses
cmds_allowed=FEAT,REST,CWD,LIST,MDTM,MKD,NLST,PASS,PASV,PORT,PWD,QUIT,RETR,RMD,RNFR,RNTO,SIZE,STOR,TYPE,USER,ACCT,APPE,CDUP,HELP,MODE,NOOP,REIN,STAT,STOU,STRU,SYST

# Explication COMPLÈTE :
# 
# cmds_allowed définit une LISTE BLANCHE de commandes FTP autorisées
# 
# Toute commande NON listée sera REFUSÉE
# 
# Commandes listées ci-dessus :
# 
# AUTHENTIFICATION :
# - USER : Nom d'utilisateur
# - PASS : Mot de passe
# - ACCT : Compte (rarement utilisé)
# - REIN : Réinitialiser (ré-authentification)
# 
# NAVIGATION :
# - CWD : Change Working Directory (cd)
# - CDUP : Change Directory UP (cd ..)
# - PWD : Print Working Directory
# 
# LISTING :
# - LIST : Liste détaillée (ls -l)
# - NLST : Liste simple (ls)
# - STAT : Statut
# 
# TRANSFERT :
# - RETR : Télécharger (retrieve)
# - STOR : Uploader (store)
# - APPE : Append (ajouter à un fichier)
# - STOU : Store Unique (upload avec nom unique)
# - REST : Restart (reprendre un transfert)
# - ABOR : Abort (annuler un transfert)
# 
# GESTION FICHIERS :
# - MKD : Make Directory
# - RMD : Remove Directory
# - DELE : Delete file (NON inclus ici pour sécurité)
# - RNFR : Rename From
# - RNTO : Rename To
# - SIZE : Taille du fichier
# - MDTM : Date de modification
# 
# CONNEXION DONNÉES :
# - PASV : Mode passif
# - PORT : Mode actif (si port_enable=YES)
# - TYPE : Type de transfert (ASCII/Binary)
# - MODE : Mode de transfert (Stream/Block/Compressed)
# - STRU : Structure (File/Record/Page)
# 
# INFORMATIONS :
# - FEAT : Features supportées
# - SYST : Système d'exploitation
# - HELP : Aide
# - NOOP : No Operation (keep-alive)
# - QUIT : Déconnexion
# 
# Commandes DANGEREUSES souvent omises :
# - SITE : Commandes spécifiques serveur (peut exécuter du code)
# - CHMOD : Modifier les permissions (dangereux)
# - EXEC : Exécuter des commandes (très dangereux !)
# 
# En n'incluant PAS ces commandes, on renforce la sécurité

# Interdire les utilisateurs système critiques
userlist_enable=YES
userlist_deny=YES
userlist_file=/etc/vsftpd.user_deny

# Explication :
# 
# userlist_enable=YES active le filtrage par liste
# 
# userlist_deny=YES signifie :
# "Les utilisateurs dans userlist_file sont INTERDITS"
# 
# (Inverse : userlist_deny=NO = whitelist, seuls ceux dans la liste sont autorisés)
# 
# userlist_file=/etc/vsftpd.user_deny :
# Fichier contenant les utilisateurs à BANNIR
# 
# Utilité :
# [OK] Empêcher root, admin, postgres, mysql de se connecter en FTP
# [OK] Protection contre l'élévation de privilèges
# 
# Le fichier /etc/ftpusers existe déjà par défaut (même rôle)

# Forcer un umask strict
local_umask=027

# Explication umask 027 :
# 
# umask = Masque de création de fichiers
# 
# Calcul des permissions :
# Permissions par défaut :
# - Fichiers : 666 (rw-rw-rw-)
# - Dossiers : 777 (rwxrwxrwx)
# 
# umask 027 soustrait :
# - Owner : 0 (aucune restriction)
# - Group : 2 (enlève write)
# - Others : 7 (enlève read+write+execute)
# 
# Résultat fichiers : 666 - 027 = 640 (rw-r-----)
# Résultat dossiers : 777 - 027 = 750 (rwxr-x---)
# 
# Sécurité :
# [OK] Le propriétaire a tous les droits
# [OK] Le groupe peut lire (et exécuter pour les dossiers)
# [OK] Les autres (others) n'ont AUCUN accès
# 
# Comparaison :
# umask 022 : rw-r--r-- (644) - Tout le monde peut lire
# umask 027 : rw-r----- (640) - Seulement owner+group
# umask 077 : rw------- (600) - Seulement owner
# 
# Recommandation :
# - Serveur multi-tenant : umask 077 (isolation totale)
# - Serveur collaboratif : umask 027 (partage groupe)
# - Serveur public : umask 022 (lecture publique)

# Désactiver les utilisateurs anonymes (si pas déjà fait)
anonymous_enable=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO

# Explication :
# [OK] Aucune connexion anonyme
# [OK] Aucun upload anonyme
# [OK] Aucune création de dossiers anonyme
# [OK] Aucune modification anonyme
# 
# Toujours désactiver en production !

# ───────────────────────────────────────────────────────────────
# PERFORMANCES ET OPTIMISATIONS
# ───────────────────────────────────────────────────────────────

# Activer TCP wrappers pour filtrage IP
tcp_wrappers=YES

# Explication :
# tcp_wrappers permet d'utiliser /etc/hosts.allow et /etc/hosts.deny
# pour filtrer les connexions par IP
# 
# Exemple /etc/hosts.allow :
# vsftpd: 192.168.1.0/24
# vsftpd: 203.0.113.50
# 
# Exemple /etc/hosts.deny :
# vsftpd: ALL
# 
# Protection contre :
# [OK] Accès depuis des pays/réseaux non autorisés
# [OK] IPs blacklistées connues

# Utiliser sendfile() pour de meilleures performances
use_sendfile=YES

# Explication :
# sendfile() est un appel système Linux qui transfère des données
# directement du disque vers le socket réseau
# 
# SANS sendfile (traditionnel) :
# Disque -> Buffer kernel -> Buffer userspace -> Socket
# (2 copies en mémoire)
# 
# AVEC sendfile :
# Disque -> Socket
# (0 copie en mémoire, transfert direct)
# 
# Avantages :
# [OK] Moins de consommation CPU
# [OK] Moins de consommation RAM
# [OK] Transferts plus rapides (jusqu'à 30% plus rapide)
# 
# Recommandation : TOUJOURS activer

# Enable ASCII mode transfers (optionnel, peut être désactivé pour sécurité)
ascii_upload_enable=NO
ascii_download_enable=NO

# Explication :
# Mode ASCII = Conversion des fins de lignes (CRLF <-> LF)
# Mode Binary = Transfert brut (recommandé)
# 
# Problèmes du mode ASCII :
# [X] Peut corrompre des fichiers binaires
# [X] Plus lent
# [X] Faille potentielle (manipulation de données)
# 
# Recommandation :
# ascii_upload_enable=NO
# ascii_download_enable=NO
# 
# Forcer le mode binaire uniquement

# ───────────────────────────────────────────────────────────────
# SSL/TLS HARDENING (COMPLÉMENTS)
# ───────────────────────────────────────────────────────────────

# Forcer SSL pour TOUT (déjà configuré dans Exercice 3)
ssl_enable=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1_2=YES
ssl_tlsv1_3=YES
ssl_sslv2=NO
ssl_sslv3=NO
ssl_tlsv1=NO
ssl_tlsv1_1=NO

# Cipher suites ultra-sécurisées (TLS 1.3 prioritaire)
ssl_ciphers=TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256

# Explication cipher suites TLS 1.3 :
# 
# TLS 1.3 simplifie énormément :
# - Pas de négociation d'échange de clés (toujours ECDHE)
# - Pas de signature (toujours RSA ou ECDSA)
# - Seulement AEAD cipher (Authenticated Encryption with Associated Data)
# 
# TLS_AES_256_GCM_SHA384 :
# - Chiffrement : AES-256 en mode GCM (Galois/Counter Mode)
# - Authentification : intégrée dans GCM
# - Hash : SHA-384
# - Sécurité : Excellente (256 bits)
# 
# TLS_CHACHA20_POLY1305_SHA256 :
# - Chiffrement : ChaCha20 (stream cipher)
# - Authentification : Poly1305
# - Hash : SHA-256
# - Avantage : Plus rapide sur mobile (pas d'AES hardware)
# 
# TLS_AES_128_GCM_SHA256 :
# - Comme AES-256-GCM mais 128 bits
# - Plus rapide, toujours sécurisé (128 bits suffisants)
# 
# Cipher suites TLS 1.2 (backward compatibility) :
# ECDHE-RSA-AES256-GCM-SHA384 :
# - ECDHE : Elliptic Curve Diffie-Hellman Ephemeral (Perfect Forward Secrecy)
# - RSA : Signature/auth
# - AES256-GCM : Chiffrement
# - SHA384 : Hash
# 
# Perfect Forward Secrecy (PFS) :
# Chaque session utilise une clé éphémère unique
# Si la clé privée du serveur est compromise,
# les anciennes sessions restent sécurisées

# Exiger la réutilisation de session SSL
ssl_reuse=YES
require_ssl_reuse=YES

# Explication require_ssl_reuse :
# 
# require_ssl_reuse=YES :
# Les connexions de DONNÉES doivent réutiliser la session SSL
# de la connexion de CONTRÔLE
# 
# Protection contre :
# [OK] Attaques MITM sur le canal de données
# [OK] Session hijacking
# 
# Sans require_ssl_reuse :
# - Canal contrôle : SSL session A
# - Canal données : SSL session B (différente)
# [X] Un attaquant pourrait intercepter le canal données
# 
# Avec require_ssl_reuse :
# - Canal contrôle : SSL session A
# - Canal données : DOIT utiliser session A
# [OK] Même niveau de sécurité sur les deux canaux

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde : `Ctrl + O`, `Entrée`, `Ctrl + X`**

---

**Créer le fichier de blacklist utilisateurs :**

```bash
sudo nano /etc/vsftpd.user_deny
```

**Contenu :**

```
root
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody
systemd-network
systemd-resolve
systemd-timesync
messagebus
syslog
_apt
uuidd
avahi-autoipd
usbmux
dnsmasq
rtkit
cups-pk-helper
speech-dispatcher
whoopsie
kernoops
saned
pulse
avahi
colord
hplip
geoclue
gnome-initial-setup
gdm
postgres
mysql
redis
mongodb
elasticsearch
```

**Sauvegarde.**

---

**Redémarrer vsftpd :**

```bash
sudo systemctl restart vsftpd
sudo systemctl status vsftpd
```

**[OK] vsftpd hardenné !**

---

### ÉTAPE 2 : Fail2Ban avancé avec règles personnalisées

**Créer un filtre personnalisé pour détecter les scans de ports :**

```bash
sudo nano /etc/fail2ban/filter.d/vsftpd-portscan.conf
```

**Contenu :**

```ini
# Fail2Ban filter pour détecter les scans de ports FTP
#

[Definition]

# Détection de connexions répétées sans authentification
failregex = ^.*"CONNECT".* from <HOST>$
            ^.*disconnect from <HOST>.*$
            ^.*Connection refused from <HOST>.*$
            ^.* \[<HOST>\] FAIL LOGIN.*$
            ^.* \[<HOST>\] FTP command: USER.*$
            ^.* \[<HOST>\] FTP response: 530.*$

ignoreregex =

[Init]
datepattern = ^%%a %%b %%d %%H:%%M:%%S %%Y
```

---

**Créer un filtre pour attaques par force brute avancées :**

```bash
sudo nano /etc/fail2ban/filter.d/vsftpd-aggressive.conf
```

**Contenu :**

```ini
# Fail2Ban filter aggressif pour vsftpd

[Definition]

# Multiples échecs d'authentification
failregex = ^.*\[.*\] FAIL LOGIN: Client "<HOST>".*$
            ^.*authentication failure.*rhost=<HOST>.*$
            ^.*USER.*Login incorrect.*<HOST>.*$
            ^.*\[<HOST>\] FTP response: 530 Login incorrect.*$
            ^.*failed login from <HOST>.*$
            ^.* pam_unix\(vsftpd:auth\):.*authentication failure.*rhost=<HOST>.*$

ignoreregex =
```

---

**Configurer les jails :**

```bash
sudo nano /etc/fail2ban/jail.d/vsftpd-custom.conf
```

**Contenu :**

```ini
# ═══════════════════════════════════════════════════════════════
# FAIL2BAN - CONFIGURATION AVANCÉE POUR VSFTPD
# ═══════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────
# JAIL 1 : PROTECTION STANDARD
# ───────────────────────────────────────────────────────────────

[vsftpd]
enabled = true
port = ftp,ftps,21,990
filter = vsftpd
logpath = /var/log/vsftpd.log

# Bannir après 3 échecs
maxretry = 3

# Durée du bannissement : 1 heure (3600 secondes)
bantime = 3600

# Fenêtre de temps pour compter les échecs : 10 minutes
findtime = 600

# Explication :
# Si 3 échecs d'authentification en 10 minutes (600s),
# -> Bannir l'IP pendant 1 heure (3600s)
# 
# Exemple timeline :
# 10:00 - Échec 1
# 10:02 - Échec 2
# 10:05 - Échec 3 -> BAN jusqu'à 11:05

# ───────────────────────────────────────────────────────────────
# JAIL 2 : PROTECTION CONTRE LES SCANS DE PORTS
# ───────────────────────────────────────────────────────────────

[vsftpd-portscan]
enabled = true
port = ftp,ftps
filter = vsftpd-portscan
logpath = /var/log/vsftpd.log

# Bannir après 5 connexions suspectes
maxretry = 5

# Bannissement long : 24 heures
bantime = 86400

# Fenêtre de détection : 5 minutes
findtime = 300

# Explication :
# Détecte les connexions répétées sans tentative d'authentification
# = Comportement typique d'un scanner de ports
# 
# Bannissement plus long (24h) car comportement malveillant évident

# ───────────────────────────────────────────────────────────────
# JAIL 3 : PROTECTION AGRESSIVE (BRUTE FORCE)
# ───────────────────────────────────────────────────────────────

[vsftpd-aggressive]
enabled = true
port = ftp,ftps
filter = vsftpd-aggressive
logpath = /var/log/vsftpd.log

# Très strict : bannir après 2 échecs seulement
maxretry = 2

# Bannissement très long : 7 jours
bantime = 604800

# Fenêtre courte : 5 minutes
findtime = 300

# Explication :
# Protection maximale contre les attaques par force brute
# Dès 2 échecs en 5 minutes -> Bannissement 7 jours
# 
# [ATTENTION] Peut bloquer des utilisateurs légitimes qui oublient leur mot de passe
# À utiliser seulement si attaques fréquentes

# ───────────────────────────────────────────────────────────────
# JAIL 4 : BANNISSEMENT PERMANENT (RECIDIVISTES)
# ───────────────────────────────────────────────────────────────

[vsftpd-recidive]
enabled = true
port = ftp,ftps
filter = recidive
logpath = /var/log/fail2ban.log

# Si déjà banni 3 fois
maxretry = 3

# Bannissement PERMANENT (-1 = infini)
bantime = -1

# Sur une période de 30 jours
findtime = 2592000

# Explication :
# Le filtre "recidive" surveille les LOGS DE FAIL2BAN
# (pas les logs vsftpd)
# 
# Si une IP est bannie 3 fois en 30 jours,
# -> Bannissement PERMANENT
# 
# Protection contre :
# [OK] Attaquants persistants
# [OK] Botnets qui réessayent après expiration du ban
# 
# Pour débannir manuellement :
# fail2ban-client set vsftpd-recidive unbanip <IP>

# ───────────────────────────────────────────────────────────────
# ACTIONS AVANCÉES
# ───────────────────────────────────────────────────────────────

# Action par défaut : bannir + envoyer un email
action = %(action_mwl)s

# Explication des actions disponibles :
# 
# action_        : Bannir uniquement (iptables DROP)
# action_mw      : Bannir + email (whois info)
# action_mwl     : Bannir + email + logs
# action_xarf    : Bannir + envoyer XARF report
# action_cf_mwl  : Bannir + Cloudflare + email
# 
# action_mwl envoie un email avec :
# - IP bannie
# - Nombre de tentatives
# - Informations whois de l'IP
# - Extrait des logs

# Configuration email (à adapter)
# destemail = admin@example.com
# sender = fail2ban@example.com
# sendername = Fail2Ban FTP Server

# ───────────────────────────────────────────────────────────────
# WHITELIST (IPS À NE JAMAIS BANNIR)
# ───────────────────────────────────────────────────────────────

[DEFAULT]
# IPs ignorées (séparées par des espaces)
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 10.0.0.0/8

# Explication :
# ignoreip liste les IPs/réseaux à JAMAIS bannir
# 
# Toujours inclure :
# - 127.0.0.1/8 : Localhost
# - ::1 : Localhost IPv6
# - Ton réseau interne (ex: 192.168.1.0/24)
# - IP de l'admin
# 
# [ATTENTION] CRITIQUE : Toujours whitelister ton IP !
# Sinon tu risques de te bloquer toi-même

# ═══════════════════════════════════════════════════════════════
```

**Sauvegarde.**

---

**Redémarrer Fail2Ban :**

```bash
sudo systemctl restart fail2ban
```

---

**Vérifier les jails actives :**

```bash
sudo fail2ban-client status
```

**Résultat :**

```
Status
|- Number of jail:      4
`- Jail list:   vsftpd, vsftpd-portscan, vsftpd-aggressive, vsftpd-recidive
```

**[OK] 4 jails actives !**

---

**Vérifier une jail spécifique :**

```bash
sudo fail2ban-client status vsftpd-aggressive
```

**Résultat :**

```
Status for the jail: vsftpd-aggressive
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/vsftpd.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:
```

---

**Tester Fail2Ban (simulation d'attaque) :**

```bash
# Plusieurs tentatives échouées
for i in {1..5}; do
    echo "Tentative $i"
    ftp localhost <<EOF
baduser
badpass
quit
EOF
    sleep 2
done
```

**Vérifier si l'IP locale est bannie :**

```bash
sudo fail2ban-client status vsftpd
```

**Débannir (si nécessaire) :**

```bash
sudo fail2ban-client set vsftpd unbanip 127.0.0.1
```

---

### ÉTAPE 3 : Script de monitoring avancé

```bash
sudo nano /usr/local/bin/monitor-ftp.sh
```

**Contenu :**

```bash
#!/bin/bash
# ═══════════════════════════════════════════════════════════════
# SCRIPT DE MONITORING FTP AVANCÉ
# ═══════════════════════════════════════════════════════════════

# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Seuils d'alerte
CPU_THRESHOLD=80
RAM_THRESHOLD=80
DISK_THRESHOLD=85
MAX_CONNECTIONS=150
MIN_DISK_SPACE_GB=10

# ───────────────────────────────────────────────────────────────
# FONCTION D'ALERTE
# ───────────────────────────────────────────────────────────────

send_alert() {
    local subject=$1
    local message=$2
    
    # Log l'alerte
    echo "[ALERTE] $(date '+%Y-%m-%d %H:%M:%S') - $subject: $message" >> /var/log/ftp-monitoring.log
    
    # Envoyer email (si configuré)
    # echo "$message" | mail -s "[FTP] $subject" admin@example.com
    
    # Notification Slack (optionnel)
    # curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
    #   -H 'Content-Type: application/json' \
    #   -d "{\"text\":\"$subject: $message\"}"
}

# ───────────────────────────────────────────────────────────────
# 1. VÉRIFIER L'ÉTAT DU SERVICE
# ───────────────────────────────────────────────────────────────

echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo -e "${BLUE}   MONITORING SERVEUR FTP - $(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo ""

echo -e "${YELLOW}[1] ÉTAT DU SERVICE VSFTPD${NC}"
if systemctl is-active --quiet vsftpd; then
    echo -e "${GREEN}[OK] vsftpd est actif${NC}"
else
    echo -e "${RED}[X] vsftpd est INACTIF !${NC}"
    send_alert "Service Down" "vsftpd est arrêté !"
    # Tentative de redémarrage automatique
    systemctl restart vsftpd
fi
echo ""

# ───────────────────────────────────────────────────────────────
# 2. CONNEXIONS ACTIVES
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[2] CONNEXIONS ACTIVES${NC}"

# Connexions sur port 21
CONNECTIONS_21=$(netstat -an | grep ":21 " | grep ESTABLISHED | wc -l)
echo "Connexions port 21 (contrôle) : $CONNECTIONS_21"

# Connexions sur plage passive
CONNECTIONS_PASV=$(netstat -an | grep -E ":(40[0-9]{3}|4[1-9][0-9]{3}|50000) " | grep ESTABLISHED | wc -l)
echo "Connexions passives (40000-50000) : $CONNECTIONS_PASV"

# Total
TOTAL_CONNECTIONS=$((CONNECTIONS_21 + CONNECTIONS_PASV))
echo -e "Total : ${BLUE}$TOTAL_CONNECTIONS${NC}"

# Alerte si trop de connexions
if [ $TOTAL_CONNECTIONS -gt $MAX_CONNECTIONS ]; then
    echo -e "${RED}[ATTENTION] ALERTE : Nombre de connexions élevé !${NC}"
    send_alert "Connexions élevées" "$TOTAL_CONNECTIONS connexions actives (seuil: $MAX_CONNECTIONS)"
fi
echo ""

# ───────────────────────────────────────────────────────────────
# 3. UTILISATEURS CONNECTÉS
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[3] UTILISATEURS CONNECTÉS${NC}"

# Extraire des processus vsftpd
ps aux | grep vsftpd | grep -v grep | awk '{print $1, $11}' | sort | uniq -c | while read count user info; do
    if [ "$user" != "root" ]; then
        echo "  $user : $count session(s)"
    fi
done
echo ""

# ───────────────────────────────────────────────────────────────
# 4. TOP 10 IPS CONNECTÉES
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[4] TOP 10 IPS CONNECTÉES${NC}"
netstat -an | grep ":21 " | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
echo ""

# ───────────────────────────────────────────────────────────────
# 5. TRANSFERTS EN COURS
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[5] TRANSFERTS EN COURS${NC}"
TRANSFERS=$(lsof -i :40000-50000 2>/dev/null | grep ESTABLISHED | wc -l)
echo "Nombre de transferts : $TRANSFERS"
echo ""

# ───────────────────────────────────────────────────────────────
# 6. RESSOURCES SYSTÈME
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[6] RESSOURCES SYSTÈME${NC}"

# CPU
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
CPU_INT=$(printf "%.0f" $CPU_USAGE)
if [ $CPU_INT -gt $CPU_THRESHOLD ]; then
    echo -e "CPU : ${RED}${CPU_INT}%${NC} [ATTENTION]"
    send_alert "CPU élevé" "Utilisation CPU : ${CPU_INT}% (seuil: $CPU_THRESHOLD%)"
else
    echo -e "CPU : ${GREEN}${CPU_INT}%${NC}"
fi

# RAM
RAM_USAGE=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}')
if [ $RAM_USAGE -gt $RAM_THRESHOLD ]; then
    echo -e "RAM : ${RED}${RAM_USAGE}%${NC} [ATTENTION]"
    send_alert "RAM élevée" "Utilisation RAM : ${RAM_USAGE}% (seuil: $RAM_THRESHOLD%)"
else
    echo -e "RAM : ${GREEN}${RAM_USAGE}%${NC}"
fi

# Disque (/srv/ftp)
DISK_USAGE=$(df -h /srv/ftp | tail -1 | awk '{print $5}' | sed 's/%//')
DISK_AVAIL_GB=$(df -BG /srv/ftp | tail -1 | awk '{print $4}' | sed 's/G//')

if [ $DISK_USAGE -gt $DISK_THRESHOLD ]; then
    echo -e "Disque /srv/ftp : ${RED}${DISK_USAGE}%${NC} [ATTENTION] (${DISK_AVAIL_GB} GB disponibles)"
    send_alert "Disque plein" "Disque /srv/ftp à ${DISK_USAGE}% (seuil: $DISK_THRESHOLD%)"
elif [ $DISK_AVAIL_GB -lt $MIN_DISK_SPACE_GB ]; then
    echo -e "Disque /srv/ftp : ${YELLOW}${DISK_USAGE}%${NC} [ATTENTION] (${DISK_AVAIL_GB} GB disponibles)"
    send_alert "Disque faible" "Seulement ${DISK_AVAIL_GB} GB disponibles (minimum: $MIN_DISK_SPACE_GB GB)"
else
    echo -e "Disque /srv/ftp : ${GREEN}${DISK_USAGE}%${NC} (${DISK_AVAIL_GB} GB disponibles)"
fi
echo ""

# ───────────────────────────────────────────────────────────────
# 7. DERNIÈRES ERREURS (30 minutes)
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[7] DERNIÈRES ERREURS (30 minutes)${NC}"
ERRORS_COUNT=$(journalctl -u vsftpd --since "30 minutes ago" | grep -i "error\|fail\|refused" | wc -l)
if [ $ERRORS_COUNT -gt 0 ]; then
    echo -e "${RED}$ERRORS_COUNT erreur(s) détectée(s)${NC}"
    journalctl -u vsftpd --since "30 minutes ago" | grep -i "error\|fail\|refused" | tail -5
else
    echo -e "${GREEN}Aucune erreur${NC}"
fi
echo ""

# ───────────────────────────────────────────────────────────────
# 8. FAIL2BAN STATUS
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[8] FAIL2BAN - IPS BANNIES${NC}"
BANNED_COUNT=$(fail2ban-client status vsftpd 2>/dev/null | grep "Currently banned" | awk '{print $4}')
if [ -n "$BANNED_COUNT" ] && [ $BANNED_COUNT -gt 0 ]; then
    echo -e "${RED}$BANNED_COUNT IP(s) bannie(s)${NC}"
    fail2ban-client status vsftpd | grep "Banned IP list" | cut -d: -f2
else
    echo -e "${GREEN}Aucune IP bannie${NC}"
fi
echo ""

# ───────────────────────────────────────────────────────────────
# 9. STATISTIQUES DES DERNIÈRES 24H
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[9] STATISTIQUES 24H${NC}"

# Uploads
UPLOADS=$(grep -c "OK UPLOAD" /var/log/vsftpd.log 2>/dev/null || echo 0)
echo "Uploads : $UPLOADS"

# Downloads
DOWNLOADS=$(grep -c "OK DOWNLOAD" /var/log/vsftpd.log 2>/dev/null || echo 0)
echo "Downloads : $DOWNLOADS"

# Échecs de login
FAILED_LOGINS=$(grep -c "FAIL LOGIN" /var/log/vsftpd.log 2>/dev/null || echo 0)
echo "Échecs de login : $FAILED_LOGINS"

# Connexions réussies
SUCCESSFUL_LOGINS=$(grep -c "OK LOGIN" /var/log/vsftpd.log 2>/dev/null || echo 0)
echo "Connexions réussies : $SUCCESSFUL_LOGINS"
echo ""

# ───────────────────────────────────────────────────────────────
# 10. CERTIFICAT SSL
# ───────────────────────────────────────────────────────────────

echo -e "${YELLOW}[10] CERTIFICAT SSL${NC}"
CERT_FILE="/etc/ssl/certs/vsftpd.crt"
if [ -f "$CERT_FILE" ]; then
    EXPIRY_DATE=$(openssl x509 -enddate -noout -in $CERT_FILE | cut -d= -f2)
    EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
    NOW_EPOCH=$(date +%s)
    DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
    
    if [ $DAYS_LEFT -lt 30 ]; then
        echo -e "${RED}[ATTENTION] Expire dans $DAYS_LEFT jours !${NC}"
        send_alert "Certificat SSL" "Le certificat expire dans $DAYS_LEFT jours"
    elif [ $DAYS_LEFT -lt 60 ]; then
        echo -e "${YELLOW}Expire dans $DAYS_LEFT jours${NC}"
    else
        echo -e "${GREEN}Valide ($DAYS_LEFT jours restants)${NC}"
    fi
else
    echo -e "${RED}Certificat introuvable !${NC}"
fi
echo ""

echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
```

**Sauvegarde.**

---

**Rendre exécutable :**

```bash
sudo chmod +x /usr/local/bin/monitor-ftp.sh
```

---

**Tester :**

```bash
sudo /usr/local/bin/monitor-ftp.sh
```

**Résultat exemple :**

```
═══════════════════════════════════════════════════════
   MONITORING SERVEUR FTP - 2024-12-16 14:30:00
═══════════════════════════════════════════════════════

[1] ÉTAT DU SERVICE VSFTPD
[OK] vsftpd est actif

[2] CONNEXIONS ACTIVES
Connexions port 21 (contrôle) : 5
Connexions passives (40000-50000) : 3
Total : 8

[3] UTILISATEURS CONNECTÉS
  client1 : 2 session(s)
  client2 : 1 session(s)

[4] TOP 10 IPS CONNECTÉES
      3 192.168.1.50
      2 192.168.1.51
      1 203.0.113.100

[5] TRANSFERTS EN COURS
Nombre de transferts : 3

[6] RESSOURCES SYSTÈME
CPU : 15%
RAM : 42%
Disque /srv/ftp : 35% (50 GB disponibles)

[7] DERNIÈRES ERREURS (30 minutes)
Aucune erreur

[8] FAIL2BAN - IPS BANNIES
Aucune IP bannie

[9] STATISTIQUES 24H
Uploads : 142
Downloads : 367
Échecs de login : 12
Connexions réussies : 198

[10] CERTIFICAT SSL
Valide (325 jours restants)

═══════════════════════════════════════════════════════
```

---

**Automatiser avec cron (toutes les 5 minutes) :**

```bash
sudo crontab -e
```

**Ajouter :**

```
*/5 * * * * /usr/local/bin/monitor-ftp.sh >> /var/log/ftp-monitoring.log 2>&1
```

---

### ÉTAPE 4 : Audit de sécurité complet

**Installer les outils d'audit :**

```bash
sudo apt install nmap lynis nikto -y
```

---

#### 4.1 - Scan de ports avec Nmap

```bash
sudo nmap -sV -sC -p21,990,40000-50000 localhost
```

**Explication :**
- `-sV` = Détection de version
- `-sC` = Scripts de sécurité par défaut
- `-p` = Ports à scanner

**Résultat exemple :**

```
PORT      STATE SERVICE VERSION
21/tcp    open  ftp     vsftpd 3.0.5
| ssl-cert: Subject: commonName=ftp.example.com
| Not valid before: 2024-12-16T12:00:00
|_Not valid after:  2025-12-16T12:00:00
|_ssl-date: TLS randomness does not represent time
| ftp-anon: Anonymous FTP login disallowed
40000/tcp open  unknown
40001/tcp open  unknown
...
```

**[OK] Vérifications :**
- Anonymous FTP : disallowed [OK]
- SSL présent [OK]
- Pas de services inattendus [OK]

---

#### 4.2 - Audit SSL/TLS

```bash
nmap --script ssl-enum-ciphers -p 21 localhost
```

**Résultat attendu :**

```
PORT   STATE SERVICE
21/tcp open  ftp
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|   TLSv1.3: 
|     ciphers: 
|       TLS_AKE_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|_  least strength: A
```

**[OK] Que des cipher suites "A" !**

---

#### 4.3 - Audit système avec Lynis

```bash
sudo lynis audit system
```

**Lynis vérifie :**
- Configuration du système
- Sécurité des services
- Permissions des fichiers
- Configurations réseau
- etc.

**Rapport :**

```
...
[+] Software: FTP
-------------------------------
  - Checking FTP daemon                                   [ VSFTPD ]
    - Checking vsftpd configuration                        [ OK ]
  - Anonymous FTP access                                  [ DISABLED ]
...

Hardening index : 78

System has been hardened:
  [OK] Firewall enabled
  [OK] SSH properly configured
  [OK] No unnecessary services
  [ATTENTION] Some kernel parameters can be improved

Suggestions:
  - Harden kernel parameters (sysctl)
  - Enable process accounting
  - Install intrusion detection (AIDE)
```

**Suivre les recommandations de Lynis.**

---

### ÉTAPE 5 : Optimisation des performances

#### 5.1 - Tuning kernel

```bash
sudo nano /etc/sysctl.d/99-ftp-tuning.conf
```

**Contenu :**

```conf
# Tuning réseau pour FTP haute performance

# Augmenter la taille des buffers TCP
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864

# Augmenter la backlog de connexions
net.core.netdev_max_backlog = 5000
net.core.somaxconn = 1024

# Activer TCP Fast Open
net.ipv4.tcp_fastopen = 3

# Tuning TCP
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1

# Augmenter les limites de fichiers
fs.file-max = 2097152
```

**Appliquer :**

```bash
sudo sysctl -p /etc/sysctl.d/99-ftp-tuning.conf
```

---

#### 5.2 - Limites utilisateur

```bash
sudo nano /etc/security/limits.conf
```

**Ajouter :**

```
*               soft    nofile          65536
*               hard    nofile          65536
root            soft    nofile          65536
root            hard    nofile          65536
```

---

#### 5.3 - Test de charge

**Installer un outil de test :**

```bash
sudo apt install python3-pip -y
pip3 install ftpbench
```

**Ou utiliser `lftp` en parallèle :**

```bash
#!/bin/bash
# test-load.sh

for i in {1..100}; do
    (
        lftp -u client1,ClientPass1! localhost <<EOF
set ftp:ssl-force true
set ssl:verify-certificate no
ls
quit
EOF
    ) &
done

wait
echo "100 connexions simultanées terminées"
```

**Surveiller pendant le test :**

```bash
watch -n1 'netstat -an | grep ":21 " | wc -l'
```

---

### ÉTAPE 6 : Plan de Disaster Recovery

**Créer un script de sauvegarde complète :**

```bash
sudo nano /usr/local/bin/full-backup-ftp.sh
```

**Contenu :**

```bash
#!/bin/bash
# Sauvegarde complète FTP

BACKUP_DIR="/var/backups/ftp-complete"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="ftp_full_$DATE"

mkdir -p "$BACKUP_DIR"

# Créer l'archive
tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" \
  /etc/vsftpd/ \
  /srv/ftp/ \
  /etc/fail2ban/jail.d/vsftpd*.conf \
  /etc/fail2ban/filter.d/vsftpd*.conf \
  /etc/ssl/certs/vsftpd.crt \
  /etc/ssl/private/vsftpd.key \
  /var/log/vsftpd.log

# Hash SHA256
sha256sum "$BACKUP_DIR/$BACKUP_NAME.tar.gz" > "$BACKUP_DIR/$BACKUP_NAME.sha256"

# Rotation (garder 7 derniers)
ls -t "$BACKUP_DIR"/ftp_full_*.tar.gz | tail -n +8 | xargs -r rm

echo "Sauvegarde créée : $BACKUP_DIR/$BACKUP_NAME.tar.gz"
```

**Rendre exécutable et planifier :**

```bash
sudo chmod +x /usr/local/bin/full-backup-ftp.sh
sudo crontab -e
```

**Ajouter :**

```
# Sauvegarde complète tous les jours à 2h
0 2 * * * /usr/local/bin/full-backup-ftp.sh
```

---

**Procédure de restauration :**

```bash
#!/bin/bash
# restore-ftp.sh

BACKUP_FILE=$1

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 <backup_file.tar.gz>"
    exit 1
fi

# Vérifier le hash
sha256sum -c "${BACKUP_FILE}.sha256" || exit 1

# Arrêter vsftpd
systemctl stop vsftpd

# Restaurer
tar -xzf "$BACKUP_FILE" -C /

# Redémarrer
systemctl start vsftpd

echo "Restauration terminée"
```

---

### [OK] CHECKLIST DE CONFORMITÉ (PCI-DSS / OWASP)

**Créer un document de conformité :**

```bash
sudo nano /root/ftp-security-checklist.md
```

**Contenu :**

```markdown
# CHECKLIST DE SÉCURITÉ FTP - CONFORMITÉ PCI-DSS/OWASP

## 1. AUTHENTIFICATION

- [x] Désactiver l'accès anonyme (anonymous_enable=NO)
- [x] Force les mots de passe forts (validation dans scripts)
- [x] Authentification chiffrée obligatoire (force_local_logins_ssl=YES)
- [x] Limitation des tentatives (max_login_fails=3)
- [x] Utilisateurs virtuels (isolation)
- [x] Fail2ban configuré (bannissement automatique)

## 2. CHIFFREMENT

- [x] SSL/TLS activé (ssl_enable=YES)
- [x] Protocoles sécurisés uniquement (TLS 1.2+)
- [x] Cipher suites modernes (HIGH:!aNULL:!MD5:!3DES:!RC4)
- [x] Chiffrement du canal de données (force_local_data_ssl=YES)
- [x] Certificat SSL valide (validité vérifiée)
- [x] SSL session reuse (require_ssl_reuse=YES)

## 3. CONTRÔLE D'ACCÈS

- [x] Chroot jail activé (chroot_local_user=YES)
- [x] Permissions strictes (umask 027)
- [x] Whitelist d'utilisateurs (userlist_enable)
- [x] Blacklist d'utilisateurs système (root, admin, etc.)
- [x] Limitation par IP (max_per_ip=3)
- [x] TCP wrappers (tcp_wrappers=YES)

## 4. LOGGING ET AUDIT

- [x] Logs détaillés activés (log_ftp_protocol=YES)
- [x] Dual logging (vsftpd + xferlog)
- [x] Rotation des logs (logrotate)
- [x] Monitoring en temps réel (scripts)
- [x] Alertes configurées (email/Slack)
- [x] Rétention des logs (90 jours minimum)

## 5. PROTECTION CONTRE LES ATTAQUES

- [x] Fail2ban actif (4 jails)
- [x] Limitation de connexions (max_clients=200)
- [x] Timeouts configurés (idle_session_timeout)
- [x] Rate limiting (max_per_ip)
- [x] Protection DDoS (kernel tuning)
- [x] Firewall configuré (ufw/iptables)

## 6. DISPONIBILITÉ

- [x] Monitoring 24/7 (scripts cron)
- [x] Alertes automatiques
- [x] Sauvegarde quotidienne
- [x] Plan de disaster recovery testé
- [x] Procédure de restauration documentée
- [x] Haute disponibilité (optionnel)

## 7. CONFORMITÉ

- [x] Documentation complète
- [x] Audit de sécurité effectué (Lynis, nmap)
- [x] Scan de vulnérabilités (pas de vulnérabilités critiques)
- [x] Tests de pénétration (recommandé annuellement)
- [x] Revue des accès (trimestrielle)
- [x] Mise à jour de sécurité (mensuelle)

## SCORE GLOBAL : 100%

Dernière revue : 2024-12-16
Prochaine revue : 2025-01-16
Auditeur : [Nom]
```

---

## [COURS] CONCLUSION FINALE - EXERCICES 1 À 5

**[BRAVO] FÉLICITATIONS ! TU AS TERMINÉ L'INTÉGRALITÉ DE LA FORMATION FTP/FTPS ! [BRAVO]**

### Récapitulatif complet

**Tu as appris (en 5 exercices) :**

**EXERCICE 1 - Fondamentaux :**
- Architecture FTP (contrôle + données)
- Installation et configuration vsftpd de base
- Chroot jail
- Utilisateurs Linux
- Logs et dépannage

**EXERCICE 2 - Utilisateurs virtuels :**
- Berkeley DB
- PAM (Pluggable Authentication Modules)
- Mapping utilisateur (guest_enable)
- Configuration par utilisateur
- Isolation complète

**EXERCICE 3 - FTPS (Sécurité) :**
- Certificats SSL/TLS (OpenSSL)
- FTPS Explicite vs Implicite
- Cipher suites sécurisées
- Protocoles SSL/TLS (TLS 1.2+)
- Chiffrement de bout en bout

**EXERCICE 4 - Production :**
- Mode passif FTP
- NAT et masq_address
- Automatisation (scripts Bash)
- Fail2ban
- Firewall (ufw/iptables)
- Rotation de logs

**EXERCICE 5 - Enterprise :**
- Hardening complet
- Fail2ban avancé (4 jails)
- Monitoring temps réel
- Audit de sécurité (Lynis, Nmap)
- Optimisation performances
- Disaster recovery
- Conformité PCI-DSS/OWASP

---

### Compétences maîtrisées

**[OK] Administration système Linux avancée**
**[OK] Sécurité réseau et chiffrement**
**[OK] Scripting Bash professionnel**
**[OK] Monitoring et alerting**
**[OK] Audit de sécurité**
**[OK] Conformité réglementaire**
**[OK] Optimisation performances**
**[OK] Architecture enterprise-grade**

---

### Certification de compétences

Tu es maintenant capable de :

1. **Déployer** un serveur FTP/FTPS sécurisé en production
2. **Gérer** des centaines d'utilisateurs virtuels
3. **Sécuriser** contre toutes les attaques courantes
4. **Monitorer** et **alerter** en temps réel
5. **Auditer** la conformité aux standards
6. **Optimiser** pour 1000+ utilisateurs simultanés
7. **Documenter** pour certification
8. **Maintenir** un SLA 99.9%

---

### Prochaines étapes (optionnel)

**Pour aller encore plus loin :**

1. **Haute disponibilité :**
   - Load balancing (HAProxy, Nginx)
   - Cluster actif-actif
   - Stockage distribué (GlusterFS, Ceph)

2. **Intégrations avancées :**
   - LDAP/Active Directory
   - MySQL pour utilisateurs virtuels
   - Prometheus + Grafana (dashboards)

3. **Automatisation DevOps :**
   - Ansible playbooks
   - Docker containers
   - Terraform (IaC)
   - CI/CD (GitLab CI, Jenkins)

4. **Certification professionnelle :**
   - CompTIA Security+
   - CISSP
   - RHCE (Red Hat)

---

### Documentation finale

**Tu as maintenant 5 exercices complets couvrant :**

- [FICHIER] **150+ pages de documentation**
- [CODE] **50+ scripts et configurations**
- [SECURISE] **30+ bonnes pratiques de sécurité**
- [OUTILS] **100+ commandes Linux**
- [GRAPHIQUE] **10+ outils d'audit et monitoring**

---

### Support et ressources

**Documentation officielle :**
- vsftpd : https://security.appspot.com/vsftpd.html
- OpenSSL : https://www.openssl.org/docs/
- Fail2ban : https://www.fail2ban.org/

**Standards de sécurité :**
- PCI-DSS : https://www.pcisecuritystandards.org/
- OWASP : https://owasp.org/
- NIST : https://www.nist.gov/

---

## [RAPIDE] TU ES PRÊT POUR LA PRODUCTION !

**Temps total de formation : ~12-15 heures**  
**Niveau atteint : Expert FTP/FTPS**  
**Taux de complétion : 100%**

**Bon courage pour tes projets professionnels ! [FORCE]**