Donner CAP_NET_ADMIN à OpenVPN sans lui donner root
Une unité qui démarre en tant qu'utilisateur non privilégié a toujours besoin du bon jeu de capacités. Vérifiez l'unité, le processus vivant et la limite exec, dans cet ordre.
Le service démarre, le journal se plaint de ne pas pouvoir ouvrir le périphérique tun, et les routes n'apparaissent jamais. Lancez capsh --print dans votre shell et cap_net_admin est juste là, ce qui rend l'échec impossible. Ce qui diffère entre votre shell et l'unité, c'est la transition de privilèges, pas la volonté du noyau d'accorder la capacité. Parcourez les quatre vérifications ci-dessous dans l'ordre et arrêtez-vous à la première qui explique l'écart.
Distinguer une capacité manquante d'un périphérique caché
Deux échecs se ressemblent dans la ligne de journal. Un processus sans CAP_NET_ADMIN ne peut ni créer ni configurer l'interface du tunnel, et un processus dont le bac à sable masque /dev/net/tun ne peut pas l'ouvrir du tout. Ajouter des capacités ne corrigera pas le second cas.
Vérifiez si le périphérique existe dans l'espace de noms du service avant de modifier quoi que ce soit. PrivateDevices=yes est une ligne de durcissement courante qui supprime entièrement le nœud tun, et un ProtectSystem restrictif peut rendre le chemin de configuration en lecture seule d'une manière qui se lit comme une erreur de permissions. Les deux produisent des lignes de journal qui mentionnent le tunnel, et c'est pourquoi on accuse les capacités. Confirmez d'abord que le nœud est présent et ouvrable, puis avancez.
Savoir quel jeu de capacités vous regardez
Linux tient des jeux permis, effectifs, héritables, limites et ambiants, et le jeu ambiant est celui qui survit à un exec par un utilisateur non root. Les capacités de fichier sur le binaire peuvent transmettre des droits permis et effectifs à l'exec, mais seulement tant que rien dans la chaîne ne bloque ce transfert.
C'est ici que sudo induit les gens en erreur. Une commande lancée via sudo -u entame une nouvelle transition de privilèges et le jeu ambiant disparaît, si bien que la même vérification qui réussit en root échoue là. Le gestionnaire de services est encore une autre transition, et il n'accorde rien d'ambiant sauf si l'unité le dit.
Accorder la capacité dans l'unité, pas dans un wrapper
Une section de service minimale pour un tunnel qui doit créer un périphérique et installer des routes se lit ainsi.
[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.confAmbientCapabilities place le droit dans le jeu ambiant avant le démarrage du processus, et CapabilityBoundingSet empêche le processus de détenir quoi que ce soit hors de cette liste. NoNewPrivileges=yes bloque l'obtention de privilèges via setuid ou les capacités de fichier, tandis que la capacité que l'unité accorde explicitement s'applique toujours. Ajoutez CAP_NET_BIND_SERVICE uniquement lorsque le service doit lier un port bas, et n'ajoutez jamais CAP_SYS_ADMIN simplement parce qu'un fil de forum l'a fait.
Si l'unité enveloppe le binaire dans sudo, retirez le wrapper. systemd applique déjà User=, et cette couche supplémentaire est la raison la plus probable du jeu ambiant vide.
Vérifiez sur le processus vivant, pas sur le fichier d'unité
Lisez ce que le gestionnaire a réellement appliqué, puis lisez le processus qu'il a engendré.
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")/statusSi l'unité liste la capacité et que CapEff en manque encore, un drop-in écrase le réglage ou une étape ExecStartPre modifie l'environnement. Cherchez le nom de l'unité dans les répertoires drop-in avant de supposer que le fichier principal fait autorité, car un fichier plus tardif gagne en silence. Si l'unité et le processus montrent tous deux la capacité et que le tunnel échoue encore, revenez aux vérifications du périphérique et du chemin plutôt que d'élargir le jeu limite. L'élargir masque la cause réelle et laisse le service plus privilégié qu'avant.
Préférez abandonner les privilèges après le démarrage
OpenVPN peut démarrer avec des privilèges puis passer à un compte non privilégié via ses propres options user et group, persist-key et persist-tun gardant le tunnel utilisable ensuite. Cet agencement réduit la fenêtre pendant laquelle le processus détient des droits, et il convient souvent mieux que de démarrer tout le démon sans privilèges avec des capacités permanentes.
Quel que soit le modèle choisi, redémarrez l'unité et répétez les vérifications après un redémarrage, car un service qui fonctionne depuis un shell root interactif et échoue au démarrage est généralement une différence de capacité, de périphérique ou de permissions de fichier. Notez les réglages de l'unité à côté de la sortie des capacités du processus, afin que le prochain relecteur voie si une mise à jour de paquet ou un drop-in a déplacé la limite.