Не можете да освободите програма от хост 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 доставчик стоят извън обхвата на мрежовото пространство от имена и отношението към освобождаването като анонимност е грешката, която надживява конфигурацията.

Подобни статии