5 Punkte von GN⁺ 2025-08-20 | 1 Kommentare | Auf WhatsApp teilen
  • systemd bietet leistungsstarke Funktionen zur Dienstverwaltung, doch die Standardeinstellungen sind eher auf Benutzerfreundlichkeit als auf Sicherheit optimiert, weshalb zusätzliche Härtungsoptionen angewendet werden sollten
  • Mit dem Befehl systemd-analyze security lassen sich die Sicherheits-Expositionswerte aller oder einzelner Dienste analysieren und priorisieren
  • Es gibt verschiedene Sicherheitsoptionen, die auf Dienstebene angewendet werden können; sie lassen sich individuell über /etc/systemd/system/ServiceName.service.d/override.conf usw. anpassen
  • Zu den wichtigsten Optionen gehören ProtectSystem, PrivateTmp, NoNewPrivileges, SystemCallFilter, MemoryDenyWriteExecute und weitere Einstellungen, die Prozessrechte und den Zugriff auf Ressourcen einschränken
  • Statt perfekte Sicherheit anzustreben, lässt sich das Risiko wirksam senken, indem man nach außen exponierte Dienste zuerst härtet; auch in Self-Hosting-Umgebungen ist der Effekt groß

Überblick über systemd

  • systemd bietet bei der Dienstverwaltung einen sehr ausgereiften und robusten Ansatz
  • Allerdings sind die Standardeinstellungen locker gehalten, weil sofortige Nutzbarkeit höher gewichtet wird als Sicherheit
  • Dieses Dokument stellt verschiedene Härtungsoptionen vor, die auf systemd-Service-Units und podman quadlets angewendet werden können, um die Wahrscheinlichkeit einer Kompromittierung zu senken und im Fall eines Vorfalls den Schaden zu begrenzen
  • Es ist kein Leitfaden zur pauschalen Anwendung auf alle Dienste; je nach Eigenschaften und Anforderungen eines Dienstes sind individuelle Tests, Log-Prüfungen und Anpassungen erforderlich
  • Die Verantwortung für die Sicherheit der Infrastruktur liegt vollständig beim Betreiber; dieses Dokument ist ein Hilfsmittel zur Orientierung

Sicherheitsanalyse von systemd

  • Mit dem Befehl systemd-analyze security lässt sich der Sicherheitsstatus aller Dienste prüfen oder die Detailkonfiguration eines bestimmten Dienstes (z. B. sshd.service) analysieren
    • Die Ausgabe enthält Prüfergebnis, Funktionsname, Beschreibung und den Exposure-Wert; je höher der Exposure-Wert, desto größer das Risiko
  • Sicherheitsoptionen können im Abschnitt [Service] (systemd) oder [Container] (podman quadlet) zusätzlich gesetzt werden
  • Empfohlen wird die Erstellung einer Override-Datei über systemctl edit ServiceName.service; bei Fehlern sollten die benötigten Berechtigungen geprüft und angepasst werden

Sicherheitsoptionen für Dienste

  • systemd bietet verschiedene Schlüsselwörter für Sicherheitsoptionen, die sich über man systemd.exec 5, man capabilities 7 usw. nachschlagen lassen
  • Typische sicherheitsrelevante Optionen
    • ProtectSystem → beschränkt das Dateisystem auf schreibgeschützten Zugriff
    • ProtectHome → blockiert den Zugriff auf /home, /root, /run/user
    • PrivateDevices → blockiert den Zugriff auf physische Geräte und erlaubt nur virtuelle Geräte wie /dev/null
    • ProtectKernelTunables, ProtectKernelModules, ProtectKernelLogs → blockieren den Zugriff auf Kernel-Ressourcen
    • NoNewPrivileges → verhindert den Erwerb neuer Rechte über setuid/setgid usw.
    • MemoryDenyWriteExecute → verhindert die gleichzeitige Nutzung von beschreibbarem und ausführbarem Speicher; kann bei einigen JIT-Sprachen Probleme verursachen
    • SystemCallFilter → beschränkt zulässige System-Calls; bei Verstößen kann der Prozess beendet oder EPERM zurückgegeben werden

