Ge OpenVPN CAP_NET_ADMIN utan att ge det root
En unit som startar som oprivilegierad användare behöver fortfarande rätt uppsättning kapabiliteter. Kontrollera uniten, den levande processen och exec-gränsen, i den ordningen.
Tjänsten startar, loggen klagar på att den inte kan öppna tun-enheten, och rutter dyker aldrig upp. Kör capsh --print i ditt skal och cap_net_admin finns direkt där, vilket gör felet omöjligt att förklara. Det som skiljer ditt skal från uniten är privilegieövergången, inte kärnans vilja att ge kapabiliteten. Gå igenom de fyra kontrollerna nedan i ordning och stanna vid den första som förklarar skillnaden.
Skilj en saknad kapabilitet från en dold enhet
Två fel ser likadana ut i loggraden. En process utan CAP_NET_ADMIN kan inte skapa eller konfigurera tunnelns gränssnitt, och en process vars sandlåda döljer /dev/net/tun kan inte öppna den alls. Att lägga till kapabiliteter löser inte det andra fallet.
Kontrollera om enheten finns inne i tjänstens namnrymd innan du ändrar något. PrivateDevices=yes är en vanlig härdningsrad som tar bort tun-noden helt, och en restriktiv ProtectSystem kan göra konfigurationsvägen skrivskyddad på ett sätt som läses som ett behörighetsfel. Båda ger loggrader som nämner tunneln, och därför får kapabiliteterna skulden. Bekräfta först att noden finns och går att öppna, och gå sedan vidare.
Vet vilken kapabilitetsuppsättning du tittar på
Linux håller permitterade, effektiva, ärvbara, begränsande och ambienta uppsättningar, och den ambienta uppsättningen är den som överlever en exec från en användare som inte är root. Filkapabiliteter på binären kan överlämna permitterade och effektiva rättigheter vid exec, men bara så länge inget i kedjan blockerar den överföringen.
Det är här sudo vilseleder folk. Ett kommando som körs via sudo -u börjar en ny privilegieövergång och den ambienta uppsättningen är borta, så samma kontroll som lyckas som root misslyckas där. Tjänstehanteraren är ännu en övergång, och den ger inget ambient om inte uniten säger det.
Ge kapabiliteten i uniten, inte i ett omslag
Ett minimalt tjänsteavsnitt för en tunnel som måste skapa en enhet och installera rutter ser ut så här.
[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 sätter rättigheten i den ambienta uppsättningen innan processen startar, och CapabilityBoundingSet hindrar processen från att hålla något utanför listan. NoNewPrivileges=yes blockerar privilegieökning via setuid eller filkapabiliteter, medan kapabiliteten som uniten uttryckligen ger fortfarande gäller. Lägg bara till CAP_NET_BIND_SERVICE när tjänsten måste binda en låg port, och lägg aldrig till CAP_SYS_ADMIN bara för att en forumtråd gjorde det.
Om uniten lindar in binären i sudo, ta bort omslaget. systemd tillämpar redan User=, och det extra lagret är den mest sannolika orsaken till att den ambienta uppsättningen är tom.
Verifiera mot den levande processen, inte mot unitfilen
Läs vad hanteraren faktiskt tillämpade och läs sedan processen den startade.
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")/statusOm uniten listar kapabiliteten och CapEff fortfarande saknar den, åsidosätter någon drop-in inställningen eller så ändrar ett ExecStartPre-steg miljön. Sök efter unitnamnet i drop-in-katalogerna innan du antar att huvudfilen är auktoritativ, eftersom en senare fil vinner i tysthet. Om både uniten och processen visar kapabiliteten och tunneln fortfarande misslyckas, gå tillbaka till enhets- och sökvägskontrollerna i stället för att vidga den begränsande uppsättningen. Att vidga den döljer den verkliga orsaken och lämnar tjänsten mer privilegierad än den var.
Föredra att släppa privilegier efter start
OpenVPN kan starta privilegierat och sedan gå ned till ett oprivilegierat konto via sina egna user- och group-alternativ, medan persist-key och persist-tun håller tunneln användbar efteråt. Den ordningen snävar in fönstret där processen har rättigheter, och den passar ofta bättre än att starta hela daemonen oprivilegierat med permanenta kapabiliteter.
Vilken modell du än väljer, starta om uniten och upprepa kontrollerna efter en omstart, eftersom en tjänst som fungerar från ett interaktivt root-skal men misslyckas vid uppstart oftast är en skillnad i kapabilitet, enhet eller filrättigheter. Anteckna unitens inställningar bredvid processens kapabilitetsutdata så att nästa granskare ser om en paketuppdatering eller en drop-in har flyttat gränsen.