De tunnel verbindt vanaf een thuisverbinding en stokt op een hotel- of kantoornetwerk, en het verplaatsen van de server naar poort 443 veranderde niets. Dat resultaat is algemeen genoeg om een vorm te hebben: de poort was het makkelijke deel, en de rest van de beslissing hoort bij alles wat tussen de client en de server zit. Twee vragen beslechten de meeste gevallen, en geen van beide gaat over cijfers. Accepteert het netwerk een TLS-handshake naar dat adres, en houdt de client een route naar zijn eigen wrapper zolang de tunnel omhoog staat?

De handshake verraadt meer dan het nummer

Een native VPN-listener op TCP 443 spreekt vanaf het eerste pakket zijn eigen protocol. Een ClientHello heeft een versieveld, een willekeurige waarde en een lijst extensies, en een apparaat dat een paar honderd bytes leest, ziet het verschil zonder iets te ontsleutelen. Poortnummers zijn goedkoop te bevredigen, en de vorm van het protocol is wat het filter werkelijk controleert. Regels worden meestal ook per protocol geschreven, dus een beleid dat TLS inspecteert zegt niets over UDP.

Een transparante proxy die op een geldige TLS-sessie staat, laat de verbinding tijdens het opzetten vallen, vaak nadat de TCP-handshake is voltooid. Dat detail telt later, want het betekent dat het clientlog stopt nadat de socket is opgezet.

De stroom inpakken maakt twee faalpunten

Een TLS-wrapper zoals stunnel herstelt de verwachte vorm: de client verbindt met een lokale listener, de wrapper opent een echte TLS-sessie naar de server op 443, en een tweede wrapper op de server geeft de ontsleutelde bytes door aan de VPN-daemon. De buitenste sessie ziet er nu uit als elke andere HTTPS-verbinding. De VPN-daemon op de server zou alleen op loopback moeten luisteren, want niets buiten de wrapper hoeft hem te bereiken.

Drie afzonderlijke dingen moeten voor dat ontwerp kloppen. Het clientprofiel wijst naar de lokale listener, het servercertificaat past bij de naam die de client verifieert, en de doorstuur op de serverside richt zich op de poort die de daemon echt gebruikt. Heb je er één fout, dan sterft de verbinding voordat de VPN-laag wordt bereikt. Een certificaatafwijking verschijnt dan als een wrapperfout en niet als een VPN-fout, en daarom loont het beide logs naast elkaar te lezen.

De route naar de wrapper is de valkuil

Zodra de tunnel omhoog komt, wijst de standaardroute erin, en de buitenste TLS-sessie heeft een pad nodig dat niet in de tunnel komt die zij draagt. Een gewone VPN-client beschermt het adres dat hij belt; een ingepakte client belt zijn eigen loopback, dus het bestemmingsadres van de wrapper is onzichtbaar voor die bescherming.

sudo ip route add 198.51.100.20 via 192.168.0.1
sudo openvpn --config client.ovpn
sudo ip route del 198.51.100.20

De exacte adressen vult u zelf in, en de route moet het hele leven van de verbinding bestaan, niet alleen bij het opstarten. Een klein wrapperscript dat de route voor de client toevoegt en daarna verwijdert, is betrouwbaarder dan een onthouden commando.

Op Android is het equivalent van die uitzondering een instelling per app: sluit de wrapper-app uit van de tunnel zodat het eigen verkeer via de mobiele verbinding naar buiten gaat. Zonder de uitsluiting wordt de wrapper in de tunnel geleid die hij probeert te bouwen, en de herverbindingslus lijkt op een serverprobleem.

Lees de timing voordat u iets verandert

Een sessie die elke keer na hetzelfde interval sterft, is een handtekening van beleid en geen cryptografische fout, en langdurige stroomlimieten produceren precies dat patroon. Een verbinding die direct na de handshake wordt gereset, wijst op een proxy die de certificaatketen niet beviel.

Vergelijk de uitgever van het certificaat van een gewone HTTPS-site vanaf beide netwerken. Als de uitgever op het beperkte netwerk anders is, beëindigt iets TLS in het midden, en geen enkele wrapper overleeft die onderschepping ongewijzigd. Dezelfde vergelijking vertelt u of de blokkade op uw servernaam of op elke TLS-sessie op dat adres is gericht.

Schrijf het waargenomen gedrag op: hoe lang de sessie duurde, of de socket opende, of de wrapper een handshake logde. Elk daarvan vernauwt de volgende test.

Test één variabele tegelijk

Controleer eerst UDP, want sommige netwerken gooien het volledig weg en een UDP-fout zegt niets over 443. Probeer daarna TCP 443 zonder de wrapper, dan de wrapper op 443. Lees het clientlog bij elke stap en stop zodra het gedrag verandert.

Verander één element per poging. Een nieuwe poort, een nieuwe wrapper en een nieuwe cipher in dezelfde run laten u niet zeggen welke van de drie telde.

Gerelateerde artikelen