Tillåt en TLS-passthrough-anslutning i NGINX stream-kontext
NGINX kan neka ett TCP TLS-relä utan att avsluta TLS. Lägg tillståndsregeln i stream, inte i en HTTP location, och kontrollera vilken peer-adress som anländer.
Att vidarebefordra krypterade byte utan att någonsin inneha certifikatet är vad ett TLS-passthrough-relä gör, och upplägget är både praktiskt och lite förvirrande. Eftersom ingenting dekrypteras finns det ingenting HTTP-format att filtrera på, så det vanliga location-blocket och dess åtkomstregler har inget värde här. Det beslut NGINX har gäller själva anslutningen: vilken nätverkspeer som knackade på och om den peeren alls ska vidarebefordras.
Beslutet hör hemma i stream, inte i HTTP
I stream-kontexten arbetar NGINX med TCP-sessioner. Det ser anslutningens peer-adress och kan tillämpa ordnade allow- och deny-regler på den innan någon byte når backend. Det är ett fullständigt tillträdesbeslut och det kräver ingen privat nyckel, inget certifikat och ingen HTTP-tolkning.
| Mechanism | What it decides | Where it lives |
|---|---|---|
| stream allow/deny | Whether this TCP peer is relayed | stream server block |
| ssl_preread map | Which backend a named connection goes to | stream, with the preread module |
| HTTP location rule | Whether an HTTP request is served | http server block |
De tre raderna ersätter aldrig varandra. Att kopiera ett HTTP-åtkomstdirektiv till filen som nämner port 443 ändrar ingenting, eftersom stream-servern aldrig läser http-kontexten.
Tillåt anslutningen innan du vidarebefordrar den
Anta en befintlig installation med modulerna stream och stream-access tillgängliga, VPN-klienter som håller källadresser i 10.90.0.0/24, och en backend på 192.168.50.20:443 som redan levererar den avsedda HTTPS-identiteten.
stream {
server {
listen 443;
allow 10.90.0.0/24;
deny all;
proxy_pass 192.168.50.20:443;
}
}
Läs detta som ett fragment av en ny listener, inte som en direkt ersättning av en fungerande konfiguration. Granska befintliga listeners och includes först, eftersom en andra listener på en redan upptagen port misslyckas vid reload, inte vid begäran.
Lägg märke till vad som saknas: ingen listen ... ssl, inget certifikatdirektiv. NGINX vidarebefordrar det krypterade flödet, och backend avslutar TLS och presenterar certifikatet som klienten validerar. En klient som inte klarar allowlist får sin TCP-session nekad, inte en HTTP 403-sida, och alla verktyg som förväntar sig en statuskod rapporterar något oanvändbart.
Vad allowlist täcker och inte täcker
Om reläet redan väljer backends efter servernamn kan ssl_preread och en map fortsätta med det arbetet, förutsatt att modulen är tillgänglig. Namnet levereras fortfarande av klienten, och ingenting i att presentera ett namn bevisar att klienten har gått med i VPN:en.
Exempelregeln täcker hela stream-listenern. Det gör den olämplig för en enda ingångspunkt som betjänar en blandning av offentliga webbplatser och webbplatser endast för VPN, där ett undantag per namn skulle behövas; separata listeners är vanligtvis tydligare än en namnaberoende policy som ingen kan läsa.
Två ytterligare luckor är värda att nämna. En prefixmatchning säger ingenting om vilket gränssnitt paketet kom in på, och en HTTP-regel någon annanstans kan inte begränsa denna listener. Båda är skäl att hålla ingress-policyn på värdnivå i bilden i stället för att behandla en enda allow-rad som hela gränsen. Skriv ner gränsen som två kontroller som måste stämma överens, så att en ändring i endera granskas.
Vems adress ser NGINX egentligen?
En lastbalanserare, en annan proxy eller source NAT kan sätta en mellanhand framför NGINX, så peeren som observeras är inte VPN-klientens interna adress. Undersök den verkliga vägen innan du väljer ett prefix, eftersom en allowlist skriven för fel adress antingen släpper in alla bakom översättaren eller ingen.
PROXY-protokollet och hantering av riktig IP är legitima svar, och de får bara konfigureras för kompatibla, uttryckligen betrodda avsändare. Båda mekanismerna tror på vad avsändaren säger, och det är just därför avsändarlistan måste vara kort. Att lita på en identitetsheader från vilken internetklient som helst gör inte källinformationen pålitlig igen; det förvandlar ett korrekt avslag till ett förfalskat tillträde.
Testa båda utfallen före reload
Validera konfigurationen, gör reload och testa sedan två gånger: en ny tillåten session som måste fungera, och en nekad som inte får. Behåll normal backend-certifikatvalidering i det tillåtna testet, eftersom ett relä som ansluter men inte kan validera backend har löst ett problem och skapat ett annat.
nginx -t
ss -tnp | grep ':443'
Kontrollera också vägen till backend och svaret separat. Att klara allowlist bevisar bara att NGINX accepterade sessionen; det kan inte få en oåtkomlig backend att svara, och det kan inte reparera en returväg som saknades innan du började.