Open Source im professionellen Einsatz
Linux-Magazin 02/2016
© ammentorp, 123RF

© ammentorp, 123RF

Systemd und die Prozesse

Vom Start weg

Fast alles, was ein Computer tut – rechnen, speichern, ein- und ausgeben von Daten –, das tut er mit Hilfe von Prozessen. Entsprechend wichtig ist die Kontrolle über diese Prozesse, bei der Systemd ein gewichtiges Wörtchen mitzureden hat.

1071

Die ersten Prozesse starten beim Booten, und schon hier hat Systemd gleich mehrfach seine Finger im Spiel. Zum einen, indem es den gesamten Bootvorgang steuert und organisiert, zum anderen, indem es später Auskunft gibt, wie es den gestarteten Prozessen geht.

Dabei tritt Systemd die Nachfolge des System-V-Init-Systems an, das inzwischen in die Jahre gekommen ist. Das lässt sich beispielsweise daran ablesen, dass diese Methode für den Systemstart die nötigen Prozesse nur streng nacheinander und in einer starren Reihenfolge in die Spur schicken kann, was verglichen mit dem gleichzeitigen Start verschiedener Services Zeit kostet.

Außerdem benutzt System-V-Init für alle Aktionen Shellskripte, die zwar wortreich, aber dennoch schwer leserlich und zudem langsam sind. Außerdem eignen sie sich beispielsweise für die Koordination parallel laufender Prozesse nur schlecht. Systemd ist dazu angetreten, eine bessere Alternative zu bieten.

Der neue Bootvorgang