Erläuterung der einzelnen Optionen

  • ProtectSystem: Mit der Einstellung strict wird das gesamte Dateisystem schreibgeschützt eingehängt; für /dev, /proc, /sys sind separate Schutzoptionen nötig
  • ReadWritePaths: Erlaubt das Schreiben wieder nur auf bestimmten Pfaden
  • ProtectHome: Blockiert den Zugriff auf /home, /root, /run/user
  • PrivateDevices: Deaktiviert den Zugriff auf physische Geräte und erlaubt nur Pseudo-Geräte wie /dev/null
  • ProtectKernelTunables: Behandelt /proc und /sys als schreibgeschützt
  • ProtectControlGroups: Erlaubt nur schreibgeschützten Zugriff auf cgroups
  • ProtectKernelModules: Verbietet das explizite Laden von Kernel-Modulen
  • ProtectKernelLogs: Beschränkt den Zugriff auf den Kernel-Log-Puffer
  • ProtectProc: Mit der Einstellung invisible werden Prozesse anderer Benutzer in /proc/ verborgen
  • ProcSubset: Blendet in /proc Inhalte aus, die nicht zu bestimmten PID-bezogenen Einträgen gehören
  • NoNewPrivileges: Verhindert neue Privilegieneskalation über setuid, setgid und Dateisystem-Capabilities
  • ProtectClock: Blockiert Schreibzugriffe auf System- und Hardware-Uhr
  • SystemCallArchitectures: Mit native sind nur native Syscalls wie x86-64 erlaubt
  • RestrictNamespaces: Beschränkt containerbezogene Namespaces
  • RestrictSUIDSGID: Verhindert das Setzen der Dateibits setuid und setgid
  • LockPersonality: Verhindert Änderungen der Ausführungsdomäne (nur für ältere Anwendungen relevant)
  • RestrictRealtime: Beschränkt Echtzeit-Scheduling (nur für bestimmte Spezialdienste nötig)
  • RestrictAddressFamilies: Beschränkt erlaubte Socket-Adressfamilien (z. B. AF_INET, AF_INET6, AF_UNIX usw.)
  • MemoryDenyWriteExecute: Verhindert das zusätzliche Anlegen von Speicherbereichen mit Schreib- und Ausführungsrechten zugleich (Vorsicht bei Diensten mit JIT)
  • ProtectHostname: Verbietet die Verwendung der Syscalls sethostname und setdomainname
  • SystemCallFilter: Erlaubt dienstspezifische Regeln zum Zulassen oder Sperren von Syscalls und eine feingranulare Filterung
    • Gruppen, einzelne Syscalls sowie Allow-/Deny-Strategien lassen sich anpassen
    • Bei Verstößen kann statt eines Prozessabbruchs auch die Rückgabe eines Fehlercodes wie EPERM konfiguriert werden
    • Die vollständige Liste ist über systemd-analyze syscall-filter oder man systemd.exec(5) einsehbar
    • Mit dem Präfix ~ lässt sich eine gesamte Liste negieren (z. B. CapabilityBoundingSet=~CAP_SETUID usw.)

Vorgehen zum Anpassen von SystemCallFilter-Beschränkungen

  • Mit auditd lässt sich beim Fehlschlagen eines Dienstes im Log prüfen, welcher Syscall blockiert wurde
    • sudo ausearch -i -m SECCOMP -ts recent ausführen und anschließend den Syscall-Wert prüfen
    • Den betreffenden Syscall oder die zugehörige Gruppe zu SystemCallFilter hinzufügen, um das Problem schrittweise zu beheben

Priorisierung der Härtung und Betriebstipps

  • Es ist nicht nötig, alles auf jeden Dienst anzuwenden
  • Entscheidend sind Bedrohungsmodell und Risikomanagement; insbesondere nach außen exponierte Dienste (httpd, nginx, ssh usw.) sollten zwingend berücksichtigt werden
  • Auch bei benutzerdefinierten Kommandos und Timer-Units (als Ersatz für cron) ist eine frühzeitige Anwendung wirksam
  • Je weniger komplex ein Dienst ist, desto eher ist eine feine Abstimmung möglich

