Du kan inte undanta ett program från en WireGuard-värd med full tunnel genom att redigera rutter. Rutter väljer en väg efter destination, och det du vill undanta är en process, så kärnan har inget att matcha mot. Det fungerande tillvägagångssättet är att ge den processen sin egen nätverkskontext: ett namnutrymme med eget gränssnitt, egna adresser och egen standardrutt, kopplat till värden med ett veth-par. Jag körde detta på Ubuntu 24.04 med wireguard-tools 1.0.20210914, och namnutrymmet var aldrig problemet — värdens vidarebefordringspolicy och tunnelns markeringsregler var det.

Välj först vilken typ av kontext du behöver

I praktiken dyker två former upp. Om värden kör en full tunnel och ett program ska ut via ISP-vägen bygger du ett andra namnutrymme, kopplar det till värden och låter värden vidarebefordra och översätta trafiken för det. Om ett namnutrymme redan bär ett VPN-gränssnitt och du bara behöver ett kommando startat inuti det, är det det vanliga ip netns exec-fallet och det mesta av ruttjobbet är redan gjort.

Ingen av formerna ger dig en regel som är begränsad till ett enda process-id. Netfilter matchar adresser, portar, märken och gränssnitt; det finns ingen routingtabell per process. Märkning kan styra trafik, men märket måste sättas på paket som du redan har identifierat, och det är samma problem ett lager längre ner. Ett namnutrymme avskiljer hela stacken för det processträdet, och därför är det det vanliga svaret.

Om kravet verkligen är att ingenting lämnar tunneln, stoppa tunneln i stället. Namnutrymmet finns för det blandade fallet: ett program ut, allt annat in, på samma maskin, samtidigt.

Bygg den andra kontexten och koppla den till värden

En illustrativ layout: värden har ett WireGuard-gränssnitt som bär standardrutten, och ett nätverksnamnutrymme som heter clearnet kopplat till värden med ett veth-par. Adresserna nedan är exempel.

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

Det namnutrymmet kan nu nå värden och ingenting annat. Värden måste vidarebefordra trafiken och skriva om källadressen, eftersom 192.168.100.0/24 är privat och routern ovanför inte har någon rutt tillbaka in i det:

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

Bekräfta namnutrymmets sida innan du går vidare.ip netns exec clearnet ip route bör visa veth-rutten och standardrutten via 192.168.100.1, och en ping till den adressen bör svara. Om ping till värdens adress misslyckas är adresserna eller länktillståndet fel och ingen brandväggsregel hjälper.

När namn löses men ingenting kommer tillbaka, läs FORWARD

Det klassiska felet ser ut som en ruttbugg: namnutrymmet löser ett namn, paketet går ut och det kommer aldrig något svar. På värdar med FORWARD-policy DROP — det gör flera distributioner och de flesta härdade avbildningar — släpps paketet på vägen, och felet programmet skriver ut säger ingenting om filtrering.

Läs kedjan innan du lägger till något:

iptables -S FORWARD
nft list chain inet filter forward

Släpp sedan igenom trafiken i båda riktningarna, med räknare, så att du kan se om regeln någonsin matchade:

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'

En regel med noll paketräknare är inte på vägen. Antingen skiljer sig gränssnittsnamnen från det du antog, eller så har en tidigare regel i kedjan accepterat, släppt eller returnerat paketet först. Rätta ordningen, inte regeltexten.

Svartrafik är den hälft folk glömmer. Returregeln behöver samma veth-namn plus en matchning av anslutningstillstånd, eller en vanlig gränssnittsacceptans om du håller policyn öppen. Lägg bara till den utgående regeln och det ursprungliga symptomet är tillbaka, medan din nya regel står där och ser korrekt ut.

Håll tunnelns markeringsregler borta från den nya vägen

