/dev/net/tun липсва при зареден tun: поправете възела на устройството
Зареден модул tun не доказва, че възелът на устройството съществува. Отделете драйвера от възела, изградете го по ред и го проверете с интерфейс.
OpenVPN спира със съобщение errno 2 за /dev/net/tun докато lsmod спокойно изброява модула tun. И двата факта са верни едновременно. Модулът предоставя драйвер, а пътят, който клиентът отваря, е възел на устройство, който нещо друго трябва да създаде. Третирането им като един обект е причината очевидната поправка чрез презареждане на модула да не променя абсолютно нищо.
Два обекта, двама различни собственици
Модулът на ядрото и възелът на устройството са независими обекти с независими жизнени цикли. Зареждането на модула регистрира драйвер и в система с devtmpfs ядрото иска да бъде създаден съответният възел. В система без devtmpfs нищо не създава нищо и драйверът остава там без път, който да сочи към него. Модулът може да е зареден, здрав и напълно недостъпен през файловата система в един и същ момент.
Затова текстът на грешката и списъкът на модулите не си противоречат. Клиентът отваря път, пътят не съществува и ядрото връща ENOENT, преди драйверът tun изобщо да бъде потърсен. Презареждането на модула не може да поправи липсващ път, а създаването на пътя не може да поправи липсващ драйвер.
lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts
devtmpfs срещу явен mknod
Обикновено този възел се създава от два механизма и знанието кой от тях трябва да отговаря показва какво да поправите. devtmpfs кара ядрото да създава възли на устройства в монтиран екземпляр, а udev прилага собственик и права върху тях. Явният mknod е ръчният път за образи и пространства от имена, където нито един от тях не работи при зареждане.
Сравнявайте резултатите, а не намеренията. Ако devtmpfs е монтиран в /dev и възелът все още липсва, драйверът не е този, който предполагате, или нещо е премахнало възела след зареждането. Ако /dev е обикновена директория в разопакован rootfs, няма автоматичен механизъм и този, който изгражда образа, трябва да създаде възела.
stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8
Там, където не работи нито един механизъм, възелът трябва да се направи на ръка и редът е важен. Първо създайте родителската директория, защото mknod не може да я измисли, после символното устройство, после режим, който го оставя записваемо само за root. Презаредете модула, преди да създадете възела, и премахвайте съществуващ път само след като ls е показал, че това е директория, а не устройство.
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
Типът, който съобщава stat е най-бързият различител, а директория на този път е най-честата изненада в минималните образи. Добре измислен mkdir в Dockerfile оставя точно това и никакво зареждане на модули не заменя директория със символно устройство. Major 10 с minor 200 е регистрираната двойка за tun, изразена в шестнадесетично като a и c8.
Четири следи, четири причини
Четири причини обясняват почти всеки случай и всяка оставя различна следа в журналите. Започнете със средата за зареждане. Образиите без диск, вградените платки и етапите на initramfs често не монтират нито devtmpfs, нито управляван от udev /dev, така че нито един процес никога не записва възела. След това прочетете опциите за монтиране на това, което съдържа /dev, защото nodev позволява пътят да съществува, но отказва да го отвори, а bind монтиране, взето от укрепен хост, носи флага, без да се обявява. Монтирането само за четене се проваля по-рано и по-шумно: mknod връща там EROFS, докато EPERM означава, че на процеса липсва способност, а не че файловата система се защитава. И накрая, контейнерен runtime със свой /dev tmpfs се нуждае възелът да бъде инжектиран в собственото му пространство от имена, а неговата device cgroup трябва да разрешава двойката major и minor.
Проверете слоя на политиката, преди отново да променяте права. SELinux и AppArmor могат да откажат отваряне, което всеки файлов атрибут разрешава, и този отказ се появява в одиторския журнал, а не в изхода на клиента. Промяна на права, която никога не се появява в отказ, е време, изразходвано напълно в грешен слой.
sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5
Докажете го с интерфейс, не със списък
Успешният списък доказва, че път съществува и нищо повече. Отворете здрав възел tun за четене и извикването се връща с грешка, защото устройството няма семантика за четене и не е обикновен файл. Тази грешка е сигналът за успех тук и разпознаването ѝ ви пази да не я преследвате като дефект.
head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state
Решаващият тест създава интерфейс, защото упражнява драйвера, възела и вашите привилегии в една стъпка. Ако добавянето успее и връзката се появи, и трите работят. Когато се провали, errno разделя причините: ENOENT означава, че няма използваем възел, EPERM сочи към способност, флагове за монтиране или политика, а EBUSY означава, че друг процес вече притежава интерфейса.
sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun
Изпълнете този тест в контекста, който наистина се проваля, защото service unit, контейнер или планирана задача може да носи различен набор от способности от вашата входна обвивка. Тест, който минава в грешен контекст, не доказва нищо за провалящия се.
Когато устройството не е проблемът
Ако тестът на интерфейса успее, а клиентът все още се проваля, останалият проблем е профилът, контекстът на услугата или маршрутът и устройството е наред. Това е моментът да спрете да редактирате възли на устройства, защото допълнителните промени само добавят разстояние от работеща система.
Изпълнявайте същите пет проверки всеки път, вместо да измисляте нова: зареден ли е модулът без конкурентен модул, пътят символно устройство ли е с правилните major и minor, чисти ли са опциите за монтиране, носи ли контекстът на процеса способността и има ли отказ на политиката на времевата марка на отказа. Дефект, който оцелява след всичките пет, не е проблем на устройството, каквото и да споменава съобщението.