Checkliste: empfohlene Kombination von Sicherheitsoptionen (Priorität für die erste Anwendung)

  • ProtectSystem=strict
  • PrivateTmp=yes
  • ProtectHome=yes oder ProtectHome=tmpfs
  • ProtectClock=yes, ProtectKernelLogs=yes, ProtectKernelModules=yes
  • RestrictSUIDGUID=yes
  • UMask=0077
  • LockPersonality=yes
  • RestrictRealtime=yes
  • MemoryDenyWriteExecute=yes
  • DynamicUser=yes oder User auf einen bestimmten Nicht-Root-Benutzer setzen
  • Diese Punkte sind in der Regel eine Kombination, die sich für Dienste fast ohne Beeinträchtigung verwenden lässt
  • Wenn zusätzlich Syscall-Filterung (SystemCallFilter) eingesetzt werden soll, sind detaillierte Tests erforderlich

Beispielkonfiguration für Traefik

  • Ein Beispiel für einen containerbasierten Traefik-Dienst, der als systemd quadlet läuft und viele Sicherheitsoptionen anwendet
    • Verwendet werden u. a. ProtectSystem=full, ProtectHome=yes, SystemCallFilter=@system-service @mount @privileged
    • Mit CapabilityBoundingSet=~CAP_SETUID CAP_SETPCAP werden bestimmte Rechte entfernt
    • Mit RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK usw. wird der Netzwerkzugriff eingeschränkt

Fazit

  • Die Härtungsoptionen von systemd sind für Administratoren von Unix-artigen Systemen ein praktisches Werkzeug, das in keinen Werkzeugkasten fehlen muss
  • Sie sind kein perfektes Sicherheitsmittel, sondern ein Werkzeug zur Risikoreduzierung; es ist nicht nötig, wahllos auf alle Dienste Sicherheitseinstellungen anzuwenden
  • Besonders für Administratoren in Self-Hosting-Umgebungen kann der Einsatz die Sicherheitslage deutlich verbessern
  • Mit dem Grundsatz „Praktikabilität vor Perfektion“ wird empfohlen, die Optionen zumindest teilweise und passend zu Arbeitsabläufen und Umgebung einzusetzen

