Ошибка /dev/net/tun: No such device на VPS
Ошибка /dev/net/tun: No such device обычно появляется в момент, когда OpenVPN, userspace-VPN, контейнер или другая сетевая программа пытается создать виртуальный TUN/TAP-интерфейс. Первое желание — найти команду, которая «создаст TUN». Именно здесь диагностика часто уходит не туда.
Проблема может находиться на разных уровнях: отсутствует файл устройства, ядро Linux не предоставляет TUN, контейнерная виртуализация не разрешает доступ к 10:200, процессу не хватает CAP_NET_ADMIN, systemd урезал capabilities или /dev/net/tun просто не передан внутрь Docker. Внешне несколько таких сценариев выглядят почти одинаково.
Поэтому рабочая последовательность другая: сначала проверяем само устройство, затем поддержку TUN в ядре, тип виртуализации, возможности процесса и ограничения сервиса. Только потом имеет смысл разбирать OpenVPN, WireGuard или Docker. Если пропустить один слой, можно несколько раз выполнить chmod и mknod, но так и не добраться до причины.

Что означает ошибка /dev/net/tun: No such device на VPS?
/dev/net/tun: No such device означает, что приложение не смогло получить рабочий TUN-интерфейс. Это не то же самое, что «файла /dev/net/tun нет». Файл может присутствовать, но ядро или окружение VPS не дают использовать стоящий за ним драйвер.
Похожая неисправность встречается под несколькими формулировками:
No such file or directory— путь/dev/net/tunдействительно отсутствует;No such device— файл устройства может существовать, но TUN-драйвер недоступен;Permission denied— доступ режут права файла или механизм безопасности;Operation not permitted— часто проблема уже в capabilities, cgroup, systemd или контейнерной политике;Module tun not found— модуль не найден как отдельный объект, но это ещё не доказывает отсутствие встроенного TUN;File descriptor in bad stateпослеcat /dev/net/tun— обычно не поломка, а признак того, что устройство удалось открыть.
Безопасная первая проверка ничего не меняет в системе:
ls -l /dev/net/tun
test -c /dev/net/tun && echo "TUN device exists"
cat /dev/net/tun
Если последняя команда отвечает:
cat: /dev/net/tun: File descriptor in bad state
запрос, как правило, дошёл до TUN-драйвера. Обычное чтение через cat для этого устройства не имеет смысла, поэтому такая ошибка сама по себе не означает неисправность.
mknod и chmod лучше не трогать.
Как проверить, существует ли /dev/net/tun и работает ли TUN?
Наличие пути /dev/net/tun ещё не означает, что приложение сможет создать через него интерфейс. Проверяем отдельно тип файла и отдельно реальную работу TUN.
Начните с каталога и файла устройства:
ls -ld /dev/net
ls -l /dev/net/tun
stat /dev/net/tun
TUN/TAP в Linux использует символьное устройство с major/minor 10, 200. В начале строки ls -l должна стоять буква c:
crw-rw-rw- 1 root root 10, 200 ... /dev/net/tun
Тип можно проверить и без разбора длинного вывода:
test -c /dev/net/tun && echo "TUN device exists"
Если нужно увидеть major/minor в шестнадцатеричном виде:
stat -c '%F %t:%T' /dev/net/tun
Для TUN ожидается символьное устройство с major/minor, соответствующими 10:200.
Как проверить создание настоящего TUN-интерфейса
При наличии CAP_NET_ADMIN можно провести уже не файловый, а сетевой тест:
ip tuntap add dev tun-test mode tun
ip link show tun-test
Если интерфейс появился, базовая связка «ядро + /dev/net/tun + capability» работает. После проверки интерфейс удаляем:
ip link delete tun-test
Другой типичный сценарий: файл существует, cat /dev/net/tun даёт ожидаемый File descriptor in bad state, но ip tuntap add возвращает:
RTNETLINK answers: Operation not permitted
Здесь пересоздавать /dev/net/tun уже бессмысленно. Устройство найдено. Теперь проверяем CAP_NET_ADMIN, systemd, cgroup и виртуализацию.
Как проверить поддержку TUN в ядре VPS?
Если /dev/net/tun отсутствует или возвращает No such device, нужно проверить сам драйвер TUN. Он может быть встроен в ядро, собран отдельным модулем либо отсутствовать в текущей конфигурации.
Что показывают modprobe, lsmod и modinfo
На полноценной виртуальной машине начните с:
modprobe -n -v tun
modinfo tun
lsmod | grep '^tun'
modprobe -n -v tun выполняет пробный запуск без фактической загрузки и показывает, что попытался бы сделать modprobe. modinfo tun проверяет наличие файла модуля и его метаданных. lsmod показывает только реально загруженные модули.
Здесь есть ловушка: пустой lsmod | grep tun не означает, что TUN отсутствует. При CONFIG_TUN=y драйвер встроен непосредственно в ядро и отдельной строкой в lsmod не появится.
Как читать CONFIG_TUN
Если конфигурация текущего ядра доступна:
grep CONFIG_TUN /boot/config-$(uname -r)
или:
zgrep CONFIG_TUN /proc/config.gz
Интерпретация результатов:
| Результат | Что это означает | Что делать дальше |
|---|---|---|
CONFIG_TUN=y |
TUN встроен в ядро | Проверять /dev/net/tun и права окружения |
CONFIG_TUN=m и modinfo tun работает |
TUN собран модулем и файл модуля доступен | Загрузить modprobe tun и проверить устройство |
CONFIG_TUN=m, но modinfo tun не работает |
Конфигурация ожидает модуль, но его файл недоступен | Проверить установленные модули для текущего ядра |
# CONFIG_TUN is not set |
Текущее ядро собрано без TUN | Нужно ядро с поддержкой TUN |
| Файл конфигурации не найден | Конфигурация ядра просто недоступна этим способом | Не делать вывод о TUN только по отсутствию файла |
Отдельный случай — CONFIG_TUN=m, но:
modinfo: ERROR: Module tun not found.
На полноценной VM это может означать, что для текущего ядра отсутствует пакет с модулями или содержимое /lib/modules/$(uname -r) не соответствует запущенному kernel. Сначала сравните:
uname -r
ls /lib/modules
Если версия запущенного ядра не имеет соответствующего каталога в /lib/modules, modprobe физически неоткуда взять файл модуля.
В OpenVZ, Virtuozzo или LXC логика другая: контейнер использует ядро хоста, поэтому пользователь внутри VPS не может загрузить отсутствующий модуль в физическое ядро. Там дальше проверяем уже не пакеты гостевой ОС, а тип виртуализации.
Может ли тип виртуализации VPS запрещать TUN/TAP?
Если modprobe tun запускается от root и всё равно ни на что не влияет, первым делом посмотрите тип виртуализации. На KVM ядро принадлежит гостевой системе. На OpenVZ и LXC — хосту. Это принципиально разные ситуации.
Определить окружение можно так:
systemd-detect-virt
hostnamectl
При установленной утилите:
virt-what
Что происходит на KVM VPS
KVM предоставляет полноценную виртуальную машину с собственным гостевым ядром. Владелец VPS обычно может самостоятельно проверить kernel config, загрузить модуль, восстановить device node и управлять capabilities процессов.
Для KVM рабочая последовательность выглядит так:
uname -r
modprobe tun
ls -l /dev/net/tun
ip tuntap add dev tun-test mode tun
Если один из этапов ломается, причина обычно находится внутри самой VM: отсутствуют модули для ядра, нет устройства, не хватает capability или сервис запущен с дополнительными ограничениями.
Почему root в OpenVZ или LXC не равен root хоста
OpenVZ, Virtuozzo и LXC используют общее ядро физического сервера. Контейнер не может загрузить в него отсутствующий TUN-драйвер и не может отменить device policy, заданную владельцем хоста.
TUN использует устройство 10:200. Хост должен разрешить контейнеру доступ к нему. Даже если /dev/net/tun вручную создан внутри VPS, cgroup или настройки контейнера могут запретить его открытие или последующий ioctl.
Обычно картина выглядит так: файл есть, права кажутся нормальными, команда запускается от root, но ip tuntap отвечает Operation not permitted. На этом месте многие начинают крутить chmod. Зря. Если ограничение поставлено уровнем выше, файловые права его не снимут.
| Среда | Собственное гостевое ядро | Можно загрузить tun из VPS | Кто контролирует /dev/net/tun | Типичный следующий шаг |
|---|---|---|---|---|
| KVM | Да | Обычно да | Владелец VPS | Проверить kernel, устройство и capabilities |
| OpenVZ / Virtuozzo | Нет | Нет | Хост / провайдер | Уточнить, разрешён ли TUN/TAP |
| LXC | Нет | Обычно нет | Хост и cgroup | Проверить device policy контейнера |
| Docker внутри VPS | Использует ядро VPS | Отдельного ядра нет | VPS + Docker | Проверить device mapping и NET_ADMIN |
При этом OpenVZ или LXC не означают автоматический запрет VPN. Если провайдер разрешил TUN/TAP и нужные сетевые возможности контейнера, OpenVPN может работать нормально. Вывод делаем по фактической конфигурации, а не по названию технологии.
Что делать, если /dev/net/tun отсутствует, но ядро поддерживает TUN?
До mknod стоит дойти только после проверки ядра. Иначе можно создать файл устройства, за которым нет рабочего драйвера или к которому контейнер всё равно не имеет доступа.
Перед созданием device node должны быть подтверждены три вещи:
- TUN присутствует в ядре или доступен как модуль;
/dev/net/tunдействительно отсутствует;- виртуализация не запрещает работу с устройством на уровне хоста.
Если каталога нет:
mkdir -p /dev/net
Затем создаётся character device с major/minor 10, 200:
mknod /dev/net/tun c 10 200
ls -l /dev/net/tun
stat -c '%F %t:%T' /dev/net/tun
После этого повторите базовый тест:
cat /dev/net/tun
Если получено:
cat: /dev/net/tun: File descriptor in bad state
файл уже связан с работающим TUN-драйвером. Дальше проверяем создание интерфейса:
ip tuntap add dev tun-test mode tun
ip link show tun-test
ip link delete tun-test
Если mknod сам отвечает:
mknod: /dev/net/tun: Operation not permitted
это уже не проблема отсутствующего файла. Среда запрещает создавать device node. В контейнерном VPS такой запрет часто устанавливается на стороне хоста.
chmod 666 /dev/net/tun как универсальное исправление. Права файла не добавляют драйвер в ядро, не выдают CAP_NET_ADMIN и не снимают cgroup-ограничения.
Почему /dev/net/tun снова исчезает после перезагрузки
Если вручную созданное устройство работает до reboot, а затем пропадает, проблема уже в том, как система формирует /dev. На обычной VM устройство обычно создаёт userspace-механизм вроде udev; в контейнерной среде содержимое /dev может формироваться самим runtime или хостом.
Сначала проверьте факт:
ls -l /dev/net
ls -l /dev/net/tun
Если после каждой перезагрузки приходится снова выполнять mknod, постоянное ручное создание устройства — не решение. Нужно искать, кто управляет /dev именно в этой среде: гостевая система, LXC/OpenVZ-конфигурация или контейнерный runtime.
Почему chmod, mknod и root не исправляют Operation not permitted?
Файл может иметь права 0666, команда может запускаться от root, но ядро всё равно отвечает EPERM. Значит, проблема уже не в обычных Unix-правах.
| Сообщение | Что оно обычно означает | Что проверить первым | Что не делать сразу |
|---|---|---|---|
No such file or directory |
Нет пути или device node | ls -l /dev/net/tun |
Не менять capabilities вслепую |
No such device |
Драйвер или устройство недоступны | CONFIG_TUN, kernel, виртуализацию |
Не лечить проблему только chmod |
Permission denied |
Права файла или security policy | Owner, group, mode, SELinux/AppArmor | Не пересоздавать устройство без проверки |
Operation not permitted |
Capability, cgroup, systemd или контейнерное ограничение | CAP_NET_ADMIN, сервис и виртуализацию |
Не считать root обходом всех ограничений |
Module tun not found |
Файл модуля недоступен либо драйвер встроен | CONFIG_TUN, modinfo |
Не делать вывод только по одной строке |
File descriptor in bad state |
При тесте через cat устройство обычно открылось | Перейти к ip tuntap |
Не считать это поломкой TUN |
Для текущего shell можно посмотреть capabilities:
capsh --print
Для бинарника, которому назначались file capabilities:
getcap "$(command -v openvpn)"
Но здесь есть ограничение: getcap показывает capabilities файла, а не окончательный набор, который реально получит процесс после запуска через systemd или контейнерный runtime. Сервис может стартовать с более жёсткой политикой.
Если после mknod сообщение No such device сменилось на Operation not permitted, это не обязательно ухудшение. Первый слой уже пройден: device node существует. Теперь система показывает следующую точку отказа.
Это другой уровень проблемы.
Почему TUN работает вручную, но не работает у systemd-сервиса?
Если ip tuntap add успешно выполняется из root-shell, но OpenVPN или другое приложение из systemd получает Operation not permitted, ядро и /dev/net/tun, скорее всего, уже работают. Разница находится в окружении процесса.
Сначала посмотрите реальный unit:
systemctl cat <service-name>
Затем проверьте параметры, которые могут ограничить доступ:
systemctl show <service-name> -p User
systemctl show <service-name> -p CapabilityBoundingSet
systemctl show <service-name> -p AmbientCapabilities
systemctl show <service-name> -p PrivateDevices
systemctl show <service-name> -p DevicePolicy
systemctl show <service-name> -p DeviceAllow
Что искать в выводе
CapabilityBoundingSet задаёт верхнюю границу capabilities, которые процесс вообще может получить. Если из набора исключён CAP_NET_ADMIN, приложение не сможет создать или перенастроить сетевой интерфейс только потому, что запущено от root.
AmbientCapabilities может использоваться для передачи capabilities непривилегированному процессу. Само отсутствие CAP_NET_ADMIN в этом поле не всегда ошибка — всё зависит от способа запуска и остальных параметров unit, — но этот вывод помогает понять реальную модель привилегий.
PrivateDevices=yes создаёт для сервиса отдельное представление /dev. В таком режиме привычное устройство может оказаться недоступным процессу, хотя из обычного shell оно видно.
DevicePolicy и DeviceAllow ограничивают доступ сервиса к устройствам. Если unit специально зажат, ручной тест от root и запуск демона будут вести себя по-разному.
Характерный сценарий выглядит так:
root shell:
ip tuntap add dev tun-test mode tun
# успешно
systemd service:
Operation not permitted
До ядра здесь уже докапываться не нужно. Оно доказало свою работоспособность ручным тестом. Сравниваем окружение процесса и ограничения unit.
mknod. Сразу переходите к systemd, пользователю сервиса и capabilities.
Могут ли SELinux или AppArmor блокировать /dev/net/tun?
Да, механизм обязательного контроля доступа может заблокировать операцию даже тогда, когда Unix-права на файл выглядят нормально. Но обвинять SELinux или AppArmor без логов тоже не стоит. Этот слой нужно подтвердить.
Как проверить SELinux
Сначала посмотрите режим:
getenforce
Если SELinux включён, ищите отказы в журнале. В зависимости от системы полезны сообщения AVC:
journalctl -b | grep -i 'avc\|selinux'
Если в момент запуска приложения появляется запись с отказом для нужного процесса или доступа к устройству, это уже предметная зацепка. Если журнал чистый, переключать SELinux «на всякий случай» не нужно.
Как проверить AppArmor
Состояние профилей:
aa-status
Ошибки можно искать в системном журнале:
journalctl -b | grep -i apparmor
Сильный признак security-проблемы — ситуация, когда root-shell успешно создаёт TUN, а конкретный ограниченный процесс стабильно получает отказ, и одновременно в журнале появляется соответствующее deny-сообщение.
Здесь важна дисциплина диагностики. Не выключаем механизм безопасности первым движением. Сначала доказываем, что блокировка действительно идёт от него.
Как через strace увидеть, где именно ломается TUN?
strace помогает отделить две разные проблемы: приложение не может открыть /dev/net/tun вообще или открывает его успешно, но получает ошибку на следующей операции с интерфейсом.
Для TUN особенно интересны системные вызовы открытия файла и ioctl. Общая форма:
strace -f -e trace=openat,ioctl <command>
Для уже известной команды OpenVPN или другого процесса подставляется его реальный запуск. В длинном выводе ищем /dev/net/tun и последующий ioctl.
Если устройство вообще не найдено
Картина будет похожа на:
openat(..., "/dev/net/tun", ...) = -1 ENOENT (No such file or directory)
Здесь приложение не дошло ни до capabilities, ни до создания интерфейса. Файла устройства нет в его namespace.
Если файл открыт, но операция запрещена
Другой сценарий:
openat(..., "/dev/net/tun", ...) = 3
ioctl(3, TUNSETIFF, ...) = -1 EPERM (Operation not permitted)
Это принципиально другой результат. /dev/net/tun найден и открыт, а отказ приходит уже на этапе настройки TUN-интерфейса. Здесь файловые права часто уже не главное. Проверяем CAP_NET_ADMIN, systemd, cgroup, контейнер и security policy.
Если вместо EPERM виден другой errno, ориентируемся на него. Сила strace как раз в том, что он показывает не предположение по тексту приложения, а конкретный системный вызов, который вернул ошибку.
| Проверка | Нормальный результат | Проблемный результат | Куда идти дальше |
|---|---|---|---|
ls -l /dev/net/tun |
Character device 10,200 | Файла нет | Ядро, /dev, виртуализация |
cat /dev/net/tun |
File descriptor in bad state |
No such device |
Kernel и host restrictions |
modprobe -n -v tun |
Модуль доступен либо не требуется | Module not found | CONFIG_TUN, /lib/modules |
ip tuntap add |
Интерфейс создан | EPERM | CAP_NET_ADMIN, systemd, cgroup |
systemd-detect-virt |
KVM/ожидаемая среда | OpenVZ/LXC | Проверить ограничения хоста |
strace |
open + успешный ioctl | ENOENT/ENODEV/EACCES/EPERM | Следовать конкретному errno |
Как отличить проблему TUN от ошибки OpenVPN, WireGuard или Docker?
Упоминание /dev/net/tun рядом со словом VPN ещё не означает одинаковую причину. OpenVPN, kernel WireGuard, userspace WireGuard и Docker используют сетевые возможности по-разному.
OpenVPN: сначала TUN, потом TLS и маршруты
OpenVPN на Linux обычно создаёт интерфейс TUN или TAP. Если системная проверка /dev/net/tun не проходит, сертификаты, маршруты и DNS пока не имеют отношения к первой ошибке.
Проверьте конфигурацию:
dev tun
или, если действительно нужен TAP:
dev tap
Для systemd-запуска полезно посмотреть журнал конкретного сервиса. Если имя unit неизвестно, сначала найдите его, а затем используйте journalctl -u. Для общей первичной выборки можно начать с:
journalctl -b | grep -i openvpn
После исправления TUN OpenVPN может упасть уже на другой ошибке: TLS, маршрутизации, конфигурации сертификата. Это нормально. Просто первый слой диагностики пройден.
WireGuard: TUN может быть вообще ни при чём
Нативный WireGuard в Linux создаёт интерфейс собственного типа и обычно не использует /dev/net/tun так, как OpenVPN. Поэтому для kernel WireGuard полезнее проверить возможность создать сам WireGuard-интерфейс:
ip link add dev wg-test type wireguard
Если команда сработала:
ip link show wg-test
ip link delete wg-test
Если вместо этого получено:
RTNETLINK answers: Operation not supported
это указывает уже на отсутствие поддержки WireGuard в текущем kernel или окружении. /dev/net/tun здесь не главный подозреваемый.
Исключение — userspace-реализации, например wireguard-go, и приложения, которые используют WireGuard как транспорт, а пользовательский сетевой интерфейс строят через TUN. Для них /dev/net/tun действительно может понадобиться.
Docker: устройство есть на VPS, но контейнер его не видит
Если приложение запускается в Docker, всегда проверяем два слоя. Сначала хостовую VPS:
ls -l /dev/net/tun
Затем контейнер:
docker exec <container> ls -l /dev/net/tun
На VPS устройство может работать, а внутри контейнера его не будет. Значит, kernel здесь ни при чём.
При запуске контейнеру может понадобиться:
--device=/dev/net/tun
--cap-add=NET_ADMIN
Для существующего контейнера полезно посмотреть конфигурацию:
docker inspect <container>
В выводе интересуют настройки устройств, дополнительные capabilities и режим Privileged. Не нужно автоматически включать privileged-режим только ради диагностики: сначала проверьте, передан ли конкретный device и добавлен ли NET_ADMIN.
В Docker Compose тем же задачам соответствуют devices и cap_add.
Что меняется в rootless-контейнере
Rootless Docker или другой rootless-runtime дополнительно ограничивает работу с сетевыми устройствами и capabilities. «Root внутри контейнера» в таком случае тем более не равен root хостовой системы.
Если обычный rootful-контейнер с переданным /dev/net/tun работает, а rootless-вариант нет, нужно анализировать модель привилегий самого runtime. Повторный chmod на хосте обычно не решает такую разницу.
Когда /dev/net/tun можно исправить самостоятельно, а когда нужен провайдер или KVM?
В какой-то момент команды внутри VPS заканчиваются. Если TUN режет хост OpenVZ/LXC, исправлять этот уровень из гостевой системы уже нечем — нужен провайдер.
Сценарий 1: /dev/net/tun отсутствует
- Проверить поддержку TUN в kernel.
- Если TUN есть, определить тип виртуализации.
- На KVM проверить создание device node и работу
udev. - На OpenVZ/LXC уточнить у провайдера доступ к TUN/TAP и device
10:200.
Сценарий 2: /dev/net/tun существует и cat отвечает File descriptor in bad state
- Выполнить
ip tuntap add. - Если интерфейс создаётся — базовый TUN работает.
- Если приходит EPERM — проверить
CAP_NET_ADMIN, systemd, cgroup и security policy.
Сценарий 3: вручную всё работает, сервис падает
- Не возвращаться к
mknod. - Проверить пользователя systemd-сервиса.
- Проверить
CapabilityBoundingSet,AmbientCapabilities,PrivateDevices,DevicePolicy. - Посмотреть журнал SELinux/AppArmor, если они используются.
Сценарий 4: VPS работает, Docker-контейнер нет
- Сравнить наличие
/dev/net/tunна VPS и внутри контейнера. - Проверить передачу устройства.
- Проверить
NET_ADMIN. - Учитывать rootless-режим.
Самостоятельное исправление обычно возможно, если:
- используется KVM или другая полноценная VM;
- ядро содержит TUN;
- проблема только в device node;
- не хватает capability процесса;
- systemd ограничивает конкретный сервис;
- Docker-контейнеру не передано устройство.
Провайдер нужен, если:
- OpenVZ/Virtuozzo/LXC не получает доступ к TUN;
- контейнеру запрещено устройство
10:200; mknodблокируется host policy;- нужный модуль должен загружаться на физическом узле;
- ограничения контейнера нельзя изменить из VPS.
Переход на KVM имеет смысл, если приложению нужен независимый контроль ядра, kernel modules, network namespaces или контейнеры с расширенными сетевыми возможностями, а текущая контейнерная платформа их не предоставляет. Но сам факт OpenVZ/LXC ещё не означает обязательную миграцию: при разрешённом TUN OpenVPN способен работать и там.
Минимальный набор безопасных проверок
Если нужно собрать картину одним проходом без изменения конфигурации, начните с read-only команд:
uname -r
systemd-detect-virt
ls -ld /dev/net
ls -l /dev/net/tun
stat /dev/net/tun
cat /dev/net/tun
modprobe -n -v tun
modinfo tun
grep CONFIG_TUN /boot/config-$(uname -r) 2>/dev/null
capsh --print
Если приложение запускается из systemd, добавьте:
systemctl cat <service-name>
systemctl show <service-name> -p User
systemctl show <service-name> -p CapabilityBoundingSet
systemctl show <service-name> -p AmbientCapabilities
systemctl show <service-name> -p PrivateDevices
systemctl show <service-name> -p DevicePolicy
systemctl show <service-name> -p DeviceAllow
Для обращения в поддержку полезно приложить:
systemd-detect-virt
uname -r
ls -l /dev/net/tun
cat /dev/net/tun
ip tuntap add dev tun-test mode tun
И сформулировать вопрос конкретно: поддерживает ли этот VPS TUN/TAP и разрешено ли окружению устройство /dev/net/tun с major/minor 10:200.
Диагностика TUN за 10 минут
- Зафиксируйте точный текст ошибки приложения.
- Проверьте
/dev/net/tunчерезls,statиcat. - Определите виртуализацию через
systemd-detect-virt. - Проверьте
CONFIG_TUNи доступность модуля. - На полноценной VM протестируйте временный интерфейс через
ip tuntap. - При EPERM проверьте
CAP_NET_ADMIN. - Если вручную всё работает, изучите ограничения systemd-сервиса.
- При подозрении на security policy проверьте SELinux/AppArmor и журналы.
- Если причина всё ещё не ясна, посмотрите
openatиioctlчерезstrace. - Для Docker повторите проверку отдельно внутри контейнера.
- Удалите временные тестовые интерфейсы после диагностики.
- Если ограничение находится на стороне OpenVZ/LXC-хоста, передайте результаты провайдеру.
Главный критерий простой: определите конкретный уровень, на котором возникает отказ. Если /dev/net/tun не открывается — смотрим устройство и namespace. Если файл открывается, но TUNSETIFF получает EPERM — смотрим capabilities и ограничения процесса. Если всё работает вручную, но ломается у сервиса — смотрим systemd и security policy. А если доступ к TUN ограничен самим контейнерным хостом, дальнейшие chmod и mknod внутри VPS уже ничего не изменят.


