OTOthoTools

systemd-Generator

Sichere Dienste erstellen
Ergebnis.service
[Unit]
Description=Otho worker
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=otho
WorkingDirectory=/opt/otho
ExecStart=/opt/otho/bin/worker
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target

Einführung

Der systemd-Generator erzeugt eine Service-Unit (eine .service-Datei) mit Härtungsoptionen, die leicht vergessen werden: ein Nicht-Root-Benutzer, NoNewPrivileges, PrivateTmp, ProtectSystem=strict und ProtectHome.

systemd lässt sich beschreiben, was ein Dienst berühren darf. Die erzeugte Unit ist ein vertretbarer Ausgangspunkt für einen Hintergrund-Worker, einen Agenten oder jeden langlaufenden Prozess.

Ziel

  • Eine syntaktisch korrekte .service-Unit aus Name, Befehl, Benutzer und Arbeitsverzeichnis erzeugen.
  • Basis-Härtung anwenden: dedizierter Benutzer, Neustart bei Fehler, keine neuen Privilegien, privates /tmp und schreibgeschützte Systempfade.
  • Die Unit lesbar halten, damit ein Administrator sie vor dem Einsatz anpassen kann.

Eingaben

  • Beschreibung (Freitext).
  • ExecStart — der absolute Pfad zum ausführbaren Programm.
  • Service-Benutzer — das unprivilegierte Konto, unter dem der Dienst läuft.
  • Arbeitsverzeichnis (optional).

So funktioniert es

Das Werkzeug setzt drei Abschnitte zusammen. [Unit] deklariert die Beschreibung und ordnet den Dienst nach network-online.target ein. [Service] setzt Type=simple, Benutzer und Arbeitsverzeichnis, ExecStart sowie Restart=on-failure mit 5 Sekunden Verzögerung.

Es folgen Härtungsdirektiven: NoNewPrivileges=true blockiert das Erlangen neuer Privilegien über Setuid-Binaries; PrivateTmp=true gibt dem Dienst ein eigenes /tmp; ProtectSystem=strict macht das gesamte Dateisystem schreibgeschützt, ausser explizit erlaubten Pfaden; ProtectHome=true verbirgt /home, /root und /run/user.

[Install] deklariert WantedBy=multi-user.target, damit die Unit mit systemctl enable aktiviert werden kann.

Testbares Beispiel

Ausprobieren — die Analyse läuft lokal in Ihrem Browser.

Beispiel

Beschreibung: Otho worker
ExecStart:  /opt/otho/bin/worker
Benutzer:   otho
Verzeichnis: /opt/otho

Erwartete Ausgabe

[Unit]
Description=Otho worker
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=otho
WorkingDirectory=/opt/otho
ExecStart=/opt/otho/bin/worker
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target

Ausgabe verstehen

  • Die Ausgabe als /etc/systemd/system/<name>.service speichern, dann sudo systemctl daemon-reload und sudo systemctl start <name> ausführen.
  • Muss der Dienst in Systempfade schreiben, blockiert ProtectSystem=strict das — ReadWritePaths ergänzen oder beschreibbare Daten unter das Arbeitsverzeichnis legen.
  • Die Unit ist eine Vorlage: TimeoutStartSec, Ressourcengrenzen (MemoryMax, CPUQuota) und Capabilities (CapabilityBoundingSet) an die Arbeitslast anpassen.

Risiken

  • Ein Dienst als root mit Netzwerkzugriff ist die riskanteste Vorgabe; die erzeugte Unit vermeidet sie, aber prüfen Sie, dass Ihr ExecStart-Binary root gehört.
  • ProtectSystem=strict kann Dienste brechen, die ausserhalb ihres Arbeitsverzeichnisses schreiben — vor Produktion testen.
  • Restart=on-failure schützt nicht vor Abstürzen mit Exit-Status 0; für kritische Worker Restart=always erwägen.

Grenzen

  • Das Werkzeug erzeugt die Datei; es kann nicht testen, dass Ihr Programm startet oder dass seine Rechte stimmen.
  • Es erzeugt keine Socket-Aktivierung, Timer oder komplexen Abhängigkeitsgraphen.
  • Die Härtung ist Basis — eine echte Prüfung sollte Capabilities, seccomp und Netzwerk-Namespaces berücksichtigen.

Offizielle Referenzen

FAQ

Warum ein eigener Benutzer für jeden Dienst?

Ein eigener unprivilegierter Benutzer begrenzt, was ein kompromittierter Dienst tun kann: Er kann weder fremde Dateien lesen noch ausserhalb seiner eigenen Pfade schreiben. Root sollte wenigen Diensten vorbehalten sein, die ihn wirklich brauchen.

Was bewirkt NoNewPrivileges=true?

Es verhindert, dass der Dienst und seine Kinder über Setuid-Binaries oder ähnliche Mechanismen Privilegien erlangen, selbst wenn solche Binaries auf dem System existieren.

Was ist ProtectSystem=strict?

Es macht das gesamte Dateisystem für den Dienst schreibgeschützt, ausser explizit erlaubten Pfaden. Es ist die stärkste ProtectSystem-Stufe und passt gut zu Diensten, die nur in ihr Arbeitsverzeichnis oder /tmp schreiben.