I ena stunden är laptopen på kontorets Wi-Fi, i nästa är den ansluten till en telefon, och tunnelindikatorn är grön igen innan du hunnit byta fönster. En grön lampa rapporterar bara att tunneln återanslöt; vad routnings- och blockeringspolicyn gjorde under mellanrummet är en annan fråga. Den policyn är en uppsättning matchningsvillkor som kompilerades vid den senaste installationen, och den namnger ett gränssnitt, en adress och en adressfamilj som övergången just tog bort. Samma byte ger därför tre utfall som ser identiska ut: blockeringen fortsätter, policyn blockerar sin egen återhämtning, eller så öppnas en väg som ingenting täcker.

Ingenting på skärmen skiljer de tre tillstånden, så fråga vilka identifierare reglerna var fästa vid i stället för vilken färg indikatorn visar. På Linux kan en regel namnge ett gränssnitt eller ett ipset fyllt från det; på Android kan en VpnService få veta vilka underliggande nätverk den ska följa via setUnderlyingNetworks. Varje bindning pekar på en länk som är på väg att ersättas, och var och en måste omvärderas efteråt.

Vad övergången verkligen skriver om

När den gamla länken försvinner tar kärnan bort dess adresser, drar tillbaka rutter som pekade genom den och bygger om valet av källadress från det som återstår. Standardrutten flyttar till den nya gatewayen, och det gränssnittsindex som de gamla reglerna refererade till är borta eller återanvänt för en annan enhet. Resolvers per länk uppdateras också, dock inte i samma ögonblick som rutterna. Allt detta sker under VPN-klienten, så en klient som bara övervakar sin egen tunnels tillstånd ser ingenting av det.

Problemet är att en regel kodar en specifik identifierare i stället för avsikten bakom den. En regel som släpper allt som inte går ut genom tunnelgränssnittet kodar ett gränssnittsnamn; en regel som tillåter ändpunkten kodar en adress som det nya nätverket kan routa någon annanstans. När identifieraren försvinner blir regeln inte synbart fel: den slutar antingen matcha något eller börjar matcha fel sak.

Bygga om den yttre tunneln utan att slå hål

Den yttre transporten var bunden till den gamla källadressen, så den måste öppna en ny socket från den nya. När ändpunkten är ett värdnamn och inte en bokstavlig adress måste en uppslagning lyckas medan blockeringen fortfarande gäller. Det är ordningsfällan: en policy som är strikt nog att släppa allt utom ändpunkten släpper också uppslagningen som behövs för att hitta den, såvida inte upplösningen sker innan blockeringen hävs eller bärs genom en tunnel som fortfarande lever. Båda ordningarna kan fungera, men bara om klienten vet vilken den är i.

Klienter skiljer sig här på ett sätt som spelar roll vid diagnostik. Somliga löser upp först och installerar reglerna efteråt, så en övergång kostar ett synligt avbrott och återhämtar sig sedan själv; andra håller blockeringen uppe och förlitar sig på den överlevande tunneln för att bära uppslagningen, vilket misslyckas helt när tunneln dog med länken. Att lägga till en bred direkt standardrutt för att återställa anslutningen får alltid testet att passera och lämnar alltid läckan du förhindrade.

En rutt som fortfarande pekar på den gamla gatewayen ger samma fastlåsta återhämtning av en annan orsak, så läs tabellen innan du skyller på klienten. Kommandona nedan namnger gränssnittet och källadressen som kärnan faktiskt skulle använda, och det avgör på en rad om den gamla vägen fortfarande är installerad.

ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111

När den nya länken ger IPv6 och reglerna inte

Mobil- och gästnätverk delar ofta ut ett globalt IPv6-prefix även när kontorets kabelbundna LAN aldrig gjorde det. En policy skriven bara som IPv4-regler, den vanliga formen för de flesta handgjorda iptables- och nftables-recept, täcker ingenting av detta. Tunneln förblir ansluten, applikationer med IPv6-nåbarhet går utanför den, och indikatorn kan inte visa skillnaden eftersom tunneln verkligen är uppe. Spegelfallet är lika vanligt: en regeluppsättning bara för IPv6 gör ingenting alls på ett nätverk som inte erbjuder v6.

Jämför vad länken erbjuder med vad policyn nämner, på båda sidor av övergången. Dessa kommandon skriver ut samma fakta som klienten arbetar med:

ip -4 route show default
ip -6 route show default
sudo nft list ruleset | grep -c 'ip6 '

Om det andra kommandot skriver ut en standardrutt medan det tredje returnerar noll kan den nya länken föra maskinen ut över IPv6 utan att någon regel håller koll. Kör alla tre igen efter bytet, för det intressanta talet är skillnaden mellan de två körningarna. Om det andra inte skriver ut något gäller det omvända fallet och varje v6-tung policy är där bara dekoration.

Resolvern byter händer mitt i sessionen

På moderna system är resolvers knutna till länkar, så en ny länk kommer med en ny uppsättning resolvers och kanske en annan split-DNS-vy. systemd-resolved håller en scope per länk och väljer mellan dem efter rutt, medan macOS läser scopade resolvers från det dynamiska lagret och respekterar gränssnittsordningen. En klient som installerar sin egen resolver konkurrerar med länkens, och prioritetsregler som ingen övervakar avgör vinnaren. Då kan namnuppslagning gå sönder medan paketfiltreringen gör precis det den skrevs för.

Läs resolvern som är aktiv i stället för den som är konfigurerad. På en systemd-värd visar underkommandot status vilken länk varje scope kom från och om ett private-DNS-namn gäller:

resolvectl status --no-pager
resolvectl query intranet.example.com

Om frågan går ut genom den fysiska länken i stället för tunneln har klienten förlorat prioritetstävlingen och ingen brandväggsjustering kommer att reparera namngivningen. Jämför frågans väg på båda sidor av övergången för att se vilken som flyttade sig. Ett namn som löses till en privat adress som det nya nätverket inte kan routa är ett tredje fall, och det visar sig som en timeout och inte som ett fel.

Öva övergången och spara loggen

Reproducera ändringen med avsikt i stället för att vänta på den. Res tunneln på den första länken, starta en långvarig överföring och en upprepad uppslagning, byt sedan länk och se vilken som överlever. Notera intervallet mellan att den gamla länken försvinner och att tunneln rapporterar att den är ansluten, för i det fönstret höll policyn eller inte. Kör sekvensen i den andra riktningen också, så att resultatet inte blir ensidigt.

Undantag behöver sin egen genomgång, för en kringgång som var berättigad på det gamla nätverket är inte automatiskt berättigad på det nya. En skrivare, en NAS eller en captive portal på hemma-LAN har ingen motsvarighet på mobilt, och undantaget som nådde dem blir en regel utan motsvarighet.

Skriv ned gränssnittsnamnen, familjerna som erbjuds, den gällande resolvern och avbrottets längd för varje riktning. En återanslutning bevisar att transporten återhämtade sig, inte att blockeringen höll under mellanrummet, och det är separata påståenden för ett ärende. Med den loggen jämförs nästa övergång med ett känt tillstånd i stället för med minnet.

Relaterade artiklar