IPIP inuti WireGuard: de extra 20 byten som ingen hade budgeterat
IPIP kostar 20 byte mer inuti WireGuard. Gör budgeten på rätt lager innan du skyller fragmentering för en överföring som stannar på en levande tunnel.
Små ping går genom tunneln hela dagen, SSH-bannern kommer in och sedan fryser sessionen i samma ögonblick som en filöverföring börjar. Mönstret pekar på en bytebudget räknad på fel lager, där den yttre tunneln dimensionerades för sin egen overhead och ingen drog av den inre. Ett nästlat IPIP-paket är bara ännu ett IP-paket sett från WireGuard, och just därför förbrukar det byten som du aldrig reserverade. Rättelsen är aritmetik, och den ryms i tre kommandon och en tabell.
Symtomet som avslöjar det
Fragmenteringsproblem aviserar sig genom storlek, aldrig genom adresser. Din peer svarar på en 56-byte ping i en timme och tystnar sedan vid 1400 byte medan tunneln står kvar och ingen rutt har ändrats. Handskakningen får plats, det första fulla TCP-fönstret inte, och överföringen stannar sekunder efter att den såg frisk ut.
Mät taket innan du redigerar något, för ett omätt tak är det du kommer att jaga två gånger. Skicka en sond under den misstänkta storleken med do-not-fragment-biten satt, ping -M do -s 1000 10.9.0.2, och upprepa den sedan vid en storlek du redan vet är för stor. När vippet följer nyttolastens storlek medan destinationen är oförändrad gör routingen sitt jobb, och det saknas en header i budgeten.
Räkna varje header en gång, på rätt lager
Börja vid den minsta MTU:n på vägen och inte vid tunnelgränssnittet, eftersom väggen sitter uppströms båda ändarna. WireGuard spenderar 60 byte på en yttre IPv4-transport: 20 för IP, 8 för UDP och 32 för sin egen header, och 80 byte när den transporten är IPv6. En 1420-byte wg0 håller 20 byte i slack under de 1440 som en 1500-byte väg verkligen kan leverera, och därför passar talet kopierat från en wiki fortfarande här. Rita hela stacken på diagrammet, för den som ändrar MTU:n nästa gång väljer annars ett nytt runt tal och ärver din bugg.
| Layer | Bytes | Remaining |
|---|---|---|
| Path MTU on the wired link | none yet | 1500 |
| WireGuard outer: IP, UDP, WG header | 60 | 1440 |
| Slack kept for safety | 20 | 1420 (wg0) |
| IPIP header inside the tunnel | 20 | 1400 (ipip0) |
| Original IPv4 and TCP headers | 40 | 1360 payload |
Den femte raden är där budgetarna går fel, för de 1400 byte ett nästlat gränssnitt bär innehåller redan det ursprungliga paketets egna 40 byte headers. Bara 1360 av dessa byte når processen som läser filen. Behandla 1400 som applikationsnyttolast, vilket varje diagram utan den kolumnen bjuder in dig till, och den inre enheten slutar 40 byte för generös mot en vägg som inte har flyttat sig.
Ställ in de två MTU:erna separat
Bäraren och den nästlade enheten är separata objekt, så var och en behöver sitt eget värde. Använd dem i den här ordningen, för den nästlade enheten ärver ingenting från bäraren:
ip link set wg0 mtu 1420
ip tunnel add ipip0 mode ipip remote 203.0.113.9 local 198.51.100.4
ip link set ipip0 mtu 1400
Regeln som är värd att komma ihåg: inre MTU = yttre MTU - 20 när paketet som IPIP-tunneln bär är IPv4, och - 40 så snart någon sida av det inre paketet är IPv6, eftersom den nästlade headern växer från 20 byte till 40. Ingenting annat hör hemma i den subtraktionen. WireGuards overhead spenderades redan när du valde 1420, och att ta betalt för den två gånger ger en tunnel som fungerar perfekt och förblir långsam så länge ingen mäter den. En utrullning där båda enheterna bär en rund 1400 är fingeravtrycket av just det misstaget.
IPv6 på vardera sidan av det nästlade paketet ogiltigförklarar varje siffra ovan, så räkna om i stället för att kopiera ett tal från en liknande webbplats. De subtraherade headrarna är 40 byte vardera så snart IPv6 dyker upp i den yttre vägen eller i det ursprungliga datagrammet, och nyttolastsiffran faller exakt lika mycket.
Brandväggsregeln du förmodligen inte behöver
Mellan två WireGuard-peers är det enda på tråden UDP, så en inkommande regel för protokoll 4, numret som RFC 2003 tilldelar IPv4-i-IPv4-inkapsling, varken skapar den nästlade vägen eller håller den vid liv. IPIP-headern lever inuti den krypterade nyttolasten, där ingen kantbrandvägg ser den. Att öppna protokoll 4 ändå köper ingenting utöver en tillåten väg till in i värden.
Politik som nämner det ursprungliga paketets källor och destinationer hör hemma efter avkapslingen, på tunnelgränssnitten och i routingtabellen. Lägg den där, och kantregeln kan förbli stängd.
Vad WireGuard faktiskt validerar
AllowedIPs bedömer källan till det paket WireGuard bär, och det den bär är det IPIP-inkapslade paketet. En tillåten IPIP-källa accepteras även när headern inuti namnger en värd du helst inte vill routa till. Den ursprungliga källan är alltså inte det peer:n kontrollerade åt dig, och det inre adressparet behöver sin egen tillämpning efter avkapslingen.
Inpackningen ger routingstruktur, inte ett andra krypteringslager. Att kalla IPIP extra skydd inuti WireGuard beskriver en annan design.
Verifiera med en stege, inte en enda ping
Prova storlekar som omger den gräns du beräknade, och bekräfta sedan vad kärnan tror om båda enheterna. Med 1360 byte nyttolast plus 40 byte headers som ger 1400 passar den första ekot nedan, och det andra sitter en byte förbi taket:
ping -M do -s 1372 10.9.0.2
ping -M do -s 1373 10.9.0.2
wg show wg0
ip -d link show ipip0
En ren passage under taket och ett misslyckande vid den första storleken ovanför betyder att aritmetiken håller från början till slut. Kör sedan om överföringen som ursprungligen stoppade, eftersom en syntetisk sond bevisar budgeten och inte säger något om avsändarens egna skrivstorlekar. Om den nästlade vägen fortfarande bryts vid en storlek du har bevisat passar, undersök avkapslingen och rutterna till den bortre änden innan du skär tio byte till av MTU:n.