Як запустити один процес Linux поза тунелем WireGuard
Дайте одній програмі власний мережевий контекст, щоб вона виходила з хоста WireGuard із повним тунелем, а потім виправте правила пересилання й маркування, які її блокують.
Не можна виключити програму з хоста WireGuard із повним тунелем, редагуючи маршрути. Маршрути обирають шлях за призначенням, а виключити ви хочете процес, тож ядру нема з чим порівнювати. Робочий підхід — дати цьому процесу власний мережевий контекст: простір імен зі своїм інтерфейсом, своїми адресами й маршрутом за замовчуванням, з'єднаний з хостом парою veth. Я запускав це на Ubuntu 24.04 з wireguard-tools 1.0.20210914, і простір імен жодного разу не був проблемою — проблемою були політика пересилання хоста й правила маркування тунелю.
Спочатку виберіть потрібний тип контексту
На практиці трапляються дві форми. Якщо хост тримає повний тунель і одна програма має вийти шляхом провайдера, ви будуєте другий простір імен, підключаєте його до хоста й дозволяєте хосту пересилати та транслювати трафік за нього. Якщо простір імен уже несе інтерфейс VPN і вам потрібна лише команда, запущена всередині нього, це звичайний випадок ip netns exec і більша частина роботи з маршрутизації вже зроблена.
Жодна з форм не дає правила, обмеженого одним ідентифікатором процесу. Netfilter зіставляє адреси, порти, мітки та інтерфейси; таблиці маршрутизації на процес не існує. Маркування може спрямовувати трафік, але мітку треба ставити на пакети, які ви вже визначили, і це та сама проблема на рівень нижче. Простір імен розділяє весь стек для цього дерева процесів, і тому це звична відповідь.
Якщо вимога справді в тому, щоб з тунелю нічого не виходило, зупиніть натомість тунель. Простір імен існує для змішаного випадку: одна програма назовні, все інше всередину, на одній машині, одночасно.
Побудуйте другий контекст і підключіть його до хоста
Ілюстративна схема: у хоста є інтерфейс WireGuard, що несе маршрут за замовчуванням, і мережевий простір імен із назвою clearnet з'єднаний з хостом парою veth. Адреси нижче — приклади.
ip netns add clearnet
ip link add veth-clear-out type veth peer name veth-clear-in
ip addr add 192.168.100.1/24 dev veth-clear-out
ip link set veth-clear-out up
ip link set veth-clear-in netns clearnet
ip netns exec clearnet ip addr add 192.168.100.2/24 dev veth-clear-in
ip netns exec clearnet ip link set veth-clear-in up
ip netns exec clearnet ip route add default via 192.168.100.1
Цей простір імен тепер може досягти хоста й нічого більше. Хост має пересилати трафік і переписувати адресу джерела, бо 192.168.100.0/24 є приватною, і в маршрутизатора вище немає маршруту назад у неї:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE
Переконайтеся в боці простору імен, перш ніж іти далі.ip netns exec clearnet ip route має показати маршрут veth і маршрут за замовчуванням через 192.168.100.1, а ping на цю адресу має відповісти. Якщо ping на адресу хоста не проходить, адреси або стан каналу неправильні, і жодне правило брандмауера не допоможе.
Коли імена розв'язуються, але нічого не повертається, прочитайте FORWARD
Класична невдача виглядає як помилка маршрутизації: простір імен розв'язує ім'я, пакет виходить, і відповідь ніколи не надходить. На хостах із політикою FORWARD DROP — так роблять кілька дистрибутивів і більшість зміцнених образів — пакет відкидається по дорозі, а помилка, яку друкує застосунок, нічого не каже про фільтрування.
Прочитайте ланцюжок, перш ніж щось додавати:
iptables -S FORWARD
nft list chain inet filter forward
Потім пропустіть трафік в обидва боки, зі слідчиками, щоб знати, чи правило колись збіглося:
iptables -A FORWARD -i veth-clear-out -o <wan-interface> -j ACCEPT
iptables -A FORWARD -i <wan-interface> -o veth-clear-out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
watch -n1 'iptables -L FORWARD -v -n'
Правило з нульовим слідчиком пакетів не на шляху. Або імена інтерфейсів відрізняються від припущення, або попереднє правило в ланцюжку першим прийняло, відкинуло чи повернуло пакет. Виправте порядок, а не текст правила.
Зворотний трафік — це половина, про яку забувають. Правилу повернення потрібна та сама назва veth плюс зіставлення стану з'єднання або звичайне прийняття інтерфейсу, якщо ви тримаєте політику відкритою. Додайте лише вихідне правило, і початковий симптом повернеться, а нове правило стоятиме там і виглядатиме правильно.
Тримайте правила маркування тунелю подалі від нового шляху
Цей крок перетворює робочий простір імен на протікаючий. Налаштування WireGuard зазвичай встановлюють політику мітки брандмауера разом зі своїми правилами маршрутизації та окремою таблицею, тож немарковані пакети падають назад у головну таблицю, а марковані використовують таблицю тунелю. Пересланий із простору імен трафік під час виходу оцінюється за політичною маршрутизацією і, залежно від того, як написано ці правила, може потрапити до таблиці тунелю.
Два доповнення розділяють шляхи. Поверніться раніше в ланцюжку mangle для підмережі простору імен і додайте правило на основі джерела, яке кладе цю підмережу в головну таблицю:
iptables -t mangle -I PREROUTING -s 192.168.100.0/24 -j RETURN
ip rule add from 192.168.100.0/24 lookup main priority 100
Пріоритет 100 на моєму хості шикується перед правилами тунелю, тож для цього джерела вирішує звичайна таблиця. Не копіюйте число наосліп: пріоритети, які wg-quick встановлює, різняться між версіями та між налаштуваннями IPv4 і IPv6, тому виконайте ip rule show і виберіть пріоритет, який на вашій машині опиняється перед правилами тунелю.
Перевірте за допомогою пошуку, специфічного для джерела а не довіряючи списку правил:
ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1
Якщо перша команда повідомляє інтерфейс WireGuard, нове правило ще не перед політикою тунелю. Якщо вона повідомляє інтерфейс WAN, поки друга досі показує маршрут за замовчуванням veth, хост і простір імен не згодні, і вам слід перечитати обидві таблиці маршрутизації.
Запустіть процес, який відкриває з'єднання
Запустити команду — один рядок, але запустіть процес, який справді створює сокет.ip netns exec clearnet curl -s https://ifconfig.me— найменший чесний тест: він показує адресу, яку простір імен подає світові, а не ту, яку використав би хост.
Для служби підключіть простір імен за шляхом, щоб процес залишався в ньому все життя:
[Service]
NetworkNamespacePath=/run/netns/clearnet
Графічні застосунки — це місце, де підхід одного рядка тихо зазнає невдачі. Браузер, запущений із меню, часто передає запит екземпляру, який уже працює поза простором імен, тож нове вікно з'являється, а трафік усе одно виходить через тунель. Дайте йому окремий профіль, щоб новий екземпляр справді створювався, а потім перевірте контекст процесу замість здогадок:
readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet
Два виводи мають збігатися. Та сама перевірка працює для будь-якої довготривалої програми, і її варто робити раз на застосунок, а не припускати, що запускач зробив те, що ви мали на увазі.
Розв'язання імен потребує власного рішення. Створення простору імен не дає йому конфігурації резолвера; файли для кожного простору імен підтримуються через /etc/netns/<name>/resolv.conf а без нього ви успадковуєте поведінку, яку легко прочитати неправильно. IPv6 потребує такого самого підходу: якщо простір імен не має маршруту за замовчуванням v6, а застосунок віддає перевагу v6, запити можуть застрягати перед відкатом, що виглядає як зламаний тунель.
Перевірте обрамлення, а не лише адресу виходу
Робоча публічна адреса доводить маршрут, а не всю вимогу. Пройдіть решту в цьому порядку:
ip netns exec clearnet ip route get 1.1.1.1показує маршрут за замовчуванням veth, а не інтерфейс WireGuard.- Слідчики FORWARD на обох правилах зростають, поки виконується запит.
- Процес застосунку повідомляє очікуваний inode простору імен.
- Після перезавантаження простір імен існує до старту служби; unit, який запускається раніше, зазнає невдачі або, що гірше, працює поза простором імен.
Потім вирішіть, що має статися, коли тунель падає. Простір імен продовжує працювати, і це мета вправи, а також ризик: виключена програма залишається підключеною, поки все інше зупиняється. Запишіть це як вибір політики і будьте ясні щодо того, що виняток не покриває — ідентичність облікового запису, збережений стан браузера й ваш постачальник DNS стоять усі поза межами мережевого простору імен, і ставлення до винятку як до анонімності — це помилка, яка переживає конфігурацію.