Der Dienst startet, das Log beklagt, dass es das tun-Gerät nicht öffnen kann, und Routen erscheinen nie. Führen Sie capsh --print in Ihrer Shell aus, und cap_net_admin ist genau dort, was den Fehler unmöglich erscheinen lässt. Was sich zwischen Ihrer Shell und der Unit unterscheidet, ist der Privilegienübergang, nicht die Bereitschaft des Kernels, die Capability zu gewähren. Gehen Sie die vier Prüfungen unten der Reihe nach durch und halten Sie bei der ersten an, die die Lücke erklärt.

Fehlende Capability von verstecktem Gerät trennen

Zwei Fehler sehen in der Logzeile gleich aus. Ein Prozess ohne CAP_NET_ADMIN kann die Tunnel-Schnittstelle nicht anlegen oder konfigurieren, und ein Prozess, dessen Sandbox /dev/net/tun verbirgt, kann sie von vornherein nicht öffnen. Zusätzliche Capabilities beheben den zweiten Fall nicht.

Prüfen Sie, ob das Gerät im Namespace des Dienstes existiert, bevor Sie etwas ändern. PrivateDevices=yes ist eine verbreitete Härtungszeile, die den tun-Knoten vollständig entfernt, und ein restriktives ProtectSystem kann den Konfigurationspfad schreibgeschützt machen, was wie ein Berechtigungsfehler klingt. Beide erzeugen Logzeilen, die den Tunnel erwähnen, weshalb die Capabilities die Schuld bekommen. Bestätigen Sie zuerst, dass der Knoten vorhanden und öffenbar ist, und gehen Sie dann weiter.

Wissen, welchen Capability-Satz Sie betrachten

Linux führt permissive, effektive, vererbbare, begrenzende und ambiente Sätze, und der ambiente Satz ist der, der ein exec durch einen Nicht-root-Benutzer überlebt. Datei-Capabilities an der Binärdatei können bei exec erlaubte und effektive Rechte übergeben, aber nur solange nichts in der Kette diese Übergabe blockiert.

Hier führt sudo die Leute in die Irre. Ein Befehl, der über sudo -u läuft, beginnt einen neuen Privilegienübergang und der ambiente Satz ist weg, sodass dieselbe Prüfung, die als root gelingt, dort fehlschlägt. Der Dienstmanager ist wieder ein anderer Übergang und gewährt nichts Ambientes, wenn die Unit es nicht sagt.

Die Capability in der Unit vergeben, nicht in einem Wrapper

Ein minimaler Dienstabschnitt für einen Tunnel, der ein Gerät anlegen und Routen installieren muss, sieht so aus.

[Unit]
Description=OpenVPN client, office profile
After=network-online.target

[Service]
Type=notify
User=openvpn
Group=openvpn
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/office.conf

AmbientCapabilities legt das Recht in den ambienten Satz, bevor der Prozess startet, und CapabilityBoundingSet hindert den Prozess daran, etwas außerhalb dieser Liste zu halten. NoNewPrivileges=yes blockiert Privilegienerwerb über setuid oder Datei-Capabilities, während die von der Unit ausdrücklich vergebene Capability weiter gilt. Fügen Sie CAP_NET_BIND_SERVICE nur hinzu, wenn der Dienst einen niedrigen Port binden muss, und fügen Sie CAP_SYS_ADMIN niemals hinzu, nur weil ein Forenthread es getan hat.

Wenn die Unit die Binärdatei in sudo einwickelt, entfernen Sie den Wrapper. systemd wendet bereits User= an, und diese zusätzliche Schicht ist der wahrscheinlichste Grund für den leeren ambienten Satz.

Gegen den laufenden Prozess prüfen, nicht gegen die Unit-Datei

Lesen Sie, was der Manager tatsächlich angewendet hat, und lesen Sie dann den Prozess, den er gestartet hat.

unit=openvpn-client@office
systemctl show -p User -p AmbientCapabilities "$unit"
systemctl show -p MainPID --value "$unit" | xargs -r getpcaps
grep -E '^Cap(Eff|Amb)' /proc/$(systemctl show -p MainPID --value "$unit")/status

Wenn die Unit die Capability auflistet und CapEff sie trotzdem nicht hat, überschreibt ein Drop-in die Einstellung oder ein ExecStartPre-Schritt ändert die Umgebung. Durchsuchen Sie die Drop-in-Verzeichnisse nach dem Unit-Namen, bevor Sie die Hauptdatei für maßgeblich halten, denn eine spätere Datei gewinnt still. Wenn sowohl die Unit als auch der Prozess die Capability zeigen und der Tunnel weiter scheitert, gehen Sie zurück zu den Geräte- und Pfadprüfungen, statt den begrenzenden Satz zu erweitern. Eine Erweiterung verbirgt die eigentliche Ursache und lässt den Dienst privilegierter als zuvor.

Privilegien lieber nach dem Start abgeben

OpenVPN kann privilegiert starten und dann über seine eigenen Optionen user und group auf ein unprivilegiertes Konto wechseln, während persist-key und persist-tun den Tunnel danach nutzbar halten. Diese Anordnung verengt das Zeitfenster, in dem der Prozess Rechte hält, und passt oft besser, als den ganzen Daemon unprivilegiert mit dauerhaften Capabilities zu starten.

Welches Modell Sie auch wählen, starten Sie die Unit neu und wiederholen Sie die Prüfungen nach einem Neustart, denn ein Dienst, der aus einer interaktiven root-Shell funktioniert und beim Booten scheitert, ist meist ein Unterschied bei Capability, Gerät oder Dateiberechtigungen. Notieren Sie die Unit-Einstellungen neben der Capability-Ausgabe des Prozesses, damit die nächste Prüfung sieht, ob ein Paketupdate oder ein Drop-in die Grenze verschoben hat.

Ähnliche Artikel