LXD надає контейнеру символьний пристрій хоста, додаючи вузол пристрою, а не навчаючи гостя створювати його. Якщо в контейнері немає /dev/net/tun, пристрій може бути на хості, а гість усе одно не зможе його відкрити. Запис unix-char — це половина цього шляху на боці менеджера, і він навмисно вужчий за привілейований контейнер. Тому вузол хоста і вузол контейнера заслуговують на окремі перевірки.

Механізм достатньо короткий, щоб тримати його в полі зору: LXD розв'язує шлях на хості, створює відповідний вузол усередині екземпляра і додає пристрій до cgroup пристроїв контейнера. Далі процесу гостя потрібні власний дозвіл і здатність, щоб використати вузол для чого завгодно.

Що запис unix-char насправді змінює

Пристрій unix-char повідомляє LXD, що потрібно надати один символьний пристрій хоста за вибраним шляхом усередині контейнера. Запис має три важливі частини: мітку пристрою, яку використовує менеджер, шлях source на хості і path, який бачить гість. Лише останні дві описують сам пристрій. Друкарська помилка в будь-якій з них створює вузол у місці, яке клієнт ніколи не відкриває.

На хості пристрій зазвичай /dev/net/tun. Усередині контейнера можна зберегти той самий шлях або вибрати інший, але шлях має збігатися з тим, що очікує клієнт VPN. Збереження /dev/net/tun уникає другої проблеми з конфігурацією, бо більшість клієнтів відкривають цей шлях не питаючи.

Менеджер застосовує запис під час запуску екземпляра або гарячого підключення пристрою. Він не копіює драйвер у гостьову систему і не створює тунельний інтерфейс. Він робить вузол видимим і дозволяє доступ через групу керування пристроями контейнера.

Оголошуйте пристрій на екземплярі, а не всередині гостя

Додайте запис з контексту адміністрування LXD, назвавши екземпляр і мітку, яку ви впізнаєте пізніше. Для контейнера з назвою vpnbox команда така:

lxc config device add vpnbox tun unix-char source=/dev/net/tun path=/dev/net/tun
lxc config device show vpnbox

Мітка tun локальна для конфігурації екземпляра. Це не назва інтерфейсу, і вона не мусить збігатися ні з чим у гості. Якщо профіль уже надає той самий пристрій, додавання другого запису створює конфлікт, а не надмірність, тож спершу перегляньте чинну конфігурацію.

Редагування файлів усередині контейнера — неправильний рівень. mknod у стартовому сценарії може виглядати так, ніби працює на привілейованому контейнері, а потім зникнути під час перестворення або не спрацювати на менш привілейованому. Набором пристроїв екземпляра володіє менеджер; хай він володіє і вузлом.

Узгодьте власника і режим із процесом гостя

Запис unix-char може задати uid, gid і mode для вузла всередині контейнера. Використовуйте їх, щоб відповідати обліковому запису, який запускає клієнт VPN, замість того щоб відкривати пристрій усім користувачам або переводити контейнер у привілейований режим.

Видимість — не те саме, що дозвіл. Вузол, що належить root із режимом 600, видимий службі, яка працює як непривілейований користувач, і все одно не може бути нею відкритий. Спершу перевірте обліковий запис гостя, потім призначте власником цей запис і тримайте режим не ширшим, ніж потрібно клієнту.

Процесу також потрібна здатність налаштовувати тунельний інтерфейс, зазвичай CAP_NET_ADMIN у мережевому просторі імен контейнера. Передача пристрою не дає цієї здатності, а надання здатності не забезпечує пристрій; це незалежні вимоги.

Знайте, чого запис не дає

Видимий вузол — не працюючий VPN. Пакет клієнта все ще треба встановити, профіль усе ще має бути чинним, і служба все ще має запуститися. Автентифікація, маршрути і DNS залишаються роботою клієнта, і збій там не є доказом того, що запис пристрою неправильний.

systemd може додати ще одне обмеження. Модуль з DeviceAllow або посиленою політикою пристроїв може заборонити доступ до вузла, який надав менеджер контейнерів. Перевірте політику пристроїв модуля, коли вузол існує, але служба повідомляє про помилку дозволу, і змініть цю політику, а не розширюйте контейнер.

Гаряче підключення необов'язкове і явне. Запису з required=false потрібен шлях джерела, і він може з'являтися або зникати разом зі зміною пристрою хоста. Такий життєвий цикл пасує обладнанню, що з'являється і зникає; для TUN-пристрою, потрібного VPN під час завантаження, необов'язковий запис може залишити службу запущеною раніше, ніж з'явиться її передумова.

Перевіряйте видимість, відкриття й інтерфейс саме в цьому порядку

Спершу підтвердьте вузол усередині потрібного контейнера. Шлях, старший і молодший номери та власник мають збігатися з пристроєм хоста і доданим записом. Відсутність вузла означає, що менеджер не застосував запис або застосував його до іншого екземпляра.

lxc exec vpnbox -- ls -l /dev/net/tun
lxc exec vpnbox -- sh -c 'test -c /dev/net/tun && echo char-device-ok'

Потім підтвердьте, що обліковий запис служби може його відкрити. Коротка перевірка від цього запису відокремлює проблему володіння від проблеми служби. Нарешті, запустіть клієнт і підтвердьте, що з'явився тунельний інтерфейс; лише цей третій крок доводить увесь шлях, бо перші два можуть пройти, поки профіль або здатність клієнта ще неправильні.

Запишіть екземпляр, мітку пристрою, джерело на хості, шлях у гості та обліковий запис-власник, коли зміну схвалено. Ці п'ять значень має зберегти подальше перестворення, міграція або зміна профілю, і їх значно легше порівняти, ніж помилку дозволу без контексту.

Схожі статті