De hook werkt wanneer u hem met de hand als root uitvoert en retourneert Operation not permitted op het moment dat de dienst hem start. Het bestand veranderde niet tussen die runs; de omgeving wel. systemd geeft het proces een kleinere wereld: minder capabilities, een andere /dev, alleen-lezen bestandssysteempaden en een plafond voor taken. Lees de fout als een grens die één specifieke bewerking weigerde, niet als een script dat stukging.

Begin bij de bewerking die werd geweigerd

Een logregel die zegt dat de unit is mislukt, vertelt u bijna niets. De nuttige regel noemt de aanroep die werd geweigerd: een apparaatknooppunt dat niet kon worden geopend, een map waarin niet kon worden geschreven, een namespace die niet kon worden gemaakt. Zoek die aanroep voordat u één richtlijn aanraakt, want elk ervan hoort bij een andere beperking. Lees daarna de unit die echt liep, inclusief drop-ins, in plaats van het bestand dat het pakket leverde.

De query hieronder print het fragmentpad, de drop-in-mappen en de eigenschappen die van belang zijn bij een weigering van een apparaat of bestandssysteem. Lees ze allemaal voordat u beslist welke grens relevant is:

systemctl show "[email protected]" -p FragmentPath -p DropInPaths -p PrivateDevices -p DevicePolicy -p DeviceAllow -p ProtectHome -p ProtectSystem -p TasksMax
journalctl -u "[email protected]" -b --no-pager | grep -iE 'operation not permitted|permission denied|cannot open|failed'

Niets in dat blok schrijft. Ontbreekt de geweigerde aanroep in het journaal, verhoog dan de uitvoerigheid van de client voor één run in plaats van richtlijnen te raden. Een lopend proces bewijst dat de unit is gestart, niet dat de hook met de benodigde rechten liep.

Een namespace heeft mount-rechten nodig die een TUN-apparaat nooit gebruikt

Twee bewerkingen die er binnen één hook hetzelfde uitzien, hebben verschillende rechtenprofielen. Het openen van /dev/net/tun en het aanmaken van de interface vereist netwerkbeheer plus toegang tot dat knooppunt. Een benoemde netwerknamespace aanmaken vereist ook mount-werk, omdat het namespace-gereedschap een verse /sys weergave mount en een statusmap op zijn plek bindt. de client-unit uit upstream laat mount-beheer bewust buiten zijn bounding set, dus de namespacestap wordt geweigerd terwijl de tunnel zelf zou hebben gewerkt.

Daarom redt het toekennen van het apparaatknooppunt het script niet. Een apparaattoestemming beantwoordt één vraag, of dit proces dit knooppunt mag openen, en de namespacevraag is een andere. Koppel de falende aanroep aan zijn capability voordat u iets verbreedt.

Een test in uw shell erft elke capability die een onbeperkte root heeft, en de unit erft wat zijn bounding set behield. Die twee runs zijn verschillende experimenten zelfs wanneer het binaire bestand identiek is.

Apparaten, beschermde paden en plafonds voor taken

Zodra de geweigerde bewerking bekend is, verklaren drie groepen richtlijnen de meeste fouten. Apparaattoegang wordt geregeld door PrivateDevices, dat /dev vervangt door een minimale set pseudo-apparaten, en door DevicePolicy met DeviceAllow, die bepalen wat de cgroup toestaat. /dev/net/tun maakt geen deel uit van die minimale set, dus een unit met PrivateDevices=yes kan het niet openen, wat het apparaatbeleid ook zegt.

Bestandssysteembescherming beantwoordt een tweede vraag. ProtectHome=yes maakt /home, /root en /run/user ontoegankelijk, en ProtectSystem=full maakt /usr, /boot en /etc alleen-lezen. Daarom werkt een hook die naast zijn eigen configuratiebestand schrijft in uw shell en faalt hij onder de unit, met dezelfde vorm van toestemming als een ontbrekende capability. Verplaats de schrijfbare invoer naar een pad dat het beleid toestaat, of voeg een smalle ReadWritePaths= vermelding toe.

Resourcelimieten zijn de derde groep, en de minst voor de hand liggende. TasksMax= begrenst hoeveel taken de unit mag aanmaken, en een plafond voor bestandsdescriptors gedraagt zich hetzelfde voor sockets en handles. Een uitrol die voorbij het plafond is gegroeid, faalt met een resourcefout in plaats van een toestemmingsfout, en daarom doet de exacte melding er nog toe.

Haal de namespacestap uit de hook

Voorbereiding die een privilege vereist dat de client niet mag hebben, hoort in zijn eigen unit. Een oneshot die vóór de client draait, zijn resultaat bewaart en vóór de verbinding is geordend, geeft de namespacestap wat hij nodig heeft zonder die rechten aan het tunnelproces te geven. De client verwijst daarna naar die unit in plaats van het script vanuit zijn up-hook aan te roepen.

De sjabloon hieronder is een beginvorm, niet iets om ongelezen toe te passen. Hij houdt de voorbereiding waar het privilege woont en laat de tunnelunit ongemoeid:

# /etc/systemd/system/[email protected]
[Unit]
Description=Namespace preparation for %i
Before=openvpn-client@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/netns-up.sh %i
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
[Install]
WantedBy=multi-user.target

Voeg de ordening toe met een drop-in in plaats van de verpakte unit te bewerken, zodat een upgrade uw wijziging niet stil kan laten vallen. De map is gekoppeld aan de instantienaam, dus een tweede profiel heeft zijn eigen bestand nodig:

sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-namespace.conf >/dev/null <<'CONF'
[Unit]
[email protected]
[email protected]
CONF
sudo systemctl daemon-reload

Herhaal dezelfde aanroep na de wijziging

Een reparatie is pas bevestigd wanneer dezelfde aanroep een ander resultaat geeft. Herstart beide units, voer de bewerking uit die faalde en vergelijk het resultaat met de logregel die u vóór de wijziging bewaarde. Een unit die start terwijl de hook nooit meer draait, is geen reparatie.

De volgorde hieronder houdt de vergelijking eerlijk, omdat hij de geweigerde aanroep controleert en niet de kleur van de unit. Bewaar de uitvoer naast de logregel die u vóór de wijziging vastlegde:

sudo systemctl restart "[email protected]" "[email protected]"
systemctl status "[email protected]" --no-pager
journalctl -u "[email protected]" -b --no-pager | grep -c 'Operation not permitted'
ip -brief addr show tun0

Tel de weigeringen in plaats van de laatste regel te lezen, want een hook kan falen, opnieuw proberen en slagen, en alleen het aantal laat zien of de grens is verschoven. Laat een opmerking achter in de drop-in die de richtlijn noemt die u hebt versoepeld en de reden, omdat de volgende upgrade uw configuratie met de verpakte standaard vergelijkt. Een unit die pas start wanneer elke bescherming is uitgeschakeld, is niet gerepareerd.

Gerelateerde artikelen