WireGuard i ett nätverksnamnrum: varför socketen blev kvar
Att flytta gränssnittet flyttar inte den krypterade UDP-socketen, som stannar i namnrummet där enheten skapades. Skapa den i målet i stället.
Gränssnittet finns i namnrummet du ville ha, programmet är bundet till det, och ändå dyker aldrig någon tunneltrafik upp. Detta är signaturen för en WireGuard-enhet i Linuxkärnan som skapades i en namnrymd och flyttades till en annan: gränssnittet flyttades och dess krypterade UDP-socket gjorde det inte. Båda måste vara på rätt plats innan den inre trafiken spelar roll. Kontrollen går snabbt när du väl vet att du måste titta på två kontexter i stället för en.
Symtomet: rätt namnrum, inga paket
Inne i namnrummet ser tunneln frisk ut. Enheten finns, adresser är tilldelade och peer-konfigurationen är på plats. Utanför dyker det förväntade UDP-utbytet aldrig upp på gränssnittet du övervakade, och andra sidan rapporterar att det inte blev någon handskakning.
Orsaken är att programmets inre paket når den flyttade enheten, och enheten försöker skicka dem genom en socket som tillhör en annan nätverkskontext. Den underliggande rutten den använder, och varje brandväggsregel som gäller för den, är de i namnrymden där enheten skapades.
Det är inte ett fel i flytten och inte en felkonfiguration av peeren. Så gör kärnimplementeringen, och namnrymdsdokumentationen för WireGuard beskriver skapanderegeln direkt.
Varför socketen har en födelseplats
En WireGuard-enhet äger en UDP-socket för sin krypterade transport, och den socketen öppnas i namnrymden där enheten skapas. Att flytta gränssnittet med ett länkkommando flyttar den synliga enheten men lämnar transporten där den började. Då har de två objekten olika ägare.
Konsekvensen är lätt att missa eftersom de två halvorna granskas på olika ställen. Den inre rutten avgörs i namnrymden där programmet kör, och den yttre rutten avgörs där socketen bor. Att kontrollera bara en av dem ger en självsäker men felaktig slutsats. Att kontrollera båda avslutar vanligtvis utredningen i en enda genomgång.
Skapa den där du vill ha socketen
Lösningen är att skapa enheten inne i mål-namnrymden i stället för att skapa den utanför och flytta den. Förutsatt att en godkänd namnrymd redan finns och att namnet är oanvänt:
ip netns exec vpn-apps ip link add wg-demo type wireguard
ip netns exec vpn-apps wg show
Nu tillhör både gränssnittet och dess socket den kontexten, så den underliggande rutten och de tillämpliga filtreringsreglerna är de som konfigurerats där. Om designen behöver den klara sidan någon annanstans, placera först det underliggande gränssnittet i namnrymden och skapa sedan tunneln. Ordningen är en del av designen, inte en implementeringsdetalj.
Behandla dem som kommandon för nätverksadministration, inte som ett recept. De skapar en enhet och visar tillstånd; nycklar, peers, adresser och rutter måste fortfarande komma från en godkänd konfiguration, och ett befintligt produktionsgränssnitt bör aldrig sättas in i ett exempel.
Läs båda sidor av vägen
När enheten är på rätt plats, verifiera de två besluten var för sig. Börja med den inre uppslagningen från programmets kontext och kontrollera sedan den yttre vägen från kontexten som äger socketen:
ip netns exec vpn-apps ip route get 10.30.0.9
ip netns exec vpn-apps wg show
tcpdump -ni any udp port 51820
Om den inre uppslagningen löses genom tunneln och den yttre fångsten visar det krypterade utbytet, stämmer de två halvorna. Om fångsten är tom finns socketen fortfarande någon annanstans, eller så når den underliggande rutten i dess namnrymd inte slutpunkten.
Ytterligare en kontroll hör till protokollet: hur enheten skapas efter en omstart. En hanterare som återskapar gränssnittet med en annan skapandekontext ändrar socketens födelseplats. En manuell flytt som fungerade en gång är inte bevis för den hanterade vägen.