1 Kommentare

 
GN⁺ 2025-08-20
Hacker-News-Kommentare
  • Ich finde es interessant, dass sich automatisiertes Hardening von systemd-Services per strace-Profiling umsetzen lässt.
    https://github.com/desbma/shh

    • Ich habe eine gute Methode gefunden: Im Beispiel wurde zwar ProtectSystem= nicht verwendet, aber mit
      TemporaryFileSystem=/:ro, BindReadOnly=/usr/bin/binary /lib /lib64 /usr/lib usr/lib64
      kann man nur die gewünschten Binärdateien und die Pfade einschließen, die lesbar sein sollen.
      ProtectSystem= ist derzeit mit diesem Verhalten nicht kompatibel.
      Mehr dazu hier.

    • Ich denke, dieser Ansatz kann problematisch für Services sein, die bei Fehlern zusätzliche Aktionen ausführen müssen, etwa E-Mails versenden.

  • Im Vergleich zu dem gestrigen Beitrag über systemd-Hardening ist dieser hier deutlich praxisnäher und enthält viele gute Tipps, die sich sofort anwenden lassen.
    Ich hatte gestern in den Kommentaren versucht, praktischere Beispiele zu geben, und der heutige Beitrag fasst das alles sehr gut zusammen und zeigt, wie man Isolation und Sicherheit mit systemd schnell und einfach verbessern kann.
    Ich halte das für einen hervorragenden Artikel.
    Zur Referenz hier auch noch der gestrige Beitrag.
    https://us.jlcarveth.dev/post/hardening-systemd.md
    https://news.ycombinator.com/item?id=44928504

    • Es wäre gut, wenn das Zertifikatsproblem der Website behoben würde.
      In manchen Browsern ist die Seite wegen Zertifikatsfehlern gar nicht erreichbar.
  • Danke fürs Teilen.
    Mit systemd-analyze zusammen mit dem Flag --user kann man die Sicherheit von systemd-Benutzereinheiten prüfen (systemd-analyze --user security).
    Seit ich Container auf Podman umstelle, nutze ich systemd häufiger, und dieses Tool wird sehr hilfreich sein, um die Sicherheit von systemd-Units bzw. Container-Services zu verbessern.

  • Früher waren Init-Skripte alle unterschiedlich, daher war so ein konsistentes Hardening nicht möglich.

    • Natürlich konnte man so etwas auch mit klassischen Init-Skripten machen, aber systemd hilft dabei, gute Kernel-Funktionen auf standardisierte und konsistente Weise einfach zu nutzen.
      Ich bin relativ spät zu Linux gekommen und kann mir Systeme ohne systemd kaum vorstellen; Systeme ohne systemd waren für mich viel zu umständlich.
      Kürzlich habe ich das Tool unshare entdeckt, mit dem ich etwa das gesamte /nix wieder als RW mounten und solche Experimente durchführen konnte, ohne andere Prozesse zu beeinflussen.
      systemd ist in der Bedienung zwar etwas kantig, aber ehrlich gesagt ist die einzige Alternative für mich Windows.
  • Ich frage mich, warum Linux-Distributionen nicht standardmäßig mehr solcher Sicherheitsschalter aktivieren.
    Ich frage mich, ob konservatives Hardening irgendwelche Nachteile hat.
    Für viele Nutzer könnten die Einstellungen einfach zu zahlreich und zu komplex sein.

    • Wenn man die Einstellungen zu aggressiv ändert, kann man unbeabsichtigt bestehende Konfigurationen kaputtmachen.
      Wenn man zum Beispiel NetworkManager härten würde, müsste man einzeln prüfen, ob IPv4 und IPv6 beide funktionieren, ob die Modi dns=systemd-resolved und dns=default korrekt arbeiten, wie es mit ModemManager und Mobilfunk-Integration aussieht, mit OpenVPN- oder Cisco-AnyConnect-Plugins, NetworkManager-dispatcher-Hooks und vielen weiteren Dingen.
      Außerdem ist die Frage, wie viele Paketbetreuer einer Distribution wirklich sicher sagen können, bis zu welchem Grad sie die Schalter eines von ihnen betreuten Pakets ändern können, ohne mehr als 0,01 % der Nutzerumgebungen zu beschädigen.
      Wenn die Distribution solche Flags pflegt, kommen bei jedem Upstream-Release automatisch Kompatibilitätsprobleme dazu; wenn dagegen Upstream die Einstellungen setzt, kann man sie wegen der Abwärtskompatibilität nur noch vorsichtiger einsetzen.

    • Diese Frage ist ähnlich wie: „Warum setzen Distributionen nicht standardmäßig ein strengeres MAC wie SELinux ein?“
      Auch sshd könnte man stärker einschränken, aber

      1. die anfänglichen Entwicklungskosten für die Einführung,
      2. die Kosten für die Bearbeitung von Bug-Reports aus allen möglichen Nutzerumgebungen,
      3. die laufenden Wartungskosten bei Änderungen in Distribution oder Upstream
        machen das für große Distributionen zu einer erheblichen Belastung.
        Bei SELinux und AppArmor ist es ähnlich: Viele Maintainer halten das Kosten-Nutzen-Verhältnis für eher gering.
    • Ein weiterer wichtiger Grund ist, dass oft die Fähigkeit oder die Ressourcen fehlen, das korrekte Verhalten zentraler Systemdienste für jeden einzelnen Parameter per Integrationstests zu prüfen.
      Relevante Diskussion:
      https://news.ycombinator.com/item?id=29995566
      Die Ergebnisse von systemd-analyze security unterscheiden sich je nach Distribution.
      desbma/shh erzeugt aus mit strace gesammelten Daten automatisch regelbasierte Vorgaben wie SyscallFilter, ähnlich wie audit2allow bei SELinux.
      Allerdings ist es diskussionswürdig, strace in Produktionsumgebungen zu installieren.
      https://github.com/desbma/shh

    • Ich weiß es auch nicht genau, aber manche dieser Einstellungen sind erst neuer hinzugekommen, sodass viele Nutzer sie vielleicht noch gar nicht kennen.
      Es gibt nicht nur systemd-Experten, und wenn man solche Optionen aktiviert, besteht auch das Risiko, dass ältere systemd-Versionen nicht mehr korrekt funktionieren.
      Es gibt zwar viele Funktionen wie SELinux und AppArmor, aber viele Distributionen, Entwickler und Nutzer empfinden sie nicht unbedingt als notwendig, weshalb eine automatische Aktivierung schwierig ist.

  • Es gibt so viele Optionen fürs Hardening, dass ich denke, ein Repository mit allgemeinen Hardening-Beispielen für verschiedene Services wäre hilfreich.
    Nutzer greifen oft auf gemeinsam verwendete Hardening-Skripte zurück, stellen dann aber überraschend fest, dass man Berechtigungen teils weiter fassen muss, damit es in Ausnahmesituationen nicht zu Problemen kommt.

    • Wenn man für Distributionen mit schwacher Upstream-Unterstützung wie nixpkgs paketiert,
      ist es am nützlichsten, sich anzusehen, wie Mainstream-Distributionen paketieren und härten.
      Solche Hardening-Methoden sind oft schon ausreichend getestet; wenn man also Beispiele für Härtung etwa bei PostgreSQL sucht, startet man am besten mit den Paketen von Debian, Ubuntu oder RHEL.
  • Eine der großartigen Sicherheitsfunktionen von systemd ist das Credential-Management.
    Damit lassen sich Zugangsdaten sicherer an Anwendungen übergeben, als wenn man sie in Umgebungsvariablen oder im Dateisystem speichert.
    In Umgebungen ohne Vault und Ähnliches, zum Beispiel bei privaten Projekten, bevorzuge ich diese Methode immer.
    Ich habe sogar selbst ein Go-Paket gebaut, das diese Funktion integriert.
    Credentials in systemd
    credential-go-Paket

    • Das wirkt wie bei nodejs oder npm, wo selbst zweizeiliger Code in ein Paket gepackt wird.
      Tatsächlich ist es einfach

      dir, err := os.Getenv("CREDENTIALS_DIRECTORY")
      cred, err := os.ReadFile(filepath.Join(dir, "name"))
      

      und nicht einmal komplizierter als left-pad.
      Soweit ich weiß, galt es in der Go-Community eigentlich immer als Tugend, Abhängigkeiten zu reduzieren und unnötige Abstraktionen wie zusätzliche Funktionsaufrufe zu vermeiden.
      Solche einfachen Dinge hat man früher meist direkt selbst geschrieben.

    • Ich frage mich, wie diese Methode der Credential-Übergabe verhindert, dass geforkte Kindprozesse die Zugangsdaten mit erben.

  • Wirklich ein sehr nützlicher Artikel.
    Mir gefallen sowohl die Liste der einzelnen systemd-Optionen als auch Hinweise wie „Siehe man und viel Glück“.
    systemd ist wirklich großartig, und ich würde es gern breit auf meinen Servern einsetzen.

  • Ein kleiner Hinweis: Die korrekte Schreibweise im Titel ist systemd.
    Nicht SystemD, system D oder system d, sondern systemd.
    Der Grund ist, dass es für „system daemon“ steht und man gemäß der Unix-/Linux-Tradition einen Namen mit kleinem d am Ende gewählt hat.

    • Interessant.
      Ich habe meistens systemD gesehen und frage mich, warum sich das so weit verbreitet hat.
  • Der Tipp zum Debuggen von Syscall-Problemen in systemd ist wirklich nützlich.