Запустите VPN внутри собственного пространства имён, запустите там одно приложение, и трафик всё равно уходит через маршрут хоста. Ничего не сломано: пространство имён управляет только теми процессами, которые в него входят, а утечка пришла от процесса, который так и не вошёл. Интерфейсы, адреса, маршруты, правила межсетевого экрана и сокеты — это то, чем владеет пространство имён. Файлы, учётные записи и уже работающие службы — нет, и отсюда берётся большинство сюрпризов.

Чем владеет пространство имён и где рождается сокет

Перенесите интерфейс в пространство имён, и хост его потеряет; постройте туннель внутри, и хост его не увидит. Таков механизм VPN, ограниченного пространством имён: устройство и маршруты к нему живут в контексте, до которого добираются только выбранные процессы. Хост сохраняет свой маршрут по умолчанию, поэтому всё снаружи остаётся нетронутым.

Для WireGuard контекст создания важен не меньше текущего расположения: сокет UDP привязывается в том пространстве имён, где был создан интерфейс, даже после того как устройство переедет в другое место. От какой таблицы маршрутизации зависят шифрованные пакеты, зависит от этого места рождения. Когда сокет остаётся в контексте без маршрута к партнёру, интерфейс выполняет поиск, и рукопожатие никогда не уходит. Проверьте место его рождения, затем текущее расположение.

Что пространство имён не изолирует

Ничто здесь не разделяет файловые системы, учётные записи или секреты, и ни одна из этих границ не появляется оттого, что вы создали пространство имён. Конфигурация резолвера — это файл, поэтому процесс внутри всё ещё может прочитать настройку, указывающую на резолвер хоста, и отправить свой запрос наружу по маршруту, который это подразумевает. Приложение, передающее запрос уже работающему посреднику или системной службе, вовлекает процесс в совершенно другой контекст. И то и другое — запросы, на которые граница никогда не была рассчитана отвечать.

Решение — файл для каждого пространства имён в /etc/netns/<name>/resolv.conf или bind mount подготовленного файла, направленный на резолвер, доступный изнутри. Правка /etc/resolv.conf на хосте не меняет ничего из того, что видит пространство имён.

Размещение процессов и есть управление

Изоляция, которую вы получаете, — это ровно изоляция процессов, запущенных внутри. Оболочка, запущенная через помощник exec пространства имён, и всё, что она порождает, остаётся внутри; приложение рабочего стола, запущенное из сеанса хоста, — нет. Создайте контекст, перенесите устройство, затем докажите обе стороны:

ip netns add vpn1
ip link set wg0 netns vpn1
ip netns exec vpn1 wg show
wg show

Прочитайте первый wg show изнутри пространства имён, а второй — с хоста, и ожидайте, что только один из них перечислит партнёра. Если оба это делают, устройство так и не переехало; если ни один — оно ушло куда-то ещё. Когда запускающая сторона — менеджер служб, править нужно файл unit, а не ярлык на рабочем столе. Unit без настройки пространства имён запускает демон в контексте хоста и тихо отменяет замысел.

Проверяйте из контекста приложения

Выполните проверку тем же бинарником и тем же пользователем, что и приложение, внутри пространства имён. Включите DNS и оба семейства адресов, потому что маршрут IPv6, о котором вы не подумали, — обычный выход наружу. Проверка из вашей собственной оболочки доказывает лишь то, что ваша оболочка изолирована.

Затем выполните ту же проверку на хосте и убедитесь, что ответы различаются: адрес туннеля и предполагаемый выход внутри, маршрут хоста и выход из офиса снаружи, и резолвер по имени. Называйте пространства имён по развёртыванию, а не по протоколу, чтобы скрипт очистки не путал два из них.

Пересылка, политика сбоя и очистка

Для шлюза осознанно включите пересылку и решите, что должно произойти при падении туннеля. Пространство имён не блокирует маршруты, которые вы устанавливаете внутри, поэтому резервный маршрут к хосту будет использован, если вы его создадите. Это политическое решение, и его стоит записать до того, как сбой его проверит.

Запишите имена пространств имён, интерфейсы и то, кому принадлежит конфигурация, чтобы очистка удаляла только созданное развёртыванием. Сброс сети хоста во время отката превращает очистку в сбой. Страница network_namespaces(7) коротка, и её стоит прочитать перед проектированием этого пути.

Похожие статьи