Звичайна програма Linux використовує VPN, не торкаючись TUN
Демон володіє пристроєм TUN і тунелем; програми лише відкривають сокети. Тримайте привілей налаштування й мережевий доступ як окремі межі.
Браузер, що використовує вже встановлений Linux VPN, не відкриває /dev/net/tun. Він відкриває сокет, а ядро вирішує, через який інтерфейс виходять пакети цього сокета. Процес, що створив тунель, виконує іншу роботу, ніж процес, чий трафік він переносить. Розділення цих двох ролей відповідає на більшість питань про права ще до того, як їх ставлять.
Простежте один пакет від сокета до тунелю
Звичайна програма викликає connect або send, і ядро шукає маршрут до призначення. Якщо вибраний маршрут указує на інтерфейс тунелю, пакет ставиться в чергу пристрою, який читає демон VPN. Демон шифрує його й надсилає назовні через фізичний інтерфейс. Кожна стрілка в цьому описі — місце, де можна відповісти на питання про права.
Ніщо на цьому шляху не вимагає, щоб програма знала про пристрій. Демон тримає файловий дескриптор і виконує операції з інтерфейсом, а програма бачить лише звичайний мережевий API.
Намалюйте дві половини один раз, і питання про права стане легше розмістити. Верхня половина — світ програм, нижня належить демону.
Вирішіть, кому потрібен пристрій, а кому ні
Створення інтерфейсу TUN або приєднання до нього потребує доступу до пристрою й додатково можливості його налаштувати, тому підтримуваний сервіс VPN починає з прав адміністрування мережі або використовує привілейованого помічника. Ця вимога належить демону. Вона нічого не каже про браузер, клієнт бази даних чи засіб передавання файлів. Сервісу, якому потрібна ця можливість, вона потрібна для власного кроку налаштування, а не для його клієнтів.
Коли маршрут і політика на місці, звичайний процес використовує отриманий шлях через свої звичайні виклики сокетів. Йому не потрібен вузол пристрою і не потрібен root.
Зміна прав пристрою — не спосіб дати програмі доступ до призначення. Вона лише переносить межу пристрою в інше місце.
Перевірте простір імен, у якому програма справді працює
Контейнер або другий мережевий простір імен дає своїм процесам окремий набір інтерфейсів і таблицю маршрутів. Тунель на хості не з'являється там автоматично, і жодні зміни прав пристрою цього не змінять. Програма просто маршрутизуватиме через те, що надає цей простір імен. Тому образ контейнера не може випадково успадкувати тунель хоста.
Перевірте за допомогою ip netns list і ip -n NAME route, або оглянувши посилання простору імен процесу. Відповідь зазвичай видно однією командою.
Двом користувачам на тому самому хості політика також може дати різні шляхи. Це мережеве рішення, а не доказ володіння пристроєм.
Відокремте можливості від мережевої політики
Деяким інструментам потрібно більше, ніж сокет. Перехоплення пакетів потребує сирого сокета, а зміна маршрутів — адміністративних прав. Це окремі операції з окремими дозволами, і надання однієї не варто читати як загальну вимогу для використання VPN.
Програма, що реалізує власний тунель, — третій випадок. Вона справді відкриває TUN, бо бере на себе роль демона, тому їй потрібні його привілеї.
Назвіть операцію, перш ніж називати привілей. Зазвичай їх легше розділити, ніж здається.
Перевірте розділення двома обліковими записами
Підключіть тунель як сервіс, потім запустіть програму як звичайний користувач і підтвердьте, що вона досягає приватного ресурсу. Перевірте ip route get для призначення з оболонки цього користувача, щоб побачити, який інтерфейс вибрано. Якщо маршрут правильний, а з'єднання все одно не працює, проблема в політиці, а не в привілеї.
Отриманий дизайн — мінімальні привілеї з явною межею: один компонент володіє налаштуванням і ресурсами тунелю, робочі навантаження зберігають звичайні облікові записи, а мережева політика вирішує, що може пройти. Запуск усього як root руйнує ці ролі, нічого не пояснюючи.