Systemd managt nicht nur Dienste, sondern auch Geräte oder Mountpoints. All diese Dinge bezeichnet es als Unit. Die Dateien, die eine solche Unit während des Bootens initialisieren und starten, heißen folgerichtig Unitfiles. Sie sind der direkte Nachfolger der Initskripte. Der Admin findet sie nicht mehr wie bei System-V in Runlevel-Verzeichnissen, sondern unter:

  • »/etc/systemd/system/*«
  • »/run/systemd/system/*«
  • »/usr/lib/systemd/system/*«

Unitfiles sind keine ausführbaren Dateien mehr, sondern Konfigurationsfiles im Stil der Ini-Dateien von Windows. Ein beispielhafter Blick auf das Unitfile für den Start eines MySQL-Servers zeigt die Systemd-Funktionsweise (Listing 1).

Der Abschnitt »[Unit]« enthält zum einen eine Klartext-Beschreibung des Dienstes und zum anderen mit »After« die Vorgabe, welche anderen Dienste vorher gestartet sein müssen. In diesem Fall verlässt sich MySQL darauf, dass das Netzwerk und der Syslog-Service bereits laufen. Mit »Before« ließe sich die gegensätzliche Abhängigkeit zwischen Diensten festlegen, dass also der im Unitfile definierte Dienst vor dem bezeichneten Service starten soll.

Der »[Service]« -Abschnitt legt fest, mit den Rechten welches Benutzers und welcher Gruppe der Datenbankserver laufen soll. Außerdem bestimmt »Type« hier die Art und Weise des Startvorgangs: »Simple« meint, dass das unter »ExecStart« angegebene Programm den Hauptprozess startet. Um Vorarbeiten kümmern sich die beiden unter »ExecStartPre« angegebenen MySQL-Skripte.

Mit »ExecStartPost« werden Skripte aufgerufen, die nach dem Start des Hauptprogramms laufen sollen. So wartet hier das Skript »mysql-wait-ready« darauf, dass MySQL die Aufräumarbeiten abschließt, die es beim Starten normalerweise erledigt. Dadurch starten Dienste, die MySQL voraussetzen, erst dann, wenn die Datenbank auch tatsächlich bereit ist Verbindungen anzunehmen.

Zudem legt das Unitfile noch einen Timeout fest und ordnet den Datenbankservice dem Multiuser-Target zu. Dieses Target ist eine spezielle Unit, die ungefähr die Rolle des früheren Runlevel 3 bei System-V spielt. Wenn sie aufgerufen wird, soll auch die Datenbank starten.

Listing 1

MySQL-Unitfile

01 [Unit]
02 Description=MySQL 5.6 database server
03 After=syslog.target
04 After=network.target
05
06 [Service]
07 Type=simple
08 User=mysql
09 Group=mysql
10
11 # Execute pre and post scripts as root
12 PermissionsStartOnly=true
13
14 ExecStartPre=/usr/libexec/mysql-check-socket
15 ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n
16 ExecStart=/usr/bin/mysqld_safe --basedir=/usr
17 ExecStartPost=/usr/libexec/mysql-wait-ready $MAINPID
18 ExecStartPost=/usr/libexec/mysql-check-upgrade
19
20 # Give a reasonable amount of time for the server to start up/shut down
21 TimeoutSec=300
22
23 # Place temp files in a secure directory, not /tmp
24 PrivateTmp=true
25
26 [Install]
27 WantedBy=multi-user.target

Mehr Sicherheit

Die Unitfiles kennen noch eine ganze Reihe weiterer Parameter, darunter solche, mit denen sich leicht die Sicherheit von Diensten verbessern lässt – und zwar sowohl einfacher als auch wirkungsvoller als das mit dem klassischen System-V-Init-System möglich gewesen ist.

Der erste dieser Parameter im Abschnitt »[Service]« ist:

PrivateNetwork=yes

Damit ist der Dienst von jedem Netzwerk vollkommen abgeschnitten. Er sieht dann nur noch ein Loopback-Device »lo« , und selbst das hat keine Verbindung zum echten Loopback-Device des Host. Natürlich hilft diese Option nicht bei Netzwerk-basierten Diensten weiter. Alle Diente aber, die ohne Netzwerk auskommen, sind damit vollkommen sicher vor Angriffen aus dieser Richtung.

Aber Achtung: Manchmal wird das Netzwerk doch gebraucht, obwohl das nicht auf den ersten Blick erkennbar ist – etwa weil der Dienst die Authentifikation via LDAP abwickeln will. In diesem Fall sollte sicher sein, dass nur Nutzer zu authentifizieren sind, die eine User-ID unterhalb von 1000 haben, denn für diese müssen sich die Namen lokal via »/etc/passwd« in UIDs auflösen lassen.

Ein zweites Sicherheitsfeature in »[Service]« ist:

PrivateTmp=yes

Ist diese Option gesetzt, benutzt der Dienst nicht mehr das globale »/tmp« -Verzeichnis, sondern sein eigenes. Das schützt ihn vor mancherlei bösartigen Symlink- und DoS-Attacken, die via »/tmp« gebräuchlich sind. Allerdings ist auch diese Maßnahme leider nicht in jedem Fall anwendbar. Manche Dienste platzieren nämlich Kommunikationssockets in »/tmp« , die nicht funktionieren, wenn sie sich in einem privaten Verzeichnis befinden.

Mit den nächsten beiden Optionen lässt sich verhindern, dass ein Dienst bestimmte Verzeichnisse beschreiben beziehungsweise überhaupt irgendwie auf sie zugreifen kann:

ReadOnlyDirectories=/var
InaccessibleDirectories=/home

Neben der Einschränkung mit Blick auf einzelne Verzeichnisse ist es schließlich auch möglich, einem Dienst einen Satz bestimmter Capabilities zuzuweisen oder ihm bestimmte Fähigkeiten zu entziehen. Eine Liste aller existierenden Capabilities findet sich in der Manpage »capabilities« . Gibt der Admin im Unitfile unter »[Service]« nun beispielsweise

CapabilityBoundingSet=CAP_CHOWN CAP_KILL

an, so hat er damit quasi eine Whitelist der Fähigkeiten definiert, die der Prozess haben muss.

Eine solche Whitelist festzulegen ist nicht immer einfach, oft wird der Admin nur durch Testen ermitteln können, welche Fähigkeiten er einem Dienst unbedingt zubilligen muss. Deshalb ist auch der umgekehrte Weg möglich. Wenn der Admin einer Capability eine Tilde voranstellt, dann bedeutet dies: Diese Fähigkeit soll dem Dienst explizit entzogen werden.

Zu guter Letzt ist es auch möglich, im Unitfile die Ressourcen zu begrenzen, auf die ein Dienst zugreifen darf. Alle beschränkbaren Ressourcen listet die Manpage »setrlimit« . Setzt der Admin wie im Beispiel unten beispielsweise die maximale Größe eines File, das der Dienst erzeugen darf (»FSIZE« ), auf »0« , so darf dieser nirgendwohin schreiben. Definiert man als maximale Anzahl von Prozessen, die der Dienst erzeugen darf (»NPROC« ), den Wert »1« , dann kann der Dienst keine weiteren Prozesse forken:

LimitNPROC=1
LimitFSIZE=0

In analoger Weise lassen sich auch andere Ressourcen begrenzen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 4 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Paketmaintainer

    Systemd betrifft nicht nur Admins von Systemen, sondern auch die Betreuer von Paketen. Ganz gleich, ob es sich um offizielle Distributionspakete oder das eigene Repository handelt – beim Umstieg auf Systemd gibt es einiges zu beachten.

  • Insecurity Bulletin

    Ein eigentlich verbotener Benutzername zwingt Systemd zu einer unerwarteten Entscheidung. Entwickler gaben sich zunächst uneinsichtig.

  • Init-Systeme

    Für das Starten von Systemdiensten ist das Init-System zuständig. Möchte der Admin es konfigurieren, begegnen ihm mittlerweile neben dem traditionellen System-V- und BSD-Init auch die modernen Upstart und Systemd. Eine Überlebenshilfe für die Praxis.

  • Bitparade

    Das Initsystem Systemd hat die meisten Rennen gewonnen. Das äußert sich auch darin, dass bereits mehrere Tools eine Bedienung per Mausklick anbieten. Die Bitparade hat sechs davon gestartet.

  • Systemd 216 verbessert DNS-Auflösung

    Laut Systemd-Entwickler Lennart Poettering handelt es sich bei Systemd 216 um eine Major Release, die insbesondere die DNS-Auflösung komplettiert.

comments powered by Disqus

Ausgabe 11/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.