Странное поведение modules-load и модуля tun в Linux — причины и как исправить

Требуется, чтобы модуль tun загружался автоматически при старте системы, но этого не происходит: приходится вручную запускать modprobe. Инструкция дистрибутива (форк LFS) советует создать файл tun.conf в /etc/modules-load.d/ с содержимым "tun", но это не помогает. Единственное, что срабатывает — запись модуля через alias: devname:net/tun. Почему так происходит и что проверить/сделать — разберём по шагам.

Почему alias (devname:net/tun) работает, а обычное имя модуля — нет

  • kmod использует два быстрых индекса для поиска модулей:
    • /lib/modules/$(uname -r)/modules.dep.bin — для поиска по имени модуля (tun → полный путь к tun.ko);
    • /lib/modules/$(uname -r)/modules.alias.bin — для поиска по alias (например devname:net/tun).
  • Если поиск по alias даёт результат, а поиск по имени — нет, это прямо указывает на проблему с modules.dep.bin (он может быть повреждён, устарел или отсутствует).
  • Механизм "static nodes": при загрузке системы должна быть вызвана команда kmod static-nodes, которая читает devname:… алиасы и создаёт соответствующие статические /dev-узлы (mknod), чтобы при первом обращении к /dev/net/tun kmod автоматически подгрузил модуль по alias (char-major-* alias). Если static-nodes не отработал правильно, автозагрузка по открытию устройства может не происходить.

Проверки и исправления — пошагово
1) Проверить совпадение версии ядра и каталога модулей

  • Выполните:
    uname -r
    ls -ld /lib/modules/$(uname -r)
    Убедитесь, что каталог с модулями существует и соответствует текущему ядру.

2) Посмотреть, есть ли файлы modules.dep.bin и modules.alias.bin

  • Выполните:
    ls -l /lib/modules/$(uname -r)/modules.*bin
    Если modules.dep.bin отсутствует или сильно старый — это проблема.

3) Перестроить индексы модулей

  • Выполните:
    depmod -a
    Это создаст/обновит modules.dep(.bin) и modules.alias(.bin). После этого проверьте загрузку модуля командой:
    modprobe -v tun
    Если modprobe найдёт модуль — проблема решена.

4) Проверить наличие самого модуля tun

  • Выполните:
    modinfo tun
    или
    find /lib/modules/$(uname -r) -name "tun.ko"
    Убедитесь, что файл tun.ko присутствует в дереве модулей.

5) Проверить логи автозагрузки модулей (systemd-пользователи)

  • Если у вас systemd:
    journalctl -u systemd-modules-load.service —no-pager
    Также смотрите общие логи dmesg / journalctl -b на предмет ошибок загрузки модулей/kmod.
  • Проверяйте /etc/modules-load.d/tun.conf и /run/modules-load.d/ — файлы там читаются в процессе загрузки.

6) Проверить работу kmod static-nodes

  • При корректной работе на этапе инициализации системы должна вызываться команда kmod static-nodes, которая создаёт /dev/net/tun на основе alias devname:net/tun. Если это не происходит, проверьте initrd/initramfs и скрипты инициализации (вручную можно попытаться выполнить kmod static-nodes и посмотреть ошибки).

7) Временные и альтернативные решения

  • Если depmod не помог и нужно срочно получить автозагрузку:
    • Оставьте строку devname:net/tun в /etc/modules-load.d/tun.conf — это работает, как вы заметили.
    • Либо добавьте modprobe tun в init-скрипт или создайте unit systemd, который выполнит modprobe tun во время загрузки.
    • Можно вручную создать узел устройства (пример):
      mkdir -p /dev/net
      mknod /dev/net/tun c 10 200
      chmod 666 /dev/net/tun
      (обычно major=10, minor=200 для tun — проверьте в вашей системе)

8) Если проблема не исчезает — проверьте несоответствие модулей и ядра

  • Частая причина: модули собраны для другой версии ядра. Тогда depmod/alias будут неконсистентны. Решение — установить/собрать правильные модули для текущего ядра или загрузить соответствующее ядро.

9) Проверить версию kmod / busybox modprobe

  • На минимальных системах modprobe может быть из busybox с отличным поведением. Убедитесь, что используемый kmod поддерживает работу с binaries modules.dep.bin и modules.alias.bin.

Короткое техническое объяснение механизма

  • Загрузка модуля по имени использует modules.dep(.bin) — карта имен модулей → путь к .ko.
  • Загрузка модуля по алиасу (включая devname:net/tun) использует modules.alias(.bin).
  • При отсутствии/повреждении modules.dep.bin модуль по имени не найдётся, но по alias он может быть найден в modules.alias.bin — поэтому запись devname:net/tun работает.
  • Static nodes создают /dev-узлы по alias, что позволяет автоматике подгружать модуль при первом обращении к устройству.

Резюме и рекомендации

  • Первое действие при такой проблеме — запустить depmod -a и повторно проверить modprobe tun.
  • Убедитесь, что каталог /lib/modules/$(uname -r) соответствует текущему ядру и содержит tun.ko.
  • Посмотрите журналы systemd (если используется) и вывод kmod/static-nodes.
  • Если модули и ядро не совпадают — пересоберите или установите модули под правильную версию ядра.
  • Как временный обходной путь можно оставить alias devname:net/tun в /etc/modules-load.d или принудительно подгружать модуль через systemd/unit или init-скрипт.

Если хотите, могу подготовить конкретный чеклист команд, который вы сможете выполнить на вашей системе, или помочь проанализировать вывод uname -r, ls /lib/modules и вывод depmod/modprobe/journalctl — пришлите результаты, и я подскажу дальше.

Источник

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *