/dev/net/tun жоқ, бірақ tun жүктелген: құрылғы түйінін түзетіңіз
Жүктелген tun модулі құрылғы түйінінің бар екенін дәлелдемейді. Драйверді түйіннен бөліңіз, оны ретімен қайта құрыңыз және интерфейспен тексеріңіз.
OpenVPN errno 2 шағымымен тоқтайды, ол /dev/net/tun туралы, ал lsmod tun модулін жайбарақат тізіп тұр. Екі факт бір уақытта ақиқат. Модуль драйвер береді, ал клиент ашатын жол — басқа бір нәрсе жасауы керек құрылғы түйіні. Екеуін бір нысан деп қарау — модульді қайта жүктеу сияқты көзге түсер түзетудің неге ештеңе өзгертпейтінінің себебі.
Екі нысан, екі түрлі иесі
Ядро модулі мен құрылғы түйіні — тәуелсіз өмірлік циклдері бар тәуелсіз нысандар. Модульді жүктеу драйверді тіркейді, ал devtmpfs бар жүйеде ядро сәйкес түйінді жасауды сұрайды. devtmpfs жоқ жүйеде ештеңе ештеңе жасамайды, ал драйвер оған нұсқайтын ешбір жолсыз сол жерде отырады. Модуль бір мезгілде жүктелген, сау және файлдық жүйе арқылы мүлдем қолжетімсіз болуы мүмкін.
Сондықтан қате мәтіні мен модуль тізімі бір-біріне қайшы келмейді. Клиент жолды ашады, жол жоқ, және ядро tun драйверінен сұралмай тұрып ENOENT қайтарады. Модульді қайта жүктеу жоғалған жолды түзете алмайды, ал жолды жасау жоғалған драйверді түзете алмайды.
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 процесте қабілет жоқ екенін білдіреді, файлдық жүйе өзін қорғап жатқанын емес. Соңында, өз /dev tmpfs-і бар контейнер runtime-ы түйінді өз атаулар кеңістігіне енгізуді талап етеді, және оның құрылғы 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
Бұл тесті шынымен сәтсіз болатын контексте іске қосыңыз, өйткені қызмет бірлігі, контейнер немесе жоспарланған тапсырма сіздің кіру shell-іңізден өзгеше қабілеттер жиынтығын алып жүруі мүмкін. Дұрыс емес контексте өткен тест сәтсіз болатын контекст туралы ештеңе дәлелдемейді.
Құрылғы мәселе болмаған кезде
Егер интерфейс тесті сәтті болып, клиент әлі сәтсіз болса, қалған мәселе — профиль, қызмет контексті немесе маршрут, ал құрылғы дұрыс. Бұл құрылғы түйіндерін өңдеуді тоқтататын сәт, өйткені одан әрі өзгерістер жұмыс істеп тұрған жүйеден қашықтықты ғана арттырады.
Әр жолы жаңасын ойлап таппай, сол бес тексеруді орындаңыз: модуль бәсекелес модульсіз жүктелді ме, жол дұрыс major мен minor-ы бар таңба құрылғысы ма, қондыру параметрлері таза ма, процесс контексті қабілетті алып жүр ме, және сәтсіздік уақытында саясат бас тартуы бар ма. Бесеуінен де аман өткен ақау — құрылғы мәселесі емес, хабарлама не айтса да.