Routingtabell kontra faktisk uppslagning: vart VPN-trafiken tar vägen
Börja med ett mål och dess källa och kontrollera sedan vilken regel och tabell som faktiskt avgör vägen. En full tabellutskrift utan den kontexten vilseleder.
En utskrift av routingtabellen är den minst användbara diagnosen vid VPN-felsökning och den som oftast klistras in. Fyrtio rader med prefix berättar vad maskinen skulle kunna göra, inte vad den gjorde för förfrågan som misslyckades. Mekanismen du faktiskt vill ha är uppslagningen: givet denna källa och detta mål, vilken regel matchade, vilken tabell konsulterades och vilket gränssnitt och nästa hopp kom ut. Börja med ett mål och en källa, läs sedan tabellen med den frågan i handen, och samma utdata blir bevis i stället för brus.
En tabell är en mängd kandidater, inte ett beslut
Varje post beskriver ett prefix och vad som ska göras med trafik som matchar det: skicka den till ett gränssnitt, lämna den till ett nästa hopp eller släpp den. Ingenting i listan är ordnat efter avsikt, och posten som ser mest specifik ut för en människa är inte alltid den som kärnan väljer, eftersom valet följer längsta prefixmatchning och, bland lika prefix, metrikvärdet.
Så första steget är att fråga kärnan i stället för att läsa listan. Uppslagningskommandot svarar för ett mål, och med ett källargument svarar det för det exakta paret som en vidarebefordrad eller bunden anslutning skulle använda:
ip route get 198.51.100.10
ip route get 198.51.100.10 from 10.80.0.25
ip -6 route get 2001:db8:10::40
Varje adress ovan är ett dokumentationsexempel. Poängen är svarets form: gränssnitt, vald källadress, gateway och tabellen som posten kom från. Om utdata inte matchar det gränssnitt du förväntade dig har du lokaliserat problemet med ett enda kommando, och ingen mängd läsning av hela tabellen hade berättat vilken kandidat som vann.
Uppslagningen går först genom regler och sedan genom tabeller
På Linux är beslutet i två steg. Policyregler utvärderas i prioritetsordning, och den första regel som matchar namnger en tabell att konsultera; den tabellen gör sedan längsta-prefixmatchningen. En regel kan matcha på källa, mål, brandväggsmarkering, gränssnitt eller en kombination, vilket är varför en utskrift av huvudtabellen kan vara helt korrekt och helt irrelevant för paketet du undersöker.
ip rule show
ip route show table all | head -40
ip route show table 100
Om en regel skickar trafik från din VPN-pool till tabell 100, är det tabell 100 som gäller, och huvudtabellen är en lockfågel. Detta är också mekanismen bakom källbaserad routing på en router: samma mål kan ha två olika svar beroende på var paketet kom ifrån, och endast uppslagningen med ett källargument avslöjar vilket som gäller.
IPv6 har sina egna regler och tabeller. En design som kör båda familjerna behöver båda uppslagningarna, och ett fungerande IPv4-svar säger ingenting om den v6-väg som en dual-stack-klient kan föredra.
Vad VPN-klienten installerar
Klienter ersätter vanligtvis inte standardrutten, eftersom det skulle bryta tunnelns egen yttre väg. De installerar något mer specifikt som vinner på prefixlängd: ett par halvstandardrutter som täcker 0.0.0.0/1 och 128.0.0.0/1 är det klassiska tricket, eftersom båda är längre prefix än 0.0.0.0/0 och tillsammans täcker hela rymden. Andra installerar specifika privata prefix plus en policyregel, och vissa lägger till en markering så att bara utvald trafik fångas.
Det är därför "VPN:et ändrade inte min standardrutt" inte är bevis på fel. Kontrollera vad den faktiskt lade till, och om det aktuella målet ligger inom dessa prefix:
ip route show | grep -E 'tun|wg|ppp|ipsec'
ip route get 10.20.30.40 from 10.80.0.25
Två halvrutter är lätta att missa i en utskrift eftersom de inte ser ut som en standardrutt. En split-tunnel-konfiguration som glömde att inkludera ett prefix producerar exakt det symptom du jagar: applikationen som borde använda tunneln löser och ansluter lokalt i stället. Jämför de installerade prefixen med de mål som användaren faktiskt behöver, inte med de adresser du råkade testa. En split-tunnel-lista som täcker filservern men inte dess resolver producerar en anslutning som löses till en offentlig adress och sedan misslyckas med autentiseringen, vilket ser ut som ett lösenordsproblem och är ett routingproblem.
Den yttre vägen måste också överleva
Tunneln är själv trafik. Paketen som bär den inkapslade nyttolasten går till peer-adressen via det fysiska gränssnittet, och den vägen får inte routas tillbaka in i tunneln. När det händer får du det karakteristiska felet där tunneln upprättas och sedan slutar föra trafik, eftersom transporten för tunneln nu ligger inne i tunneln.
Kontrollera peer-adressen som du kontrollerade det inre målet, och bekräfta att den löses till det fysiska gränssnittet och inte till tunneln:
ip route get 203.0.113.10
traceroute -n -m 5 203.0.113.10
En rekursiv rutt, en policyregel som fångar peeren, eller en standardrutt som ersatts av en fulltunnelklient är de tre vanliga orsakerna. Alla tre syns i den yttre uppslagningen, och ingen av dem syns i en utskrift av huvudtabellen som tagits i efterhand.
Vad routingutdata inte kan berätta för dig
En korrekt uppslagning betyder att kärnan skulle skicka paketet någonstans vettigt. Det betyder inte att brandväggen tillåter det, att IPsec-policyn täcker det, att NAT-regeln översätter det, eller att fjärrsidan har en returväg. Var och en av dessa är ett senare steg, och strongSwans anteckningar om vidarebefordran beskriver kedjan som ett paket måste passera i båda ändarna.
Det tar inte heller hänsyn till bindning på applikationsnivå. En process kan binda till ett gränssnitt, sätta en markering eller använda sin egen resolver och ansluta med ett namn som löses annorlunda än det du testade. När uppslagningen är korrekt och anslutningen fortfarande misslyckas, är nästa fråga vilken process som skapar den och om den processen ser samma tabell som du.
Håll därför diagnosen i ordning: namnge målet och källan, kör uppslagningen, läs bara den tabell och regel som uppslagningen namngav, och testa sedan nästa steg. Den sekvensen håller en routingutredning inom några minuter och lämnar ett protokoll som någon annan kan följa, vilket en inklistrad tabell aldrig gör.