Intro
Le durcissement de la sécurité Linux est le plus efficace lorsqu’il suit un rythme opérationnel clair : observer avant de changer, appliquer la plus petite modification justifiée, vérifier le résultat et prévoir une marche arrière explicite. Ce playbook met l’accent sur des actions concrètes que les développeurs, consultants DevOps et équipes de startups peuvent exécuter en toute sécurité sur des distributions Linux courantes.
Les exemples ci-dessous relient durcissement Linux, contrôle d’accès, secrets et permissions à des commandes concrètes, des signaux attendus et une réversibilité nette. Les outils connexes comme systemd, Bash et Docker sont mentionnés uniquement lorsqu’ils influencent les prérequis, la compatibilité ou la récupération.
Inventaire des versions et de l’environnement
Avant toute modification, capturez une base de référence en lecture seule. Connaître la famille d’OS, le noyau, le système d’initialisation, le cadre de sécurité (SELinux/AppArmor) et la pile réseau détermine quelles commandes et configurations sont valides.
Prérequis
- Accès shell avec un utilisateur non privilégié; élevez les privilèges uniquement lorsque la vérification l’exige.
- Une deuxième console/session prête en secours pendant les changements.
Inventaire en lecture seule (copiez les sorties avec horodatage dans votre journal de changements) :
# OS et noyau
cat /etc/os-release
uname -r
# Système d’init et contexte de session
ps -p 1 -o comm=
systemd-detect-virt --container || true
# Présence d’un cadre de sécurité
command -v getenforce >/dev/null && getenforce || echo 'SELinux not present'
command -v aa-status >/dev/null && sudo aa-status || echo 'AppArmor not present or needs sudo'
# Écoutes réseau et moteur de pare-feu
ss -tulnp
command -v nft >/dev/null && nft list ruleset | head -n 20 || iptables -S | head -n 20
# Présence de SSH et sudo
pgrep -a sshd || systemctl status ssh || true
sudo -V | head -n 1
# Utilisateurs et groupes (aperçu en lecture seule)
getent passwd | awk -F: '$3 >= 1000 {print $1":"$6}' | head
getent group | head
Conseils d’interprétation
- Si systemd n’est pas le PID 1 (p. ex., dans des conteneurs), certaines commandes de service diffèrent; privilégiez les vérifications au niveau des processus.
- L’état SELinux/AppArmor oriente l’ajustement de la politique. Enforcing/permissive/disabled modifient le risque et l’observabilité.
- Notez les ports en écoute et quel moteur de pare-feu est actif (nftables vs iptables). Planifiez en conséquence.
Définissez les attentes avant tout changement
- Signal de succès : la sortie de commande précise ou la ligne de journal qui prouve l’état désiré.
- Signal d’échec : le symptôme exact (p. ex., connexion refusée, erreur de syntaxe, refus AVC) qui déclenche le retour arrière.
Chemin de configuration sûre
Cette section illustre de petits changements traçables avec vérification et restauration explicites.
Exemple 1 : Durcir l’accès SSH
Portée et rayon d’impact
- Affecte la connexion distante. Risque : verrouillage. Conservez une console root/privilégiée active ou un accès hors bande.
Étapes
- Observer la configuration SSH et l’accès actuels :
ss -tulnp | grep -E ':(22|<PORT>)'
sshd -T | sort | grep -E '^(permitrootlogin|passwordauthentication|allowusers)'
last -F | head -n 5
- Sauvegarder et appliquer des restrictions minimales :
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d%H%M%S)
# Éditez avec votre éditeur; directives d’exemple ci-dessous :
# - Interdire la connexion root directe, préférer les clés, limiter la liste d’utilisateurs
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
# Ajouter (ou ajuster) pour restreindre à des comptes explicites
sudo grep -q '^AllowUsers' /etc/ssh/sshd_config || echo 'AllowUsers <USER1> <USER2>' | sudo tee -a /etc/ssh/sshd_config
# Valider la syntaxe avant rechargement
sudo sshd -t
sudo systemctl reload sshd || sudo service ssh reload
Vérification
- Depuis un nouveau terminal, tester que l’accès par clé fonctionne et que l’authentification par mot de passe échoue :
ssh -o PreferredAuthentications=publickey <USER1>@<HOST>
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no <USER1>@<HOST>
- Attendu : l’authentification par clé réussit; la tentative uniquement par mot de passe est refusée. Confirmez dans les journaux :
journalctl -u ssh -n 50 --no-pager | tail
Récupération
- En cas de risque de verrouillage, revenez rapidement depuis la console :
sudo mv /etc/ssh/sshd_config.bak.* /etc/ssh/sshd_config
sudo systemctl restart sshd || sudo service ssh restart
Exemple 2 : Moindre privilège pour les secrets applicatifs
Portée et rayon d’impact
- Confine l’accès en lecture à un seul compte de service. Faible risque pour la disponibilité système.
Supposons un secret à /etc/myapp/secret.json consommé par l’utilisateur de service <SERVICE_USER> dans le groupe myapp.
Étapes
- Observer le propriétaire et les permissions actuels :
namei -mo /etc/myapp/secret.json
stat -c '%U %G %a %n' /etc/myapp/secret.json
getfacl -p /etc/myapp/secret.json 2>/dev/null || true
- Appliquer le moindre privilège :
sudo chown root:myapp /etc/myapp/secret.json
sudo chmod 640 /etc/myapp/secret.json
# Si <SERVICE_USER> n’est pas dans le groupe myapp, accorder une ACL de lecture explicite
sudo setfacl -m u:<SERVICE_USER>:r /etc/myapp/secret.json
Vérification
namei -mo /etc/myapp/secret.json | tail -n 1 # doit afficher root myapp 640
sudo -u <SERVICE_USER> bash -c 'test -r /etc/myapp/secret.json && echo OK'
Récupération
- Rétablir les permissions et l’ACL si le service ne démarre pas :
sudo setfacl -b /etc/myapp/secret.json # effacer les ACL
sudo chmod 644 /etc/myapp/secret.json
Exemple 3 : Base de pare-feu avec ufw
Portée et rayon d’impact
- Bloque le trafic entrant non sollicité. Risque élevé de verrouillage si SSH n’est pas explicitement autorisé. Conservez un accès console.
Prérequis
- ufw installé mais inactif, backend nftables/iptables disponible.
Étapes
- Observer les ports en écoute et l’état d’ufw :
ss -tulnp | grep -v 127.0.0.1
sudo ufw status verbose || true
- Définir une liste d’autorisation et une politique par défaut restrictive :
# Autoriser l’admin SSH depuis un poste fixe
sudo ufw allow from <ADMIN_IP> to any port 22 proto tcp
# Autoriser les ports applicatifs requis (exemples)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Tout le reste entrant en refus; garder la sortie ouverte
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable # confirmer quand demandé
Vérification
sudo ufw status numbered
nmap -Pn -p 22,80,443 <HOST> # depuis une source autorisée et non autorisée, comparer
Récupération
- Si vous perdez l’accès réseau, depuis la console :
sudo ufw disable
# En dernier recours pour nftables/iptables, vider prudemment les règles :
command -v nft >/dev/null && sudo nft flush ruleset || sudo iptables -F
Exemple 4 : Durcissement réseau via sysctl
Portée et rayon d’impact
- Durcit le comportement de la pile réseau. Risque faible à modéré si les valeurs restent conservatrices.
Étapes
- Observer les valeurs actuelles :
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.all.accept_redirects
sysctl net.ipv4.conf.all.send_redirects
sysctl net.ipv6.conf.all.accept_redirects 2>/dev/null || true
- Rendre persistants des réglages raisonnables dans un fichier dédié :
sudo tee /etc/sysctl.d/99-hardening.conf >/dev/null <<'EOF'
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
EOF
sudo systemctl restart systemd-sysctl || sudo sysctl --system
Vérification
sysctl -a | grep -E 'rp_filter|accept_redirects|send_redirects' | sort
Récupération
- Supprimer ou modifier le fichier puis recharger :
sudo rm /etc/sysctl.d/99-hardening.conf
sudo systemctl restart systemd-sysctl || sudo sysctl --system
Vérification et diagnostics
Utilisez des contrôles simples pour confirmer la posture de sécurité et détecter tôt les régressions.
- Contrôle d’accès
- last -F et journalctl -u ssh indiquent qui s’est connecté et quand.
- Testez volontairement les cas négatifs (p. ex., SSH par mot de passe seul) pour confirmer les refus.
- Permissions et secrets
- namei -mo et getfacl révèlent les permissions de chemin effectives et les ACL.
- Utilisez sudo -u <SERVICE_USER> pour simuler l’accès du service sans supposition.
- Pare-feu et exposition
- ss -tulnp et nmap depuis des réseaux distincts valident la surface exposée voulue.
- journalctl -k met en évidence les paquets rejetés au niveau noyau si la journalisation est activée par vos règles.
- Cadres de politique
- SELinux : ausearch -m AVC -ts recent et journalctl -t setroubleshoot (si présent) mettent en évidence les refus.
- AppArmor : dmesg | grep DENIED ou journalctl -k | grep apparmor montrent les profils touchés.
Définissez un « pass » standard pour chaque changement, stockez la commande et sa dernière sortie connue comme correcte, et mettez des alertes sur les écarts lorsque c’est possible.
Modes de panne et récupération
- Verrouillé hors de SSH
- Symptôme : connexion refusée ou clé rejetée après changement.
- Récupération : utilisez la console pour restaurer /etc/ssh/sshd_config depuis la sauvegarde et redémarrer sshd. Conservez au moins une session privilégiée persistante ouverte pendant les changements.
- sudoers cassé
- Symptôme : sudo échoue avec une erreur de syntaxe.
- Prévention : modifiez toujours avec visudo, qui valide avant d’enregistrer.
- Récupération : utilisez une console root pour copier /etc/sudoers.bak vers /etc/sudoers et exécuter visudo -c.
- Le pare-feu coupe la gestion
- Symptôme : impossible d’atteindre SSH ou les ports applicatifs depuis les sources prévues.
- Récupération : en console, exécutez sudo ufw disable ou videz prudemment le jeu de règles. Réappliquez d’abord les règles d’autorisation, puis définissez le refus par défaut.
- sysctl trop strict casse le réseau
- Symptôme : régression de routage ou de connectivité après rechargement.
- Récupération : supprimez le fichier de durcissement, rechargez systemd-sysctl ou sysctl --system, puis retestez. Réintroduisez les réglages progressivement.
- La politique SELinux/AppArmor bloque des services
- Symptôme : un service échoue au démarrage après des changements de politique ou de chemins.
- Récupération : inspectez les refus (ausearch ou journalctl), ajustez les étiquettes/profils, ou passez temporairement SELinux en permissive pour diagnostic uniquement. Rétablissez enforcing après un correctif ciblé.
Liste de contrôle des opérations
Adoptez ce flux reproductible pour chaque changement de durcissement :
- Inventaire
- Capturer la version de l’OS, le noyau, l’état SELinux/AppArmor, les ports en écoute et le backend de pare-feu actif.
- Plan
- Définir la plus petite modification, ses signaux de succès et d’échec, son rayon d’impact et une commande de retour arrière explicite.
- Préparer
- Créer des sauvegardes : cp -a <FILE> <FILE>.bak.$(date +%Y%m%d%H%M%S)
- Ouvrir une deuxième session console. Confirmer l’accès de « break-glass ».
- Changer
- Appliquer la modification. Valider la syntaxe quand c’est supporté (sshd -t, visudo -c, nft -c).
- Vérifier
- Exécuter les commandes de vérification pré-déclarées. Tester à la fois les chemins d’autorisation et de refus.
- Observer
- Consulter les journaux (journalctl, dmesg) pour détecter des échecs silencieux ou des refus.
- Documenter
- Enregistrer commandes, sorties, horodatages et état final pour les audits et la réponse aux incidents.
- Rétablir si nécessaire
- Utiliser immédiatement les commandes de retour préparées dès l’apparition de signaux d’échec.
Conclusion
Un durcissement Linux efficace est concret, cadré et réversible. Commencez par l’inventaire, apportez la plus petite modification crédible, vérifiez avec des commandes et des journaux explicites, et gardez une restauration rapide à portée de main. Les exemples ci-dessus pour SSH, les permissions, le pare-feu et sysctl offrent un modèle à adapter à votre distribution et à votre mode de déploiement. Une discipline opérationnelle réduit le rayon d’impact, protège les secrets et transforme la configuration de l’approximation en une procédure fiable et testable.