Hairpin-NAT: varför VPN-slutpunkten misslyckas inifrån
En lokal klient som använder den publika adressen lämnar LAN:et och kommer tillbaka in. När routern inte gör hairpin fungerar det utifrån men inte inifrån.
En VPN-server som svarar från ett mobilnät men misslyckas från soffan är oftast inte ett certifikatproblem. Klienten inne i LAN:et ber routern översätta ett paket vars destination är routerns egen publika adress, vilket innebär att paketet måste gå ut och komma direkt in igen. Den manövern kallas hairpinning, och många routrar implementerar den antingen inte alls eller bara när en kryssruta är ikryssad. Det är att testet utifrån lyckas som gör saken förvirrande, eftersom det bevisar att lyssnaren och vidarebefordringsregeln är i ordning.
Paketet går ut och kommer in igen
Följ paketet. Klienten slår upp det publika namnet, ansluter till den publika adressen, och routerns destinations-NAT skriver om destinationen till den interna servern. Serverns svar är adresserat till klientens LAN-adress, så det går tillbaka genom routerns LAN-gränssnitt utan att någonsin passera NAT-regeln som skulle ha översatt källan tillbaka.
Nu tar klienten emot ett paket från en adress som den aldrig har skickat något till, och kastar det. Den asymmetrin är hela felet.
RFC 4787 beskriver det beteende som förväntas av ett NAT i det här fallet, och kortversionen är att det i praktiken är valfritt även där det är specificerat i teorin. En del routrar kallar inställningen NAT loopback, andra kallar den hairpin NAT eller NAT reflection, och en del visar ingenting alls. En router som saknar den är inte felkonfigurerad; den gör det vanliga, och rättelsen hör hemma någon annanstans. Dra inte slutsatsen från ett misslyckat lokalt test att den publika vidarebefordringsregeln är fel.
Kontroll 1: testa de två vägarna var för sig
Från utsidan av LAN:et ansluter du med samma profil som en riktig användare skulle använda och bekräftar att sessionen upprättas. Inifrån ansluter du till den publika adressen med samma profil och noterar det exakta felet och tiden.
Ett exakt lokalt test behåller värdnamnet och ersätter bara adressen: curl -v --resolve vpn.example.com:443:203.0.113.10 https://vpn.example.com/ skickar begäran till den publika adressen samtidigt som den fortfarande presenterar rätt servernamn. Det skiljer ett namnupplösningsproblem från ett översättningsproblem, som är lätta att blanda ihop när samma namn fungerar från ett kafé. Notera om klienten misslyckas vid TCP-anslutningen eller senare vid TLS, eftersom det första pekar på översättning och det andra på identitet.
Kontroll 2: läs vad servern ser
Den mest användbara observationen är serverns syn. Kör en inspelning på VPN-värden filtrerad på klientens LAN-adress och på routerns LAN-adress, och upprepa sedan det lokala försöket. Om ingenting kommer fram överlevde paketet inte översättningen.
Om en anslutning kommer från routerns LAN-adress i stället för klientens sker hairpinning och källan skrevs om. Det är en fungerande konfiguration, inte ett fel.
Kontroll 3: åtgärda utan att röra den yttre vägen
Det finns tre stödda former, i stigande ordning efter påverkan. Den snävaste är delad DNS: publicera en intern post så att samma servernamn löses till den interna adressen för klienter i LAN:et, vilket helt undviker den publika vägen. Nästa är att aktivera routerns dokumenterade loopback- eller reflection-alternativ, om det finns, och bara tillämpa det på den här tjänsten. Den bredaste är en source-NAT-regel på routern som skriver om trafik från LAN:et till servern så att svaret kommer tillbaka genom routern; på en Linux-router är det en MASQUERADE-regel i POSTROUTING, som matchar serverns adress och port. Alla tre lämnar den yttre vägen orörd, och det är egenskapen som ska bevaras.
Utöka inte orelaterad portvidarebefordran för att få den lokala vägen att likna den yttre, och flytta inte tjänsten till en annan port för att kringgå problemet. Båda ändringarna förändrar vad omvärlden kan nå, för att åtgärda något som bara den inre världen ser.
Delad DNS har en fälla som är värd att nämna. Att ersätta ett värdnamn med en godtycklig IP ändrar vad klienten validerar, så den interna posten måste fortfarande matcha namnet i certifikatet.
Kontroll 4: verifiera båda vägarna efteråt
Upprepa det yttre försöket från utsidan av LAN:et, upprepa det inre försöket med samma profil, och bekräfta att serverloggen visar två separata lyckade sessioner i stället för en framgång och en tystnad. Kontrollera sedan att andra klienter fortfarande når lyssnaren och att rutterna till privata resurser är oförändrade.
Håll anteckningen kort: vilken adress varje klient använde, vad servern såg och vilken av de tre åtgärderna som tillämpades. Hairpinning-kraven i RFC 4787 är referensen för vad ett NAT förväntas göra här, och de förklarar varför en router utan funktionen beter sig normalt. Ett lokalt fel som omvärlden inte kan återskapa är en översättningsfråga tills motsatsen är bevisad, så testa det som sådant.