Versleutelde bytes doorsturen zonder ooit het certificaat te bezitten is wat een TLS-passthrough-relay doet, en de opzet is zowel handig als enigszins verwarrend. Omdat niets wordt ontsleuteld, is er niets HTTP-vormigs om op te filteren, dus het gebruikelijke location-blok en zijn toegangsregels hebben hier geen nut. De beslissing die NGINX heeft, gaat over de verbinding zelf: welke netwerkpeer heeft aangeklopt, en of die peer überhaupt moet worden doorgestuurd.

De beslissing hoort in stream, niet in HTTP

In de stream-context werkt NGINX met TCP-sessies. Het ziet het peer-adres van de verbinding en kan daar geordende allow- en deny-regels op toepassen voordat er ook maar één byte de backend bereikt. Dat is een volledige toelatingsbeslissing, en die vereist geen privésleutel, certificaat of HTTP-parsing.

MechanismWhat it decidesWhere it lives
stream allow/denyWhether this TCP peer is relayedstream server block
ssl_preread mapWhich backend a named connection goes tostream, with the preread module
HTTP location ruleWhether an HTTP request is servedhttp server block

Die drie regels vervangen elkaar nooit. Een HTTP-toegangsdirectief kopiëren naar het bestand dat poort 443 noemt, verandert niets, omdat de stream-server de http-context nooit leest.

Sta de verbinding toe voordat je haar doorstuurt

Ga uit van een bestaande installatie met de modules stream en stream-access beschikbaar, VPN-clients die bronadressen in 10.90.0.0/24 houden, en een backend op 192.168.50.20:443 die al de bedoelde HTTPS-identiteit levert.

stream {
    server {
        listen 443;

        allow 10.90.0.0/24;
        deny all;

        proxy_pass 192.168.50.20:443;
    }
}

Lees dit als een fragment van een nieuwe listener, niet als een directe vervanging van een werkende configuratie. Bekijk eerst de bestaande listeners en includes, want een tweede listener op een al bezette poort faalt bij reload, niet op het moment van het verzoek.

Let op wat ontbreekt: geen listen ... ssl, geen certificaatdirectief. NGINX stuurt de versleutelde stroom door, en de backend beëindigt TLS en presenteert het certificaat dat de client valideert. Een client die de allowlist niet haalt, krijgt zijn TCP-sessie geweigerd, geen HTTP 403-pagina, en elk hulpmiddel dat een statuscode verwacht, meldt iets nutteloos.

Wat de allowlist dekt en wat niet

Als de relay al backends op servernaam kiest, kunnen ssl_preread en een map dat werk blijven doen, mits de module beschikbaar is. De naam wordt nog steeds door de client geleverd, en niets aan het presenteren van een naam bewijst dat de client lid is geworden van de VPN.

De voorbeeldregel dekt de hele stream-listener. Dat maakt hem ongeschikt voor één toegangspunt dat een mix van openbare en alleen-VPN-sites bedient, waar een uitzondering per naam nodig zou zijn; aparte listeners zijn meestal duidelijker dan een naamafhankelijk beleid dat niemand kan lezen.

Twee verdere hiaten zijn het noemen waard. Een prefix-match zegt niets over via welke interface het pakket binnenkwam, en een HTTP-regel elders kan deze listener niet beperken. Beide zijn redenen om het ingress-beleid op hostniveau in beeld te houden in plaats van één allow-regel als de hele grens te behandelen. Schrijf de grens op als twee controles die moeten overeenkomen, zodat een wijziging aan een van beide wordt beoordeeld.

Wiens adres ziet NGINX werkelijk?

Een load balancer, een andere proxy of source NAT kan een tussenpersoon voor NGINX zetten, dus de peer die wordt gezien is niet het interne adres van de VPN-client. Onderzoek het echte pad voordat je een prefix kiest, want een allowlist die voor het verkeerde adres is geschreven, laat iedereen achter de vertaler door of niemand.

Het PROXY-protocol en de omgang met echte IP’s zijn legitieme antwoorden, en ze mogen alleen worden geconfigureerd voor compatibele, expliciet vertrouwde afzenders. Beide mechanismen geloven wat de afzender zegt, en dat is precies waarom de afzenderlijst kort moet zijn. Een identiteitsheader van elke internetclient vertrouwen maakt de broninformatie niet opnieuw betrouwbaar; het verandert een correcte weigering in een vervalste toelating.

Test beide uitkomsten voor de reload

Valideer de configuratie, doe een reload en test dan twee keer: een nieuwe toegestane sessie die moet werken, en een geweigerde die niet mag. Houd de normale backend-certificaatvalidatie in de toegestane test, want een relay die verbindt maar de backend niet kan valideren, heeft één probleem opgelost en een ander gecreëerd.

nginx -t
ss -tnp | grep ':443'

Controleer ook de route naar de backend en het antwoord afzonderlijk. De allowlist halen bewijst alleen dat NGINX de sessie heeft geaccepteerd; het kan een onbereikbare backend niet laten antwoorden, en het kan een retourpad dat ontbrak voordat je begon niet repareren.

Gerelateerde artikelen