Een VPN-server die vanuit een mobiel netwerk antwoordt en vanaf de bank faalt, is meestal geen certificaatprobleem. De client binnen het LAN vraagt de router een pakket te vertalen waarvan de bestemming het eigen openbare adres van de router is, wat betekent dat het pakket naar buiten moet en meteen weer naar binnen moet. Die manoeuvre heet hairpinning, en veel routers implementeren die of helemaal niet of alleen wanneer een selectievakje is aangevinkt. Dat de test van buiten slaagt, maakt het verwarrend, want het bewijst dat de listener en de doorstuurregel in orde zijn.

Het pakket gaat naar buiten en komt weer binnen

Volg het pakket. De client lost de openbare naam op, verbindt met het openbare adres, en de destination-NAT van de router herschrijft de bestemming naar de interne server. Het antwoord van de server is gericht aan het LAN-adres van de client, dus het gaat terug via de LAN-interface van de router zonder ooit de NAT-regel te passeren die de bron terugvertaald zou hebben.

Nu ontvangt de client een pakket van een adres waar hij nooit iets naartoe heeft gestuurd, en gooit het weg. Die asymmetrie is de hele storing.

RFC 4787 beschrijft het gedrag dat in dit geval van een NAT wordt verwacht, en de korte versie is dat het in de praktijk optioneel is, zelfs waar het in theorie is gespecificeerd. Sommige routers noemen de instelling NAT loopback, andere noemen het hairpin NAT of NAT reflection, en sommige bieden helemaal niets. Een router zonder die functie is niet verkeerd geconfigureerd; hij doet het gewone, en de oplossing hoort elders. Trek uit een mislukte lokale test niet de conclusie dat de openbare doorstuurregel fout is.

Controle 1: test de twee paden apart

Verbind van buiten het LAN met hetzelfde profiel dat een echte gebruiker zou gebruiken en bevestig dat de sessie tot stand komt. Verbind van binnen met hetzelfde profiel naar het openbare adres en noteer de exacte fout en het tijdstip.

Een precieze lokale test behoudt de hostnaam en vervangt alleen het adres: curl -v --resolve vpn.example.com:443:203.0.113.10 https://vpn.example.com/ stuurt het verzoek naar het openbare adres terwijl het nog steeds de juiste servernaam presenteert. Dat scheidt een naamoplossingsprobleem van een vertaalprobleem, die makkelijk te verwarren zijn wanneer dezelfde naam vanuit een café werkt. Let op of de client faalt bij de TCP-verbinding of later bij TLS, want het eerste wijst op vertaling en het tweede op identiteit.

Controle 2: lees wat de server ziet

De nuttigste observatie is het zicht van de server. Start een opname op de VPN-host, gefilterd op het LAN-adres van de client en op het LAN-adres van de router, en herhaal dan de lokale poging. Als er niets aankomt, heeft het pakket de vertaling niet overleefd.

Als er een verbinding binnenkomt vanaf het LAN-adres van de router in plaats van dat van de client, gebeurt er hairpinning en is de bron herschreven. Dat is een werkende configuratie, geen storing.

Controle 3: los het op zonder het buitenpad aan te raken

Er zijn drie ondersteunde vormen, in toenemende mate van impact. De smalste is gesplitst DNS: publiceer een intern record zodat dezelfde servernaam voor clients in het LAN naar het interne adres oplost, wat het openbare pad volledig vermijdt. De volgende is de gedocumenteerde loopback- of reflection-optie van de router inschakelen, als die er is, en die alleen op deze dienst toepassen. De breedste is een source-NAT-regel op de router die verkeer uit het LAN naar de server herschrijft zodat het antwoord via de router terugkomt; op een Linux-router is dat een MASQUERADE-regel in POSTROUTING, die overeenkomt met het adres en de poort van de server. Alle drie laten het externe pad ongemoeid, en dat is de eigenschap die behouden moet blijven.

Breid niet-gerelateerde port forwarding niet uit om het lokale pad op het externe te laten lijken, en verplaats de dienst niet naar een andere poort om het probleem te omzeilen. Beide wijzigingen veranderen wat de buitenwereld kan bereiken om iets op te lossen dat alleen de binnenwereld ziet.

Gesplitst DNS heeft één valkuil die het noemen waard is. Een hostnaam vervangen door een willekeurig IP verandert wat de client valideert, dus het interne record moet nog steeds overeenkomen met de naam in het certificaat.

Controle 4: verifieer daarna beide paden

Herhaal de externe poging van buiten het LAN, herhaal de interne poging met hetzelfde profiel, en bevestig dat het serverlog twee afzonderlijke geslaagde sessies toont in plaats van één succes en één stilte. Controleer daarna of andere clients de listener nog bereiken en of de routes naar privébronnen ongewijzigd zijn.

Houd de notitie kort: welk adres elke client gebruikte, wat de server zag en welke van de drie oplossingen is toegepast. De hairpinning-eisen uit RFC 4787 zijn de referentie voor wat hier van een NAT wordt verwacht, en ze leggen uit waarom een router zonder de functie zich normaal gedraagt. Een lokale fout die de buitenwereld niet kan reproduceren is een vertaalvraag tot het tegendeel is bewezen, dus test het als zodanig.

Gerelateerde artikelen