Ein VPN-Daemon braucht privilegierte Netzwerkoperationen, obwohl gewöhnliche Anwendungen ausgehende Sockets ganz ohne Privilegien öffnen. Genau in dieser Lücke beginnen die meisten Capability-Fehler: Jemand sieht einen Berechtigungsfehler, vergibt den ganzen Satz, und der Dienst läuft aus Gründen, die später niemand erklären kann. Der folgende Durchgang beginnt bei der fehlgeschlagenen Operation, ordnet sie einer Befugnis zu und prüft dann den Kontext, in dem der Prozess tatsächlich läuft. Der Betrieb als uneingeschränkter root ist für manche Umgebungen eine gültige Antwort, sollte aber eine Entscheidung sein und kein Standard.

Beginnen Sie bei der fehlgeschlagenen Operation

Lesen Sie den Fehler, bevor Sie eine Anleitung lesen. „Operation not permitted“ bei einer Interface-Änderung, die Verweigerung, einen Geräteknoten zu öffnen, und ein Bind-Fehler auf einem niedrigen Port sind drei verschiedene Probleme mit drei verschiedenen Berechtigungen. Wenn der Prozess startet und erst bei der ersten Routenänderung scheitert, heißt das außerdem, dass die Interface-Erstellung bereits geklappt hat, was die Antwort erheblich verengt.

Reproduzieren Sie den Fehler bei gestopptem Dienst und starten Sie ihn dann im Vordergrund unter demselben Benutzer, wenn die Implementierung das erlaubt. Ein Fehler, den Sie sehen, ist besser als eine Logzeile, die Sie raten müssen, und er macht den Unterschied zwischen einem Capability-Problem und einer Ablehnung durch SELinux oder AppArmor deutlich.

Ordnen Sie jede Operation einer Befugnis zu

Die Tabelle ist eine Ausgangskarte, kein Ersatz für die Dokumentation der Implementierung:

OperationUsual authorityWatch for
Create or configure tun/tapCAP_NET_ADMIN in the relevant namespaceCreating the device and opening it are separate steps
Add routes, rules, firewall entriesCAP_NET_ADMINSame capability, different namespace than you think
Open /dev/net/tunDevice permissions, not a capabilityGroup membership or a udev rule may be enough
Raw socketsCAP_NET_RAWNeeded by some user-space tunnel implementations
Bind a port below 1024CAP_NET_BIND_SERVICEIrrelevant for most modern tunnel ports

Die beiden Zeilen in dieser Tabelle sind die, die Leute verwechseln. Das Öffnen von /dev/net/tun ist eine Frage der Dateiberechtigungen; den Kernel darum zu bitten, das Geöffnete zu konfigurieren, ist eine Frage der Capabilities. CAP_NET_ADMIN zu vergeben repariert keinen Geräteknoten, den Ihr Dienstbenutzer nicht lesen kann, und den Knoten zu reparieren gibt Ihnen keine Routenbefugnis. Prüfen Sie beides, bevor Sie eines von beiden ändern.

Kernel-WireGuard und Tunnelprogramme im Userspace haben ebenfalls keine identischen Anforderungen. Der Weg über das Kernelmodul konfiguriert ein vorhandenes Interface über netlink, während eine Userspace-Implementierung zusätzlich das Gerät und für manche Transporte rohe Sockets brauchen kann.

Lesen Sie den Kontext: Dienst, Container oder Shell

Eine Capability im Netzwerk-Namespace des Hosts kann weit mehr bewirken als dieselbe Operation in einem bewusst isolierten Stack. Eine Container-Laufzeit startet typischerweise mit einem reduzierten Bounding-Set; NET_ADMIN einem Container zu geben, der das Hostnetz teilt, ist eine viel größere Vergabe als einem mit eigenem Netzwerk-Namespace und ohne Host-Mounts.

Lesen Sie bei systemd-Units, was tatsächlich angewendet wird, statt was die Unit-Datei zu sagen scheint: systemctl show -p CapabilityBoundingSet -p AmbientCapabilities meldet die effektiven Werte, die ein vergessenes Drop-in gesetzt haben kann. Fragen Sie nach dem effektiven Wert, nie nach dem beabsichtigten. Ambient-Capabilities sind wichtig, weil ein Dienst ohne root ohne sie über exec hinweg Capabilities verliert.

Nehmen Sie die unterstützte Einrichtung des Pakets oder Images als Ausgangsbasis. Fügen Sie keine Raw-Socket-Rechte und keinen privilegierten Modus hinzu, nur weil eine andere Anleitung sie für ein anderes Werkzeug aufgeführt hat; diese Begründung überträgt nichts und kostet Sie die Isolierung, für die Sie bezahlt haben. Im Zweifel vergeben Sie nichts und lesen die Implementierungshinweise für die genaue Operation, die Sie brauchen.

Beobachten Sie, was nach dem Fall der Privilegien passiert

Viele Daemons starten privilegiert, konfigurieren das Interface und wechseln dann zu einem unprivilegierten Benutzer und behalten den Tunnel. Ab diesem Punkt kann der Prozess keine Route mehr hinzufügen, keine Firewall-Regel neu schreiben und kein neues privilegiertes Gerät öffnen, was in Ordnung ist, bis ein Reconnect genau das braucht. Spätere Dateizugriffe und Hook-Ausführung können aus demselben Grund scheitern.

Testen Sie den ganzen Lebenszyklus statt der ersten Sekunde: Start, eine Erneuerung oder ein Reconnect und die Bereinigung beim Stoppen. Eine erste erfolgreiche Interface-Erstellung belegt nicht, dass jede spätere privilegierte Operation noch funktioniert, und der Fehler tritt meist Stunden später im Produktivbetrieb auf.

Implementierungen, die den Tunnel über einen Benutzerwechsel hinweg offen halten, kombinieren das meist mit Optionen, den Tunnel und die Schlüssel zu erhalten. Auf der systemd-Seite lautet die entsprechende Frage, ob der Capability-Satz der Unit den konfigurierten Benutzerwechsel übersteht.

Halten Sie die Vergabe und ihren Grund fest

Schreiben Sie die genaue Vergabe auf, die Operation, die sie ermöglicht, und den Fehler, den sie behoben hat. Eine Zeile in den Deployment-Notizen — „CAP_NET_ADMIN im Netzwerk-Namespace der Unit, nötig für Routenänderungen nach einem Reconnect“ — genügt, damit die nächste Person die Vergabe nicht wieder ausweitet.

Lesen Sie danach nach jedem Upgrade den effektiven Satz erneut. Hersteller fügen Funktionen hinzu, Images ändern Standardwerte, und eine Capability, die letztes Jahr unnötig war, kann tragend werden, ohne dass es jemand merkt.

Ähnliche Artikel