Nie można wyłączyć programu z hosta WireGuard z pełnym tunelem, edytując trasy. Trasy wybierają ścieżkę według celu, a to, co chcesz wyłączyć, jest procesem, więc jądro nie ma czego dopasować. Działające podejście to danie temu procesowi własnego kontekstu sieciowego: przestrzeni nazw z własnym interfejsem, adresami i domyślną trasą, połączonej z hostem parą veth. Uruchomiłem to na Ubuntu 24.04 z wireguard-tools 1.0.20210914 i przestrzeń nazw nigdy nie była problemem — problemem były polityka przekazywania hosta i reguły znakowania tunelu.

Najpierw wybierz rodzaj kontekstu, którego potrzebujesz

W praktyce występują dwie formy. Jeśli host prowadzi pełny tunel i jeden program ma wyjść ścieżką ISP, budujesz drugą przestrzeń nazw, łączysz ją z hostem i pozwalasz hostowi przekazywać i tłumaczyć ruch za nią. Jeśli przestrzeń nazw już niesie interfejs VPN i potrzebujesz tylko polecenia uruchamianego w niej, to zwykły przypadek ip netns exec i większość pracy z trasami jest już zrobiona.

Żadna z form nie daje reguły ograniczonej do jednego identyfikatora procesu. Netfilter dopasowuje adresy, porty, znaczniki i interfejsy; nie ma tabeli tras na proces. Znakowanie może kierować ruchem, ale znak trzeba nałożyć na pakiety, które już zidentyfikowałeś, a to ten sam problem o warstwę niżej. Przestrzeń nazw oddziela cały stos dla tego drzewa procesów i dlatego jest to zwykła odpowiedź.

Jeśli wymaganie naprawdę jest takie, że nic nie wychodzi z tunelu, zatrzymaj tunel. Przestrzeń nazw istnieje dla przypadku mieszanego: jeden program na zewnątrz, wszystko inne do środka, na tej samej maszynie, w tym samym czasie.

Zbuduj drugi kontekst i połącz go z hostem

Ilustracyjny układ: host ma interfejs WireGuard niosący domyślną trasę oraz przestrzeń nazw sieci o nazwie clearnet połączoną z hostem parą veth. Adresy poniżej są przykładami.

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

Ta przestrzeń nazw może teraz dotrzeć do hosta i do niczego innego. Host musi przekazywać ruch i przepisywać adres źródłowy, bo 192.168.100.0/24 jest prywatne, a router nadrzędny nie ma trasy z powrotem do niego:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE

Potwierdź stronę przestrzeni nazw, zanim przejdziesz dalej.ip netns exec clearnet ip route powinno pokazać trasę veth i domyślną trasę przez 192.168.100.1, a ping na ten adres powinien odpowiedzieć. Jeśli ping na adres hosta zawiedzie, adresy lub stan łącza są złe i żadna reguła zapory nie pomoże.

Gdy nazwy się rozwiązują, ale nic nie wraca, przeczytaj FORWARD

Klasyczna awaria wygląda jak błąd routingu: przestrzeń nazw rozwiązuje nazwę, pakiet wychodzi i odpowiedź nigdy nie nadchodzi. Na hostach z polityką FORWARD DROP — tak robi kilka dystrybucji i większość utwardzonych obrazów — pakiet jest odrzucany po drodze, a błąd drukowany przez aplikację nic nie mówi o filtrowaniu.

Przeczytaj łańcuch, zanim cokolwiek dodasz:

iptables -S FORWARD
nft list chain inet filter forward

Następnie przepuść ruch w obu kierunkach, z licznikami, aby wiedzieć, czy reguła kiedykolwiek pasowała:

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'

Reguła z zerowym licznikiem pakietów nie jest na ścieżce. Albo nazwy interfejsów różnią się od założonych, albo wcześniejsza reguła w łańcuchu przyjęła, odrzuciła lub zwróciła pakiet jako pierwsza. Popraw kolejność, nie treść reguły.

Ruch odpowiedzi to połowa, o której ludzie zapominają. Reguła powrotu potrzebuje tej samej nazwy veth plus dopasowania stanu połączenia albo zwykłego przyjęcia interfejsu, jeśli trzymasz politykę otwartą. Dodaj tylko regułę wychodzącą, a pierwotny objaw wraca, podczas gdy nowa reguła stoi tam i wygląda poprawnie.

Trzymaj reguły znakowania tunelu z dala od nowej ścieżki

