Module 1 — Linux serveur sécurisé

Provisionner un VPS, durcir SSH, installer un pare-feu, automatiser les patches, auditer les logs. Les fondamentaux d'admin sécu.

🚀 Provisionnement d'un VPS — checklist J0

Dès que votre VPS est créé chez Hetzner / Scaleway / OVH, vous avez ~60 minutes avant que les bots commencent à brute-force votre SSH. Voici le runbook à dérouler immédiatement.

1. Connexion initiale

# Récupérer l'IP dans le panel du provider
ssh root@<IP>
# (mot de passe envoyé par email ou clé SSH ajoutée lors de la création)

2. Mise à jour complète

apt update && apt upgrade -y
apt autoremove -y
# Redémarrer si le kernel a été mis à jour
[ -f /var/run/reboot-required ] && reboot

3. Créer un user nominatif

adduser francois
usermod -aG sudo francois
# Copier vos clés SSH actuelles vers le nouvel user
mkdir -p /home/francois/.ssh
cp ~/.ssh/authorized_keys /home/francois/.ssh/
chown -R francois:francois /home/francois/.ssh
chmod 700 /home/francois/.ssh
chmod 600 /home/francois/.ssh/authorized_keys

# Tester la connexion AVANT de fermer la session root
# (dans un autre terminal)
ssh francois@<IP>
sudo whoami  # doit retourner "root"
JAMAIS fermer la session root avant d'avoir testé le nouvel user

Si vous fermez sans tester et que la connexion sudo ne marche pas, vous êtes lock out de votre propre serveur. Solution : passer par la console web du provider (lente, douloureuse). Faites TOUJOURS le test en parallèle dans un 2e terminal.

🔑 Durcir SSH

L'attaque #1 sur un VPS est le brute-force SSH. Quelques règles éliminent 99 % des tentatives.

Désactiver login root + auth password

sudo nano /etc/ssh/sshd_config

# Modifications à faire (ou ajouter si absentes) :
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
# (Optionnel) changer le port pour réduire le bruit dans les logs
Port 2222

sudo systemctl restart sshd

Générer une bonne clé (côté client)

# Sur votre machine locale :
ssh-keygen -t ed25519 -C "francois@ezway-laptop-2026"
# Passphrase OBLIGATOIRE (l'agent SSH la mémorise pour la session)

# Vérifier la clé publique
cat ~/.ssh/id_ed25519.pub

# Ajouter au ssh-agent (chaque démarrage de session)
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519

Tester la connexion sécurisée

ssh -p 2222 francois@<IP>
# Doit demander la passphrase (locale) puis te connecter sans password serveur
💡
Ed25519 vs RSA

Préférez ed25519 à rsa : plus courte, plus rapide, plus sûre. RSA reste valide mais minimum 4096 bits, alors que ed25519 est inattaquable même en 256 bits.

🛡️ fail2ban — banir les brute-forcers

fail2ban surveille les logs (SSH, nginx auth, etc.) et bannit automatiquement les IPs qui dépassent un seuil de tentatives échouées.

sudo apt install fail2ban -y

# Config locale (ne pas modifier jail.conf qui sera écrasé aux mises à jour)
sudo nano /etc/fail2ban/jail.local

# Coller :
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
# → liste les IPs actuellement bannies

🔥 Pare-feu — ufw

Principe : bloquer TOUT par défaut, n'ouvrir QUE ce qui est nécessaire.

# Politique par défaut : tout bloquer en entrée, autoriser sortie
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Autoriser SSH (port custom si modifié)
sudo ufw allow 2222/tcp comment 'SSH custom'

# Autoriser web
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# (Optionnel) autoriser source IP spécifique pour port admin
# sudo ufw allow from 90.x.y.z to any port 5432 comment 'Postgres bureau Paris'

# Activer
sudo ufw enable
sudo ufw status verbose
⚠️
Ne JAMAIS activer ufw avant d'avoir ajouté la règle SSH

Si vous lancez ufw enable sans avoir d'abord autorisé votre port SSH, vous coupez la connexion en cours. Toujours ufw allow ssh AVANT ufw enable.

🔄 Mises à jour automatiques — unattended-upgrades

Les patches de sécurité critiques doivent être appliqués sans délai. Le paquet unattended-upgrades le fait automatiquement.

sudo apt install unattended-upgrades apt-listchanges -y

# Configurer
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Répondre "Yes" à "Automatically download and install stable updates?"

# Vérifier la config
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

# Activer le reboot auto si nécessaire (à vous de juger)
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

# Tester en dry-run
sudo unattended-upgrade --dry-run --debug
Reboot auto = traffic offline

Si vous activez le reboot auto, votre service est down quelques minutes à 3h du matin. Sur du critique 24/7, prévoyez plutôt un alert sur /var/run/reboot-required et faites le redémarrage manuellement.

📋 Audit logs

Logs essentiels à surveiller

FichierContientCommande utile
/var/log/auth.logSSH, sudo, loginsudo journalctl -u sshd -n 50
/var/log/syslogSystem eventstail -f /var/log/syslog
/var/log/nginx/access.logRequêtes HTTP serviestail -f /var/log/nginx/access.log
/var/log/nginx/error.logErreurs nginxtail -f /var/log/nginx/error.log
/var/log/fail2ban.logIPs banniessudo fail2ban-client status

Détecter une activité suspecte SSH

# Tentatives échouées récentes
sudo grep "Failed password" /var/log/auth.log | tail -20

# Connexions réussies (vérifier qu'il n'y a personne d'inconnu)
sudo grep "Accepted" /var/log/auth.log | tail -20

# Sessions actuellement actives
who
w

Centralisation logs (avancé)

Pour 3+ serveurs, centralisez vers une stack comme Grafana Loki ou ELK. Permet de corréler entre serveurs et conserver au-delà de la rotation locale.

🎯 Hardening kernel (bonus)

Quelques sysctl utiles pour durcir la pile réseau :

sudo nano /etc/sysctl.d/99-hardening.conf

# Protection contre les SYN floods
net.ipv4.tcp_syncookies = 1

# Ignorer ICMP ping broadcast
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Logger les paquets martiens (sources impossibles)
net.ipv4.conf.all.log_martians = 1

# Désactiver source routing (attaque MITM)
net.ipv4.conf.all.accept_source_route = 0

# Désactiver IPv6 si pas utilisé (sinon laisser)
# net.ipv6.conf.all.disable_ipv6 = 1

sudo sysctl --system

🔗 Ressources

📋 Quiz de validation

Accueil Module 2 — Nginx + TLS →