Det här steget förvandlar ett fungerande namnutrymme till ett läckande. WireGuard-setuper installerar vanligtvis en brandväggsmarkeringspolicy tillsammans med egna routingregler och en egen tabell, så omärkta paket faller tillbaka till huvudtabellen medan märkta paket använder tunneltabellen. Vidarebefordrad trafik från namnutrymmet utvärderas mot policy-routing på väg ut och, beroende på hur reglerna skrevs, kan den hamna i tunneltabellen.

Två tillägg skiljer vägarna. Gå tillbaka tidigt i mangle-kedjan för namnutrymmets subnät, och lägg till en källbaserad regel som sätter det subnätet i huvudtabellen:

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

Prioritet 100 sorteras före tunnelreglerna på min värd, så den vanliga tabellen avgör för den källan. Kopiera inte numret blint: de prioriteter som wg-quick installerar skiljer sig mellan versioner och mellan IPv4- och IPv6-uppsättningarna, så kör ip rule show och välj en prioritet som hamnar före tunnelreglerna på din maskin.

Verifiera med en källspecifik uppslagning i stället för att lita på regellistan:

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

Om det första kommandot rapporterar WireGuard-gränssnittet är den nya regeln ännu inte före tunnelpolicyn. Om det rapporterar WAN-gränssnittet medan det andra fortfarande visar veth-standardrutten, är värden och namnutrymmet oense och du bör läsa om båda routingtabellerna.

Starta processen som öppnar anslutningen

Att starta kommandot är en rad, men starta processen som faktiskt skapar socketen.ip netns exec clearnet curl -s https://ifconfig.me är det minsta ärliga testet: det visar adressen som namnutrymmet presenterar för världen, inte den värden skulle använda.

För en tjänst, fäst namnutrymmet via sökväg så att processen stannar i det hela livet:

[Service]
NetworkNamespacePath=/run/netns/clearnet

Grafiska program är där enradsmetoden tyst misslyckas. En webbläsare som startas från en meny ger ofta förfrågan till en instans som redan körs utanför namnutrymmet, så det nya fönstret dyker upp och trafiken går fortfarande ut genom tunneln. Ge den en separat profil så att en ny instans verkligen skapas, och kontrollera sedan processkontexten i stället för att gissa:

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

De två utdata måste stämma överens. Samma kontroll fungerar för alla långvariga program, och det är värt att göra den en gång per program i stället för att anta att startaren gjorde det du menade.

Namnuppslagning behöver sitt eget beslut. Att skapa ett namnutrymme ger det ingen resolverkonfiguration; filer per namnutrymme stöds via /etc/netns/<name>/resolv.conf och utan en ärver du beteende som är lätt att läsa fel. IPv6 behöver samma behandling: om namnutrymmet inte har någon v6-standardrutt medan programmet föredrar v6, kan förfrågningar hänga innan de faller tillbaka, vilket ser ut som en trasig tunnel.

Kontrollera inramningen, inte bara utgångsadressen

En fungerande offentlig adress bevisar rutten, inte hela kravet. Gå igenom resten i den här ordningen:

  • ip netns exec clearnet ip route get 1.1.1.1 visar veth-standardrutten, inte WireGuard-gränssnittet.
  • FORWARD-räknarna på båda reglerna ökar medan en förfrågan körs.
  • Programprocessen rapporterar den namnutrymmesinod du förväntar dig.
  • Efter en omstart finns namnutrymmet innan tjänsten startar; en unit som körs tidigare misslyckas eller, värre, körs utanför namnutrymmet.

Bestäm sedan vad som ska hända när tunneln faller. Namnutrymmet fortsätter att fungera, vilket är poängen med övningen och också risken: det undantagna programmet förblir anslutet medan allt annat stannar. Skriv ned det som ett policyval och var tydlig med vad undantaget inte täcker — kontoidentitet, sparat webbläsartillstånd och din DNS-leverantör står alla utanför räckvidden för ett nätverksnamnutrymme, och att behandla undantaget som anonymitet är felet som överlever konfigurationen.

Relaterade artiklar