OpenVPN stoppar med ei errno 2-klage over /dev/net/tun medan lsmod listar tun-modulen utan problem. Begge fakta er sanne samstundes. Modulen leverer ein drivar, og stigen klienten opnar, er ein einingknute som noko anna må opprette. Å handsame dei som eitt objekt er grunnen til at den opplagde reparasjonen med å laste modulen på nytt ikkje endrar noko som helst.

To objekt, to ulike eigarar

Ein kjernemodul og ein einingknute er uavhengige objekt med uavhengige livssyklusar. Innlasting av modulen registrerer ein drivar, og på eit system med devtmpfs ber kjernen om at den tilsvarande knuten blir oppretta. På eit system utan devtmpfs opprettar ingenting noko, og drivaren sit der utan nokon stig som peikar på han. Modulen kan vere lasta, sunn og heilt utilgjengeleg gjennom filsystemet i same augneblink.

Difor motseier ikkje feilteksten og modullista kvarandre. Klienten opnar ein stig, stigen finst ikkje, og kjernen returnerer ENOENT før tun-drivaren i det heile blir spurd. Å laste modulen på nytt kan ikkje reparere ein manglande stig, og å opprette stigen kan ikkje reparere ein manglande drivar.

lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts

devtmpfs kontra ein eksplisitt mknod

Vanlegvis opprettar to mekanismar den knuten, og å vite kven som skal vere ansvarleg fortel deg kva du skal reparere. devtmpfs lèt kjernen opprette einingknutar i ein montert instans, og udev legg eigarskap og rettar oppå. Ein eksplisitt mknod er den manuelle vegen for avbildingar og namnerom der ingen av dei køyrer ved oppstart.

Samanlikn resultat i staden for intensjonar. Viss devtmpfs er montert på /dev og knuten framleis manglar, er drivaren ikkje den du antek, eller noko fjerna knuten etter oppstart. Viss /dev er ein vanleg katalog i eit utpakka rootfs, finst det ingen automatisk mekanisme, og den som byggjer avbildinga må opprette knuten.

stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8

Der ingen av mekanismane køyrer, må knuten lagast for hand, og rekkjefølgja betyr noko. Opprett først overordna katalog, fordi mknod ikkje kan finne han opp, deretter teikneininga, deretter ein modus som gjer henne skrivbar berre for root. Last modulen på nytt før du opprettar knuten, og fjern berre ein eksisterande stig etter at ls har vist at det er ein katalog og ikkje ei eining.

sudo modprobe tun
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 600 /dev/net/tun
ls -l /dev/net/tun

Den raskaste skilnaden er typen som stat rapporterer, og ein katalog på den stigen er den vanlegaste overraskinga i minimale avbildingar. Ein velmeint mkdir i ein Dockerfile etterlèt nettopp det, og inga mengd modullasting erstattar ein katalog med ei teikneining. Major 10 med minor 200 er det registrerte paret for tun, uttrykt heksadesimalt som a og c8.

Fire spor, fire årsaker

Fire årsaker forklarer nesten alle tilfelle, og kvar etterlèt eit ulikt spor i loggane. Start med oppstartsmiljøet. Disklause avbildingar, innebygde kort og initramfs-fasar monterer ofte korkje devtmpfs eller ein udev-styrt /dev, så ingen prosess skriv nokon gong knuten. Les deretter monteringsvala på det som er vert for /dev, fordi nodev lèt stigen finnast medan han nektar å opne han, og ein bind-montering henta frå ein herda vert ber flagget utan å annonsere det. Ei skriveverna montering feilar tidlegare og høgare: mknod returnerer EROFS der, medan EPERM betyr at prosessen manglar evna og ikkje at filsystemet vernar seg sjølv. Til slutt treng ein containerruntime med sin eigen /dev tmpfs at knuten blir injisert i sitt eige namnerom, og eining-cgroupen hans må tillate major- og minor-paret.

Kontroller policylaget før du endrar rettar igjen. SELinux og AppArmor kan avvise ei opning som kvart filattributt tillèt, og den avvisinga viser seg i revisjonsloggen i staden for i utdataa til klienten. Ei rettsendring som aldri viser seg i ei avvising, er tid brukt på heilt feil lag.

sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5

Prov det med eit grensesnitt, ikkje ei liste

Ei vellukka liste provar at ein stig finst og ikkje noko meir. Opne ein sunn tun-knute for lesing, og kallet kjem tilbake med ein feil, fordi eininga ikkje har lesesemantikk og ikkje er ei vanleg fil. Den feilen er suksesssignalet her, og å kjenne han att hindrar deg i å jage han som ein feil.

head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state

Den avgjerande testen opprettar eit grensesnitt, fordi han prøver drivaren, knuten og privilegia dine i eitt trinn. Viss tillegginga lukkast og lenkja viser seg, verkar alle tre. Når han feilar, skil errno årsakene: ENOENT betyr at det ikkje finst nokon brukbar knute, EPERM peikar på evne, monteringsflagg eller policy, og EBUSY betyr at ein annan prosess alt eig grensesnittet.

sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun

Køyr den testen i den konteksten som faktisk feilar, fordi ei tenesteeining, ein container eller ein planlagd jobb kan bere eit anna evnesett enn innloggingsskalet ditt. Ein test som går gjennom i feil kontekst, provar ingenting om den som feilar.

Når eininga ikkje er problemet

Viss grensesnitttesten lukkast og klienten framleis feilar, er det gjenverande problemet profilen, tenestekonteksten eller ruta, og eininga er i orden. Det er augneblinken for å slutte å redigere einingknutar, fordi fleire endringar berre aukar avstanden til eit fungerande system.

Køyr dei same fem kontrollane kvar gong i staden for å finne opp ein ny: er modulen lasta utan ein konkurrerande modul, er stigen ei teikneining med rett major og minor, er monteringsvala reine, ber prosesskonteksten evna, og finst det ei policyavvising på tidspunktet for feilen. Ein feil som overlever alle fem, er ikkje eit einingproblem, uansett kva meldinga nemner.

Relaterte artiklar