NET_ADMIN er den Linux-kapacitet, der lader en proces udføre netværksadministration, og i en container gør den præcis det inde i det netværksnavnerum, hvor processen kører. Det er ikke en licens til at åbne en socket, og det er ikke en erstatning for en enhed eller en rute. Det interessante spørgsmål er aldrig, om kapaciteten er givet, men hvilket navnerum der modtager ændringen.

Hvad kapaciteten dækker

Inde i sit navnerum kan en proces med NET_ADMIN bringe grænseflader op og ned, tildele adresser, tilføje og fjerne ruter og skrive firewallregler, hvilket er den gruppe af operationer, som capabilities(7) samler under denne kapacitet. Den kan også justere indstillinger på grænsefladeniveau, der styrer, hvordan kernen sætter trafik i kø og filtrerer den. En VPN-klient har typisk brug for nogle få af dem ved opstart og intet andet bagefter. Derfor beder de fleste images om større rækkevidde, end de bruger.

Operationer uden for det navnerum er ikke dækket, og tilstødende privilegier er adskilte. Læsning og skrivning af rå pakker hører til NET_RAW, og oprettelse af en tun-enhed kræver både kapaciteten og adgang til enhedsknudepunktet. En proces uden enheden får en tilladelsesfejl, der ligner et netværksproblem og ikke er det.

Navnerummet bestemmer skadesradiusen

En container på sit eget bro-netværk når sit eget loopback, sine egne grænseflader og sin egen routingtabel. At give NET_ADMIN der lader VPN-klienten bygge en tunnel uden at røre værtens routingbeslutninger, hvilket er den ordning, de fleste container-images forudsætter.

Skift den container til værtsnetværk, og den samme tildeling redigerer nu værtens ruter og værtens firewall, fordi der ikke er noget separat navnerum tilbage. Den klient, der skulle styre én tunnel, kan derefter omdirigere trafik for hele maskinen, og en fejl i dens nedrivningsscript efterlader værten med regler, som ingen har skrevet. Intet i selve kapaciteten ændrede sig; konteksten gjorde. Derfor opfører den samme compose-fil sig forskelligt på to værter.

Tre forudsætninger, der smeltes sammen til én

Opstartsfejl i VPN-containere involverer normalt en af tre adskilte ting: kapaciteten, tunneleenheden og kernestøtte til protokollen. At give alle tre på én gang virker, og det gør også den næste fejl umulig at tilskrive. Et minimalt compose-uddrag giver kapaciteten og sender enhedsknudepunktet eksplicit:

services:
  vpn:
    image: example/vpn-client:latest
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1

Læs imagets egen dokumentation for, hvilke sysctls det har brug for, fordi en sysctl i en container kan kræve et ekstra privilegium eller en indstilling på værtsniveau. Hvor imaget kun understøtter brugertilstand, er der slet ikke brug for en enhed, og kapacitetslisten skrumper tilsvarende.

Giv den snævre operation, ikke tilstanden

Privilegeret tilstand overdrager enhver kapacitet og udvider enhedsadgangen på samme tid, så den skjuler, hvilken af de tre forudsætninger der manglede. Den gør også containerens fejltilstande umulige at skelne fra ændringer på værten. Foretræk en eksplicit liste, selv når den er længere at skrive.

Rootless- og brugernavnerumsudrulninger ændrer, hvad en kapacitet betyder i praksis, da processen kun kan holde den inde i et mappet navnerum. At kopiere en kapacitetsliste fra et rootful-eksempel til en rootless-kørselsmiljø og forvente samme rækkevidde er en almindelig måde at miste en eftermiddag.

Hemmeligheder hører til en separat beslutning. At holde NET_ADMIN siger intet om, hvilken peer-identitet klienten fremviser, hvilke legitimationsoplysninger den indlæser, eller hvordan de roteres. Netværksadministration leverer ikke tillid.

Bekræft ændringen, og notér hvorfor tildelingen findes

Bekræft, hvad containeren faktisk modtog, før du fejlfinder tunnelen. Inspektionen nedenfor rapporterer de tilføjede kapaciteter og netværkstilstanden og viser derefter, hvordan grænsefladelisten ser ud indefra:

docker inspect --format '{{.HostConfig.CapAdd}} {{.HostConfig.NetworkMode}} {{.HostConfig.Privileged}}' vpn
docker exec vpn sh -c 'grep CapEff /proc/self/status'
docker exec vpn ip -br addr
docker exec vpn ip route

Hvis kapaciteten er til stede, og grænsefladelisten stadig er tom, fejlede klienten, før den kunne oprette noget, og containerlogfilerne er det næste sted at kigge. Hvis tunnelen findes, men trafikken ikke flyder, svarer routingtabellen inde i containeren på det næste spørgsmål.

Test også nedrivningsvejen, fordi en klient, der skriver firewallregler, kan efterlade dem. Stop containeren, og tjek værtens regelsæt igen, hvis værtsnetværk bruges. En tildeling, der kun er nødvendig i to sekunder ved opstart, bør ikke beskrives i compose-filen som et permanent krav uden en note, der forklarer det.

Skriv årsagen ved siden af hver kapacitet: hvilken operation der havde brug for den, og hvad der fejler uden den. Den note overlever imageopdateringer, og den er forskellen mellem en gennemgået privilegieliste og en, der er vokset ved kopiering.

Relaterede artikler