/dev/net/tun chýba, hoci je tun načítaný: opravte uzol zariadenia
Načítaný modul tun nedokazuje, že uzol zariadenia existuje. Oddeľte ovládač od uzla, znova ho zostavte v poradí a overte rozhraním.
OpenVPN sa zastaví so sťažnosťou errno 2 na /dev/net/tun zatiaľ čo lsmod bez problémov vypisuje modul tun. Obe skutočnosti platia súčasne. Modul poskytuje ovládač a cesta, ktorú klient otvára, je uzol zariadenia, ktorý musí vytvoriť niečo iné. Považovať ich za jeden objekt je dôvod, prečo zjavná oprava v podobe opätovného načítania modulu nezmení vôbec nič.
Dva objekty, dvaja rôzni vlastníci
Modul jadra a uzol zariadenia sú nezávislé objekty s nezávislými životnými cyklami. Načítanie modulu zaregistruje ovládač a v systéme s devtmpfs jadro požiada o vytvorenie zodpovedajúceho uzla. V systéme bez devtmpfs nič nič nevytvára a ovládač tam zostáva bez cesty, ktorá by naň ukazovala. Modul môže byť načítaný, zdravý a zároveň úplne nedostupný cez súborový systém.
Preto si text chyby a výpis modulov neodporujú. Klient otvára cestu, cesta neexistuje a jadro vráti ENOENT skôr, než sa ovládač tun vôbec opýta. Opätovné načítanie modulu nemôže opraviť chýbajúcu cestu a vytvorenie cesty nemôže opraviť chýbajúci ovládač.
lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts
devtmpfs verzus explicitný mknod
Ten uzol zvyčajne vytvárajú dva mechanizmy a znalosť toho, ktorý má byť zodpovedný, vám povie, čo opraviť. devtmpfs necháva jadro vytvárať uzly zariadení v pripojenej inštancii a udev na ne navrchu aplikuje vlastníctvo a oprávnenia. Explicitný mknod je ručná cesta pre obrazy a menné priestory, kde pri boote nebeží ani jeden z nich.
Porovnávajte výsledky, nie úmysly. Ak je devtmpfs pripojený v /dev a uzol stále chýba, ovládač nie je ten, ktorý predpokladáte, alebo niečo uzol po boote odstránilo. Ak je /dev obyčajný adresár v rozbalenom rootfs, neexistuje žiadny automatický mechanizmus a ten, kto obraz stavia, musí uzol vytvoriť.
stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8
Tam, kde nebeží ani jeden mechanizmus, musí sa uzol vytvoriť ručne a na poradí záleží. Najprv vytvorte nadradený adresár, pretože mknod ho nedokáže vymyslieť, potom znakové zariadenie, potom režim, ktorý ho nechá zapisovateľný len pre root. Pred vytvorením uzla znova načítajte modul a existujúcu cestu odstraňujte len potom, čo ls ukázal, že ide o adresár a nie o zariadenie.
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
Typ, ktorý hlási stat je najrýchlejší rozlišovač a adresár na tejto ceste je najčastejšie prekvapenie v minimálnych obrazoch. Dobre mienený mkdir v Dockerfile zanechá presne to a žiadne načítanie modulov nenahradí adresár znakovým zariadením. Major 10 s minor 200 je registrovaná dvojica pre tun, vyjadrená hexadecimálne ako a a c8.
Štyri stopy, štyri príčiny
Štyri príčiny vysvetľujú takmer každý prípad a každá zanecháva v logoch inú stopu. Začnite u bootovacieho prostredia. Obrazy bez disku, vstavané dosky a fázy initramfs často nepripájajú ani devtmpfs, ani /devspravovaný udev, takže žiadny proces nikdy uzol nezapíše. Potom si prečítajte možnosti pripojenia toho, čo hostuje /dev, pretože nodev dovoľuje, aby cesta existovala, ale odmieta ju otvoriť, a bind mount prevzatý z očvrsnutého hostiteľa nesie túto príznak, bez toho aby sa ohlásil. Pripojenie iba na čítanie zlyháva skôr a hlasnejšie: mknod tam vracia EROFS, zatiaľ čo EPERM znamená, že procesu chýba schopnosť, a nie že sa súborový systém chráni. Nakoniec kontajnerový runtime s vlastným /dev tmpfs potrebuje uzol vložiť do svojho vlastného menného priestoru a jeho device cgroup musí povoliť dvojicu major a minor.
Pred ďalšou zmenou oprávnení skontrolujte vrstvu politiky. SELinux a AppArmor môžu odmietnuť otvorenie, ktoré všetky atribúty súboru povoľujú, a toto odmietnutie sa objaví v audítnom logu, nie vo výstupe klienta. Zmena oprávnení, ktorá sa nikdy neobjaví v odmietnutí, je čas strávený úplne na nesprávnej vrstve.
sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5
Dokážte to rozhraním, nie výpisom
Úspešný výpis dokazuje, že cesta existuje a nič viac. Otvorte zdravý uzol tun na čítanie a volanie sa vráti s chybou, pretože zariadenie nemá sémantiku čítania a nie je bežný súbor. Táto chyba je tu signálom úspechu a jej rozpoznanie vám zabráni hnať sa za ňou ako za poruchou.
head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state
Rozhodujúci test vytvorí rozhranie, pretože precvičí ovládač, uzol aj vaše oprávnenia v jedinom kroku. Ak pridanie uspeje a spoj sa objaví, všetky tri fungujú. Keď zlyhá, errno oddelí príčiny: ENOENT znamená, že nie je použiteľný uzol, EPERM ukazuje na schopnosť, príznaky pripojenia alebo politiku a EBUSY znamená, že rozhranie už vlastní iný proces.
sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun
Spustite tento test v kontexte, ktorý skutočne zlyháva, pretože service unit, kontajner alebo naplánovaná úloha môžu niesť inú sadu schopností než váš prihlasovací shell. Test, ktorý prejde v nesprávnom kontexte, nič nedokazuje o tom zlyhávajúcom.
Keď zariadenie nie je problém
Ak test rozhrania uspeje a klient stále zlyháva, zostávajúci problém je profil, kontext služby alebo trasa a zariadenie je v poriadku. To je okamih prestať upravovať uzly zariadení, pretože ďalšie zmeny len pridávajú vzdialenosť od funkčného systému.
Spúšťajte rovnakých päť kontrol zakaždým, namiesto vymýšľania novej: je modul načítaný bez konkurenčného modulu, je cesta znakovým zariadením so správnym major a minor, sú možnosti pripojenia čisté, nesie kontext procesu schopnosť a existuje odmietnutie politiky v časovej značke zlyhania. Porucha, ktorá prežije všetkých päť, nie je problém zariadenia, nech správa spomína čokoľvek.