Ten krok zamienia działającą przestrzeń nazw w przeciekającą. Instalacje WireGuard zwykle instalują politykę znaku zapory wraz z własnymi regułami routingu i osobną tabelą, więc pakiety nieoznaczone wracają do tabeli głównej, a oznaczone korzystają z tabeli tunelu. Przekazywany ruch z przestrzeni nazw jest oceniany wobec routingu politycznego na wyjściu i w zależności od tego, jak zapisano te reguły, może trafić do tabeli tunelu.

Dwa dodatki rozdzielają ścieżki. Wróć wcześnie w łańcuchu mangle dla podsieci przestrzeni nazw i dodaj regułę opartą na źródle, która umieszcza tę podsieć w tabeli głównej:

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

Priorytet 100 sortuje się przed regułami tunelu na moim hoście, więc dla tego źródła decyduje zwykła tabela. Nie kopiuj liczby na ślepo: priorytety, które wg-quick instaluje, różnią się między wersjami i między konfiguracjami IPv4 i IPv6, więc uruchom ip rule show i wybierz priorytet, który na twojej maszynie wypada przed regułami tunelu.

Zweryfikuj za pomocą wyszukiwania specyficznego dla źródła zamiast ufać liście reguł:

ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1

Jeśli pierwsze polecenie zgłasza interfejs WireGuard, nowa reguła jeszcze nie jest przed polityką tunelu. Jeśli zgłasza interfejs WAN, podczas gdy drugie nadal pokazuje domyślną trasę veth, host i przestrzeń nazw nie są zgodne i powinieneś ponownie przeczytać obie tabele routingu.

Uruchom proces, który otwiera połączenie

Uruchomienie polecenia to jedna linia, ale uruchom proces, który naprawdę tworzy gniazdo.ip netns exec clearnet curl -s https://ifconfig.me to najmniejszy uczciwy test: pokazuje adres, który przestrzeń nazw przedstawia światu, a nie ten, którego użyłby host.

Dla usługi podłącz przestrzeń nazw przez ścieżkę, aby proces pozostał w niej przez całe życie:

[Service]
NetworkNamespacePath=/run/netns/clearnet

Aplikacje graficzne to miejsce, w którym podejście jednej linii po cichu zawodzi. Przeglądarka uruchomiona z menu często przekazuje żądanie instancji działającej już poza przestrzenią nazw, więc nowe okno się pojawia, a ruch nadal wychodzi przez tunel. Daj jej osobny profil, aby naprawdę powstała nowa instancja, a potem sprawdź kontekst procesu zamiast zgadywać:

readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet

Oba wyjścia muszą się zgadzać. Ta sama kontrola działa dla każdego długo działającego programu i warto ją wykonać raz na aplikację zamiast zakładać, że launcher zrobił to, co miałeś na myśli.

Rozwiązywanie nazw wymaga własnej decyzji. Utworzenie przestrzeni nazw nie daje jej konfiguracji resolvera; pliki dla poszczególnych przestrzeni nazw są obsługiwane przez /etc/netns/<name>/resolv.conf a bez niego dziedziczysz zachowanie, które łatwo odczytać błędnie. IPv6 wymaga tego samego podejścia: jeśli przestrzeń nazw nie ma domyślnej trasy v6, a aplikacja preferuje v6, żądania mogą się zablokować przed wycofaniem, co wygląda jak zepsuty tunel.

Sprawdź oprawę, nie tylko adres wyjścia

Działający publiczny adres dowodzi trasy, nie całego wymagania. Przejdź przez resztę w tej kolejności:

  • ip netns exec clearnet ip route get 1.1.1.1 pokazuje domyślną trasę veth, nie interfejs WireGuard.
  • Liczniki FORWARD na obu regułach rosną, gdy żądanie trwa.
  • Proces aplikacji zgłasza oczekiwany inode przestrzeni nazw.
  • Po ponownym uruchomieniu przestrzeń nazw istnieje, zanim usługa wystartuje; unit uruchamiany wcześniej zawodzi albo, co gorsza, działa poza przestrzenią nazw.

Następnie zdecyduj, co ma się stać, gdy tunel padnie. Przestrzeń nazw działa dalej, co jest celem ćwiczenia i jednocześnie ryzykiem: wyłączony program pozostaje połączony, a wszystko inne się zatrzymuje. Zapisz to jako decyzję polityki i bądź jasny co do tego, czego wyjątek nie obejmuje — tożsamość konta, zapisany stan przeglądarki i twój dostawca DNS stoją wszyscy poza zasięgiem przestrzeni nazw sieci, a traktowanie wyjątku jako anonimowości to błąd, który przeżyje konfigurację.

Powiązane artykuły