Auditer le hardening systemd avec systemd-analyze security
La plupart des services que je fais tourner sur ce VPS passent par systemd, et je me suis rendu compte que je ne profitais jamais de systemd-analyze security. Depuis systemd 245+, cette commande audite chaque unit et lui colle un score d'exposition (0 = quasi confiné, 10 = plein accès root). Elle vérifie une soixantaine de critères : NoNewPrivileges, ProtectSystem, PrivateTmp, restrictions de namespaces, capabilities, syscalls filtrés via seccomp, etc.
systemd-analyze security docker.service
systemd-analyze security --no-pager sshd.service
Le retour donne une ligne par contrôle avec EXPOSURE et un score final. Sans surprise, sshd.service et docker.service ressortent avec un score élevé (proche de 9) parce qu'ils ont besoin d'un accès quasi total au système — c'est normal pour ce type de service. L'intérêt, c'est plutôt pour les petits daemons custom : un service Python qui expose une API interne n'a aucune raison d'avoir CAP_SYS_ADMIN ou un accès au réseau host complet.
[Service]
ExecStart=/usr/bin/python3 /opt/myapp/app.py
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
CapabilityBoundingSet=
Après ajout de ces directives, le score de mon service custom est passé de 8.5 à environ 2.9. Le vrai piège : ProtectSystem=strict casse silencieusement l'écriture de logs ou de fichiers d'état si on ne prévoit pas un ReadWritePaths= explicite vers le bon répertoire. Donc après chaque changement, un coup de journalctl -u monservice -f pendant le redémarrage pour vérifier que rien ne crash avant de considérer le hardening comme acquis.