Образи контейнерів можуть містити всі потрібні двійкові та конфігураційні файли OpenVPN і все одно зазнавати невдачі під час першого мережевого виклику. Помилка називає /dev/net/tun, бо застосунок попросив у ядра інтерфейс TUN, а контейнер не мав ані вузла пристрою, ані можливості його створити. Це два окремі дозволи, і виправлення одного залишає інший точно там, де він був.

Щоб їх розділити, потрібна одна команда на кожен. Наступне повідомлення про помилку скаже, на якій межі ви насправді стояли.

Вузол пристрою і можливість — це двоє дверей

Вузол пристрою — це об'єкт файлової системи, тому контейнер має бачити його у власному просторі імен монтування. Можливість — це дозвіл, тому процесу потрібен CAP_NET_ADMIN у просторі імен, де буде створено інтерфейс. Передача пристрою без можливості дає вузол, який відкривається, і ioctl, який зазнає невдачі. Надання можливості без пристрою залишає застосунок нездатним відкрити будь-що, тому в прикладах обидва зазвичай з'являються разом.

Налаштування devices у Docker відображає пристрій хоста всередину контейнера, а cap_add коригує набір можливостей. Bind mount того самого шляху показує файл, не застосовуючи семантику доступу до пристрою.

Відтворіть це поза файлом Compose

Перед редагуванням служби перевірте, що на хості є пристрій і що голий контейнер може створити інтерфейс. Команда нижче навмисно мінімальна, і її єдина мета — відокремити проблему хоста від проблеми compose. Якщо вона не спрацює, жодна зміна compose не допоможе.

ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun:/dev/net/tun alpine sh -c 'apk add -q iproute2 && ip tuntap add dev tun9 mode tun && ip link show tun9'

Відсутність вузла на хості означає, що модуль tun недоступний, і це виправлення на боці хоста, а не контейнера. Вузол, який існує, але не відкривається всередині контейнера, вказує на доступ до пристрою, і повідомлення скаже permission denied, а не no such file. Порядок цих двох збоїв і є весь діагноз. Запишіть, який із них ви бачили, перш ніж змінювати будь-який прапорець.

Помилки після TUN — це інші проблеми

Щойно інтерфейс з'являється, наступний збій має іншого власника. Помилки автентифікації означають, що тунель дістався сервера і облікові дані було відхилено, тому зміни можливостей не допоможуть. Тунель, який встановлюється, поки застосунки все ще зазнають невдачі, вказує на маршрути, пересилання, розв'язання DNS усередині контейнера або власну мережеву схему контейнера. Кожен із цих пунктів — звичайне мережеве питання, на яке дозвіл TUN не може відповісти. Повторення початкового тесту після кожної зміни не дає збоям злитися в одне враження.

Копіювання кожного налаштування з робочого прикладу — це шлях, яким мінімальне виправлення перетворюється на нечитабельне визначення служби. Перенесіть лише ті, які потрібні цьому розгортанню, і запишіть, чому кожне там.

Перевірте інтерфейс усередині контейнера

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

ls -l /dev/net/tun
capsh --print | grep -i net_admin
ip link add dev tun9 type tun && ip link show tun9

Можливість, присутня в bounding set, але відсутня в effective set, поводиться інакше, ніж та, яку ніколи не надавали, і capsh показує обидві. Якщо вузол існує і можливість є, а створення все ще не вдається, середовище виконання нав'язує щось інше, наприклад профіль seccomp або політику AppArmor, що обмежує операцію. Це третя межа, яку документує середовище виконання, а не застосунок.

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

Схожі статті