/dev/net/tun trūksta, nors tun įkeltas: sutaisykite įrenginio mazgą
Įkeltas tun modulis neįrodo, kad įrenginio mazgas egzistuoja. Atskirkite tvarkyklę nuo mazgo, atkurkite jį iš eilės ir patikrinkite sąsaja.
OpenVPN sustoja su errno 2 skundu dėl /dev/net/tun tuo tarpu lsmod ramiai išvardija tun modulį. Abu faktai teisingi tuo pačiu metu. Modulis suteikia tvarkyklę, o kelias, kurį atidaro klientas, yra įrenginio mazgas, kurį turi sukurti kažkas kitas. Traktuoti juos kaip vieną objektą yra priežastis, kodėl akivaizdus taisymas perkraunant modulį nieko visiškai nekeičia.
Du objektai, du skirtingi savininkai
Branduolio modulis ir įrenginio mazgas yra nepriklausomi objektai su nepriklausomais gyvavimo ciklais. Modulio įkėlimas registruoja tvarkyklę, o sistemoje su devtmpfs branduolys prašo sukurti atitinkamą mazgą. Sistemoje be devtmpfs niekas nieko nesukuria, o tvarkyklė sėdi ten be jokio kelio, rodančio į ją. Modulis gali būti įkeltas, sveikas ir visiškai nepasiekiamas per failų sistemą tuo pačiu metu.
Štai kodėl klaidos tekstas ir modulių sąrašas neprieštarauja vienas kitam. Klientas atidaro kelią, kelio nėra, o branduolys grąžina ENOENT dar prieš tai, kai tun tvarkyklės apskritai paklausiama. Modulio perkrovimas negali sutaisyti trūkstamo kelio, o kelio sukūrimas negali sutaisyti trūkstamos tvarkyklės.
lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts
devtmpfs prieš aiškų mknod
Paprastai tą mazgą sukuria du mechanizmai, o žinojimas, kuris turėtų būti atsakingas, pasako, ką taisyti. devtmpfs leidžia branduoliui kurti įrenginių mazgus prijungtame egzemplioriuje, o udev taiko jiems nuosavybę ir teises. Aiškus mknod yra rankinis kelias atvaizdams ir vardų erdvėms, kuriose nė vienas jų neveikia įkrovimo metu.
Palyginkite rezultatus, o ne ketinimus. Jei devtmpfs prijungtas prie /dev ir mazgo vis dar nėra, tvarkyklė ne ta, kurią manote, arba kažkas pašalino mazgą po įkrovimo. Jei /dev yra paprastas katalogas išpakuotame rootfs, automatinio mechanizmo nėra ir tas, kas kuria atvaizdą, turi sukurti mazgą.
stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8
Ten, kur neveikia nė vienas mechanizmas, mazgą reikia padaryti rankiniu būdu, ir tvarka svarbi. Pirmiausia sukurkite tėvinį katalogą, nes mknod negali jo išgalvoti, tada ženklelio įrenginį, tada režimą, kuris palieka jį rašomą tik root. Perkraukite modulį prieš kurdami mazgą, o esamą kelią pašalinkite tik po to, kai ls parodė, kad tai katalogas, o ne įrenginys.
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
Greičiausias skirtukas yra tipas, kurį praneša stat ir katalogas tame kelyje yra dažniausia staigmena minimaliuose atvaizduose. Geranoriškas mkdir Dockerfile faile palieka būtent tai, ir joks modulių įkėlimo kiekis nepakeičia katalogo ženklelio įrenginiu. Major 10 su minor 200 yra registruota tun pora, išreikšta šešioliktaine kaip a ir c8.
Keturi pėdsakai, keturios priežastys
Keturios priežastys paaiškina beveik kiekvieną atvejį, ir kiekviena palieka skirtingą pėdsaką žurnaluose. Pradėkite nuo įkrovimo aplinkos. Be disko atvaizdai, įterptos plokštės ir initramfs etapai dažnai neprijungia nei devtmpfs, nei udev valdomo /dev, todėl joks procesas niekada nerašo mazgo. Tada perskaitykite prijungimo parinktis tame, kas talpina /dev, nes nodev leidžia keliui egzistuoti, bet atsisako jį atidaryti, o bind prijungimas, paimtas iš sukietinto šeimininko, neša šią vėliavą nesiskelbdamas. Tik skaitymui skirta prijungimas nepavyksta anksčiau ir garsiau: mknod ten grąžina EROFS, o EPERM reiškia, kad procesui trūksta gebėjimo, o ne kad failų sistema saugo save. Galiausiai konteinerių runtime su savo /dev tmpfs reikalauja, kad mazgas būtų įšvirkštas į jo paties vardų erdvę, o jo įrenginių cgroup turi leisti major ir minor porą.
Patikrinkite politikos sluoksnį prieš vėl keisdami teises. SELinux ir AppArmor gali atmesti atidarymą, kurį leidžia kiekvienas failo atributas, ir tas atmetimas pasirodo audito žurnale, o ne kliento išvestyje. Teisių pakeitimas, kuris niekada nepasireiškia atmetime, yra visiškai netinkamam sluoksniui skirtas laikas.
sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5
Įrodykite tai sąsaja, o ne sąrašu
Sėkmingas sąrašas įrodo, kad kelias egzistuoja ir nieko daugiau. Atidarykite sveiką tun mazgą skaitymui, ir kvietimas grįžta su klaida, nes įrenginys neturi skaitymo semantikos ir nėra įprastas failas. Ta klaida čia yra sėkmės signalas, ir jos atpažinimas neleidžia jos persekioti kaip gedimo.
head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state
Lemiamas testas sukuria sąsają, nes vienu žingsniu išbando tvarkyklę, mazgą ir jūsų privilegijas. Jei pridėjimas pavyksta ir nuoroda atsiranda, visi trys veikia. Kai nepavyksta, errno atskiria priežastis: ENOENT reiškia, kad nėra tinkamo mazgo, EPERM nurodo gebėjimą, prijungimo vėliavas ar politiką, o EBUSY reiškia, kad sąsają jau turi kitas procesas.
sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun
Vykdykite tą testą tame kontekste, kuris tikrai nepavyksta, nes paslaugos vienetas, konteineris ar suplanuota užduotis gali turėti kitokį gebėjimų rinkinį nei jūsų prisijungimo shell. Testas, kuris praeina netinkamame kontekste, nieko neįrodo apie nepavykstantį.
Kai įrenginys nėra problema
Jei sąsajos testas pavyksta, o klientas vis dar nepavyksta, likusi problema yra profilis, paslaugos kontekstas arba maršrutas, ir įrenginys tvarkingas. Tai momentas nustoti redaguoti įrenginių mazgus, nes tolesni pakeitimai tik didina atstumą nuo veikiančios sistemos.
Kiekvieną kartą vykdykite tuos pačius penkis patikrinimus, o ne išgalvokite naują: ar modulis įkeltas be konkuruojančio modulio, ar kelias yra ženklelio įrenginys su teisingu major ir minor, ar prijungimo parinktys švarios, ar proceso kontekstas turi gebėjimą, ir ar gedimo laiko žymoje yra politikos atmetimas. Gedimas, išgyvenęs visus penkis, nėra įrenginio problema, ką bebeminėtų pranešimas.