📍 Article de référence : Sécuriser les systèmes d’information : guide complet 2026
Ce tutoriel détaille l’application opérationnelle du durcissement Linux. Pour la vue d’ensemble, consultez le guide de référence.
Un serveur Linux installé par défaut depuis une ISO Debian ou Ubuntu offre, après un apt install openssh-server, environ deux cents services, processus, démons et démons potentiels exposés à des attaques connues. Le défaut d’usine d’une distribution ne reflète pas une posture de sécurité opérationnelle — il reflète un compromis entre facilité d’installation, compatibilité et confort utilisateur. Le durcissement (hardening) est l’opération systématique qui transforme cette installation par défaut en un système robuste, dont la surface d’attaque est minimale et la posture mesurable. Ce tutoriel applique pas à pas le référentiel CIS Benchmarks, complété par les recommandations ANSSI, sur une cible Ubuntu 24.04 LTS ou Debian 12 — le pipeline est identique sur les autres distributions modernes.
Prérequis
- Serveur Ubuntu 24.04 LTS ou Debian 12 fraîchement installé, avec accès root ou sudo.
- Connexion SSH initiale opérationnelle (vous devez pouvoir vous reconnecter).
- Niveau attendu : intermédiaire (administration Linux de base).
- Temps estimé : 90 à 120 minutes pour un durcissement complet niveau CIS Level 1.
- Recommandation forte : exécuter d’abord sur une VM de test avant d’appliquer en production.
Étape 1 — Inventaire initial et préparation
Avant toute modification, on capture l’état initial du système pour pouvoir comparer après durcissement et identifier d’éventuelles régressions. Les commandes ci-dessous produisent un inventaire des paquets installés, des services actifs et des ports ouverts. Cet état initial doit être archivé hors de la machine cible — ce qu’on cherchera à comparer après durcissement, c’est ce qui n’aurait pas dû changer.
# Snapshot des paquets installés
dpkg --get-selections | grep -v deinstall > /root/baseline-packages.txt
# Snapshot des services activés
systemctl list-unit-files --type=service --state=enabled > /root/baseline-services.txt
# Snapshot des ports en écoute
ss -tulpn > /root/baseline-ports.txt
# Mise à jour complète du système — ne JAMAIS durcir un système non patché
apt update && apt full-upgrade -y
apt autoremove --purge -y
La commande apt full-upgrade applique également les mises à jour qui changent des dépendances (à la différence de upgrade simple) ; sur un système maintenu correctement, elle ne devrait casser aucun service en production grâce à la stabilité des dépôts Debian/Ubuntu. Un redémarrage est nécessaire si le noyau a été mis à jour : [ -f /var/run/reboot-required ] && reboot.
Étape 2 — Comptes, mots de passe et sudo
Le principe du moindre privilège commence par l’absence d’utilisation directe du compte root : on travaille avec un compte nominatif, élevé via sudo lorsque nécessaire, avec traçabilité de chaque action privilégiée. Si le compte personnel n’existe pas encore :
# Créer un compte administrateur nominatif
adduser admindev
# Définir un mot de passe robuste (interactif) puis ajouter au groupe sudo
usermod -aG sudo admindev
# Vérifier que sudo fonctionne sans mot de passe root
su - admindev
sudo -l # affiche les commandes autorisées
exit
Côté politique des mots de passe, on durcit /etc/login.defs et on installe le module PAM pwquality qui force la complexité :
# Politique d'expiration et de longueur minimale
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs
sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' /etc/login.defs
sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' /etc/login.defs
# Installation du module qualité de mot de passe
apt install -y libpam-pwquality
# Édition de /etc/security/pwquality.conf — paramètres recommandés CIS L1
cat >> /etc/security/pwquality.conf <<'EOF'
minlen = 14
minclass = 4
maxrepeat = 3
maxsequence = 3
dictcheck = 1
enforce_for_root
EOF
Après cette étape, tout changement de mot de passe (y compris root) impose 14 caractères minimum avec au moins une majuscule, une minuscule, un chiffre et un symbole. La directive enforce_for_root est essentielle pour éviter qu’un attaquant qui aurait obtenu un shell root ne définisse un mot de passe trivial.
Étape 3 — SSH : authentification par clés et bannières
SSH est, statistiquement, la première porte qu’un attaquant essaiera. Les bots de scan tentent en continu des mots de passe sur le port 22 partout sur Internet. La règle absolue : désactiver l’authentification par mot de passe, n’autoriser que l’authentification par clé publique, et idéalement utiliser des clés Ed25519 (plus rapides et plus sûres que RSA-2048). Sur le poste de travail de l’administrateur :
# Génération d'une clé Ed25519 robuste avec passphrase
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_admindev -C "admindev@station"
# Copie de la clé publique sur le serveur cible
ssh-copy-id -i ~/.ssh/id_ed25519_admindev.pub admindev@serveur.exemple.io
# Tester la connexion par clé AVANT de désactiver les mots de passe
ssh -i ~/.ssh/id_ed25519_admindev admindev@serveur.exemple.io
Une fois la connexion par clé validée — ne jamais sauter cette vérification, sous peine de se verrouiller hors du serveur — on durcit la configuration serveur. L’édition se fait dans /etc/ssh/sshd_config.d/99-hardening.conf (Ubuntu 22.04+/Debian 12 supportent les fragments conf.d, plus propres qu’éditer le fichier principal) :
# /etc/ssh/sshd_config.d/99-hardening.conf
Protocol 2
Port 22
AddressFamily inet
ListenAddress 0.0.0.0
# Authentification
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
PubkeyAuthentication yes
MaxAuthTries 3
MaxSessions 4
LoginGraceTime 30
# Contrôle d'accès
AllowUsers admindev
AllowGroups sudo
# Algorithmes (recommandations Mozilla / ANSSI)
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
# Hygiène générale
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
LogLevel VERBOSE
Banner /etc/issue.net
Une bannière légale dissuasive est placée dans /etc/issue.net :
cat > /etc/issue.net <<'EOF'
*****************************************************************
* ACCÈS RÉSERVÉ AU PERSONNEL AUTORISÉ *
* Toute connexion non autorisée est strictement interdite *
* et fera l'objet de poursuites conformément à la loi. *
* Les sessions sont enregistrées et auditées. *
*****************************************************************
EOF
On valide la syntaxe puis on recharge le démon sans interrompre la session courante :
# Validation de la configuration (toujours faire ÇA avant reload)
sshd -t
# Recharger sshd (ne ferme pas les sessions actives)
systemctl reload ssh
Tester immédiatement, depuis une seconde connexion, qu’on peut toujours se connecter — sans fermer la session originale qui sert de filet de sécurité. Si la nouvelle session échoue, on diagnostique avec journalctl -u ssh -n 50, on corrige, et on retente.
Étape 4 — Pare-feu nftables : règle par défaut DENY
Depuis Debian 10 et Ubuntu 20.04, nftables est le sous-système de pare-feu par défaut (les commandes iptables historiques sont en fait redirigées vers nftables via iptables-nft). Une configuration durcie applique la règle d’or : tout est interdit par défaut, on autorise explicitement ce qui est nécessaire. La configuration vit dans /etc/nftables.conf.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
# Trafic local et connexions établies
iif lo accept
ct state established,related accept
ct state invalid drop
# ICMPv4 et ICMPv6 limités
ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 5/second accept
ip6 nexthdr ipv6-icmp icmpv6 type { echo-request, destination-unreachable, time-exceeded, packet-too-big, parameter-problem, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
# SSH limité contre brute force (10 tentatives par minute par IP source)
tcp dport 22 ct state new limit rate 10/minute accept
tcp dport 22 ct state new log prefix "SSH-BLOCKED: " drop
# Logger puis dropper le reste
log prefix "INPUT-DROP: " flags all counter drop
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Cette configuration rejette par défaut tout trafic entrant (policy drop), accepte la boucle locale et les connexions déjà établies, autorise un trafic ICMP minimal limité contre les abus, et n’expose que SSH avec un seau à jetons qui ralentit les attaques par force brute. La règle log prefix trace les paquets bloqués dans journalctl -k pour analyse. Pour des services web on ajouterait par exemple : tcp dport { 80, 443 } accept. On charge et active :
# Valider la syntaxe puis charger
nft -c -f /etc/nftables.conf
systemctl enable --now nftables
systemctl status nftables
# Vérifier les règles actives
nft list ruleset
Tester immédiatement la connexion SSH depuis une seconde session. Si quelque chose cloue, systemctl stop nftables rétablit l’accès, on diagnostique calmement, on corrige le fichier, et on recharge.
Étape 5 — AppArmor : confinement des processus exposés
AppArmor est le système de Mandatory Access Control (MAC) par défaut sur Debian et Ubuntu. Il complète la sécurité DAC traditionnelle (permissions chmod/chown) en confinant chaque processus profilé à un ensemble explicite de fichiers, capacités et ressources réseau. Même si un service est compromis (RCE sur nginx, par exemple), l’attaquant reste confiné par le profil et ne peut pas écrire arbitrairement dans /etc ou /home.
# Vérifier qu'AppArmor est actif
systemctl status apparmor
aa-status
# Sortie attendue : un module chargé, des profils en mode enforce/complain
# Installer les profils étendus si nécessaire
apt install -y apparmor-utils apparmor-profiles apparmor-profiles-extra
# Lister les profils disponibles
ls /etc/apparmor.d/
# Pour chaque service exposé, déployer puis activer le profil
# Le profil sshd ships dans /usr/share/apparmor/extra-profiles/ — le copier d'abord
cp /usr/share/apparmor/extra-profiles/usr.sbin.sshd /etc/apparmor.d/
systemctl reload apparmor
aa-enforce /etc/apparmor.d/usr.sbin.sshd
aa-enforce /etc/apparmor.d/usr.sbin.nginx # si nginx est installé (profil shipé avec nginx)
Un profil mal écrit peut empêcher un service de démarrer (déni de service auto-infligé). Pour développer ou ajuster un profil sans casse, on utilise d’abord le mode complain (aa-complain) qui journalise les violations sans bloquer, on analyse les logs avec aa-logprof, et on bascule en enforce quand le profil est stable.
Étape 6 — auditd : journalisation des événements sensibles
auditd est le démon d’audit du noyau Linux. Il journalise les appels système, accès fichiers et modifications de configuration selon des règles paramétrables. C’est la base d’une investigation forensique post-incident.
# Installation
apt install -y auditd audispd-plugins
# Activation immutable des règles à chaque démarrage
systemctl enable --now auditd
Le fichier /etc/audit/rules.d/99-hardening.rules reçoit un jeu de règles couvrant les changements de configuration sensibles. Ce jeu est inspiré du modèle « Neo23x0 / auditd-attack » qui aligne les règles auditd sur les techniques MITRE ATT&CK :
# /etc/audit/rules.d/99-hardening.rules — extrait essentiel
# Modifications du système d'identité
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k identity
-w /etc/sudoers.d/ -p wa -k identity
# Configuration SSH
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/sshd_config.d/ -p wa -k sshd_config
# Chargement de modules kernel
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
# Exécution de binaires privilégiés
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k privileged
# Mode immuable : empêche toute modification des règles sans reboot
-e 2
# Charger les nouvelles règles sans redémarrer
augenrules --load
# Vérifier les règles actives
auditctl -l
# Inspecter les événements
ausearch -k identity
ausearch -k sshd_config --start today
Les journaux auditd s’accumulent vite. La configuration de rotation se fait dans /etc/audit/auditd.conf avec max_log_file = 50 (Mo), num_logs = 10 et space_left_action = email pour alerter avant saturation disque.
Étape 7 — Vérification avec Lynis et chiffrement disque
Lynis est l’outil d’audit de durcissement de référence sur Linux/BSD, maintenu par CISOfy en open-source. Il évalue plus de 300 contrôles et fournit un score de durcissement (Hardening Index) entre 0 et 100, avec des recommandations détaillées.
# Installation depuis les dépôts officiels Debian/Ubuntu
apt install -y lynis
# Exécution d'un audit complet
lynis audit system --quick
# Le rapport détaillé est dans /var/log/lynis.log
# Les actions recommandées sont en fin de sortie ou dans /var/log/lynis-report.dat
Un système Debian/Ubuntu fraîchement installé obtient typiquement un score de 60-65. Après application des étapes 1 à 6, on vise un score supérieur à 80. Au-delà, les gains marginaux deviennent coûteux à obtenir (durcissement noyau via sysctl, modules de sécurité, etc.) et doivent être arbitrés contre le risque opérationnel.
Côté chiffrement disque, LUKS2 est la norme pour chiffrer les partitions (idéalement défini lors de l’installation). Pour un serveur déjà en production, le chiffrement à chaud est complexe ; la stratégie recommandée est : prochaine réinstallation avec LUKS, et pour les volumes de données déjà existants cryptsetup luksFormat sur une copie hors-ligne. Sur un poste de travail, BitLocker ou LUKS doit être obligatoire dès l’installation.
Erreurs fréquentes à éviter
| Erreur | Conséquence | Bonne pratique |
|---|---|---|
Désactiver PasswordAuthentication sans avoir testé la clé |
Verrouillé hors du serveur | Tester la connexion par clé depuis une seconde session avant d’éditer sshd_config |
| Charger nftables sans règle SSH | Coupé immédiatement de toutes les connexions actives | Toujours valider avec nft -c -f avant systemctl reload, et garder un canal d’accès console |
Passer tous les profils AppArmor en enforce sans test |
Services qui refusent de démarrer | Mode complain d’abord, analyse aa-logprof, puis enforce |
| Oublier la rotation des logs auditd | Saturation du disque, déni de service auto-infligé | Configurer max_log_file, num_logs, space_left_action |
| Durcir avant de patcher | Faille publique persiste sous la couche de durcissement | Toujours apt full-upgrade en première étape |
| Pas de second utilisateur sudo | Verrouillé si admindev est compromis ou supprimé par erreur |
Créer au moins deux comptes administrateurs nominatifs, conserver un mot de passe root scellé en coffre-fort physique |
Tutoriels complémentaires
- Durcissement Windows : GPO, BitLocker, Defender et AppLocker — l’équivalent côté Windows Server et Active Directory.
- Authentification forte et IAM : MFA, SSO, OAuth 2.0/OIDC et Keycloak — gestion centralisée des identités au-delà du compte local.
- Mettre en œuvre Zero Trust : NIST SP 800-207, identités et microsegmentation — pour aller au-delà de la sécurité périmétrique.
- 🔝 Retour au guide complet : Sécuriser les systèmes d’information : guide complet 2026.
Questions fréquentes (FAQ)
Q : CIS Level 1 ou Level 2 — lequel viser ?
R : Le Level 1 rassemble des contrôles à faible risque d’impact opérationnel, applicables sans préparation lourde sur la plupart des serveurs. Le Level 2 ajoute des contrôles plus restrictifs (interdiction d’IPv6, désactivation de protocoles, désinstallation d’outils de développement) qui peuvent casser des applications. La règle pragmatique : appliquer L1 partout, viser L2 sur les serveurs sensibles après tests d’impact en pré-production.
Q : Comment automatiser le durcissement sur un parc de serveurs ?
R : Trois familles d’outils. Premièrement, les rôles Ansible CIS publiés sur GitHub (par exemple ansible-lockdown/UBUNTU22-CIS ou MVladislav/ansible-cis-ubuntu-2204) appliquent l’ensemble des contrôles de manière idempotente. Deuxièmement, OpenSCAP évalue la conformité avec des profils SCAP Security Guide (SSG) puis applique les remédiations. Troisièmement, Canonical Security Center propose des outils de durcissement automatique pour Ubuntu Pro.
Q : Faut-il désactiver IPv6 ?
R : Non par principe — c’est une recommandation héritée d’époques où la pile IPv6 Linux avait des bugs de sécurité. Sur les noyaux modernes, IPv6 est aussi sûr qu’IPv4. La règle correcte : configurer correctement IPv6 si on l’utilise, désactiver complètement si on ne l’utilise pas. Désactiver à moitié (interface up sans configuration) crée des vulnérabilités d’autoconfiguration (SLAAC, rogue RA).
Q : SELinux ou AppArmor ?
R : Les deux sont des systèmes de Mandatory Access Control valides. SELinux (RHEL, CentOS, Fedora, Rocky, Alma) est plus granulaire et plus complexe à maîtriser. AppArmor (Debian, Ubuntu, SUSE) est basé sur les chemins de fichiers, plus simple à lire et à modifier. Ni l’un ni l’autre n’est intrinsèquement plus sûr ; on utilise celui de la distribution.
Q : Le durcissement remplace-t-il un EDR ?
R : Non. Le durcissement réduit la surface d’attaque ; l’EDR fournit la détection comportementale et la capacité de réponse. Les deux sont complémentaires : un système durci sans EDR n’a pas de visibilité ; un EDR sur un système non durci doit traiter cent fois plus d’événements suspects. La combinaison est ce qui définit une posture défendable.
Références et ressources officielles
- CIS Benchmarks Ubuntu Linux — cisecurity.org/benchmark/ubuntu_linux
- CIS Benchmarks Debian Linux — cisecurity.org/benchmark/debian_linux
- ANSSI — Recommandations relatives à l’administration sécurisée des SI — cyber.gouv.fr/publications
- OpenSSH documentation — openssh.com/manual.html
- nftables Wiki — wiki.nftables.org
- AppArmor Documentation — gitlab.com/apparmor/apparmor/wikis
- Linux Audit (auditd) — github.com/linux-audit/audit-userspace
- Lynis — CISOfy — cisofy.com/lynis
- Mozilla SSH Guidelines — infosec.mozilla.org/guidelines/openssh