En VPN-demon behöver privilegierade nätverksoperationer trots att vanliga program öppnar utgående sockets helt utan privilegier. Det är i den luckan de flesta kapabilitetsfel börjar: någon ser ett behörighetsfel, ger hela uppsättningen, och tjänsten fungerar av skäl som ingen senare kan förklara. Genomgången nedan börjar vid operationen som misslyckades, kopplar den till en enda behörighet och kontrollerar sedan den kontext som processen faktiskt kör i. Att köra som obegränsad root är ett giltigt svar för vissa driftsättningar, men det bör vara ett beslut och inte ett standardvärde.

Börja vid operationen som misslyckades

Läs felet innan du läser en guide. ”Åtgärden är inte tillåten” vid en gränssnittsändring, ett nekande att öppna en enhetsnod och ett bind-fel på en låg port är tre olika problem med tre olika beviljanden. Om processen startar och bara misslyckas vid den första ruttändringen betyder det också att gränssnittet redan har skapats, vilket snävar in svaret betydligt.

Reproducera felet med tjänsten stoppad och starta den sedan i förgrunden under samma användare om implementeringen tillåter det. Ett fel du kan se är bättre än en loggrada du måste gissa dig till, och det gör skillnaden mellan ett kapabilitetsproblem och ett avslag från SELinux eller AppArmor tydlig.

Koppla varje operation till en enda behörighet

Tabellen är en startkarta, inte en ersättning för implementeringens dokumentation:

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

De två raderna i tabellen är dem folk blandar ihop. Att öppna /dev/net/tun är en fråga om filrättigheter; att be kärnan konfigurera det du öppnade är en fråga om kapabiliteter. Att ge CAP_NET_ADMIN reparerar inte en enhetsnod som din tjänsteanvändare inte kan läsa, och att reparera noden ger dig inte ruttbehörighet. Kontrollera båda innan du ändrar någon av dem.

Kärnans WireGuard och tunnelprogram i användarutrymmet har inte heller identiska krav. Kärnmodulens väg konfigurerar ett befintligt gränssnitt via netlink, medan en implementering i användarutrymmet också kan behöva enheten och, för vissa transporter, råa sockets.

Läs kontexten: tjänst, container eller skal

En kapabilitet i värddatorns nätverksnamnrymd kan påverka långt mer än samma operation inuti en medvetet isolerad stack. En container-runtime börjar vanligtvis med en reducerad gränsuppsättning; att lägga till NET_ADMIN till en container som delar värdens nätverk är ett mycket större beviljande än att lägga det till en med egen nätverksnamnrymd och utan värdmonteringar.

För systemd-enheter, läs vad som faktiskt tillämpas och inte vad enhetsfilen verkar säga: systemctl show -p CapabilityBoundingSet -p AmbientCapabilities rapporterar de effektiva värdena, som kan ha satts av en drop-in du glömt. Fråga efter det effektiva värdet, aldrig det avsedda. Ambient-kapabiliteter spelar roll eftersom en tjänst utan root förlorar kapabiliteter genom exec utan dem.

Utgå från paketets eller avbildningens stödda uppsättning. Lägg inte till råa socketrättigheter eller privilegierat läge bara för att en annan guide listade dem för ett annat verktyg; det resonemanget överför ingenting och kostar dig isoleringen du betalade för. Om du är osäker, ge ingenting och läs implementeringens anteckningar för den exakta operationen du behöver.

Se vad som händer när privilegierna faller

Många demoner startar privilegierat, konfigurerar gränssnittet, byter sedan till en oprivilegierad användare och behåller tunneln. Från den punkten kan processen inte längre lägga till en rutt, skriva om en brandväggsregel eller öppna en ny privilegierad enhet, vilket är okej tills en återanslutning behöver just det. Senare filläsningar och hook-körning kan misslyckas av samma skäl.

Testa hela livscykeln i stället för den första sekunden: uppstart, en förnyelse eller återanslutning och städning vid stopp. Ett första lyckat gränssnittsskapande bevisar inte att varje senare privilegierad operation fortfarande fungerar, och felet dyker vanligtvis upp timmar senare i produktion.

Implementeringar som håller tunneln öppen genom ett användarbyte kombinerar det vanligtvis med alternativ för att bevara tunneln och nycklarna. På systemd-sidan är den motsvarande frågan om enhetens kapabilitetsuppsättning överlever det användarbyte du konfigurerade.

Skriv ner beviljandet och skälet till det

Skriv ned det exakta beviljandet, den operation det möjliggör och det fel det åtgärdade. En rad i driftsättningsanteckningarna — ”CAP_NET_ADMIN i enhetens nätverksnamnrymd, nödvändigt för ruttändringar efter återanslutning” — räcker för att hindra nästa person från att utöka beviljandet igen.

Läs sedan om den effektiva uppsättningen efter varje uppgradering. Leverantörer lägger till funktioner, avbildningar ändrar standardvärden, och en kapabilitet som var onödig i fjol kan bli bärande utan att någon märker det.

Relaterade artiklar