Leisti TLS passthrough ryšį NGINX stream kontekste
NGINX gali atmesti TCP TLS relay neužbaigęs TLS. Įdėkite leidimo taisyklę į stream, o ne į HTTP location, ir patikrinkite, koks peer adresas ateina.
Šifruotų baitų persiuntimas niekada neturint sertifikato yra tai, ką daro TLS passthrough relay, ir ši tvarka yra patogi bei kartu kiek paini. Kadangi niekas neiššifruojama, nėra nieko HTTP formos, ką būtų galima filtruoti, todėl įprastas location blokas ir jo prieigos taisyklės čia nieko neduoda. NGINX turimas sprendimas susijęs su pačiu ryšiu: kuris tinklo peer pasibeldė ir ar tą peer apskritai reikia persiųsti.
Sprendimas priklauso stream, o ne HTTP
stream kontekste NGINX dirba su TCP sesijomis. Jis mato ryšio peer adresą ir gali jam taikyti iš eilės allow ir deny taisykles, kol dar nė vienas baitas nepasiekė backend. Tai išsamus priėmimo sprendimas, ir jam nereikia privataus rakto, sertifikato ar HTTP analizės.
| 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 |
Tos trys eilutės niekada nepakeičia viena kitos. HTTP prieigos direktyvos kopijavimas į bet kurį failą, kuriame minimas 443 prievadas, nieko nekeičia, nes stream serveris niekada neskaito http konteksto.
Priimkite ryšį prieš jį persiųsdami
Tarkime, kad yra esama instaliacija su stream ir stream-access moduliais, VPN klientai laiko šaltinio adresus 10.90.0.0/24, o backend adresu 192.168.50.20:443 jau teikia numatytą HTTPS tapatybę.
stream {
server {
listen 443;
allow 10.90.0.0/24;
deny all;
proxy_pass 192.168.50.20:443;
}
}
Skaitykite tai kaip naujo listener fragmentą, o ne kaip tiesioginį veikiančios konfigūracijos pakaitalą. Pirmiausia peržiūrėkite esamus listener ir include, nes antras listener jau užimtame prievade nepavyksta reload metu, o ne užklausos metu.
Atkreipkite dėmesį, ko trūksta: nėra listen ... ssl, nėra sertifikato direktyvos. NGINX persiunčia šifruotą srautą, o backend užbaigia TLS ir pateikia sertifikatą, kurį klientas patikrina. Klientas, nepraėjęs allowlist, gauna atmestą TCP sesiją, o ne HTTP 403 puslapį, ir bet kokia priemonė, kuri tikisi būsenos kodo, praneš ką nors nenaudingo.
Ką allowlist apima, o ko ne
Jei relay jau renkasi backend pagal serverio vardą, ssl_preread ir map gali tęsti šį darbą, jei modulis prieinamas. Vardą vis tiek pateikia klientas, ir niekas vardo pateikime neįrodo, kad klientas prisijungė prie VPN.
Pavyzdinė taisyklė apima visą stream listener. Tai daro ją netinkamą vienam įėjimo taškui, kuris aptarnauja viešų ir tik VPN skirtų svetainių mišinį, kur prireiktų išimties pagal vardą; atskiri listener paprastai yra aiškesni nei nuo vardo priklausanti politika, kurios niekas negali perskaityti.
Verta įvardyti dar dvi spragas. Prefiksų atitikimas nieko nesako apie tai, per kurią sąsają paketas atėjo, o HTTP taisyklė kitur negali apriboti šio listener. Abi yra priežastys laikyti host lygmens ingress politiką vaizde, o ne vieną allow eilutę laikyti visa riba. Užrašykite ribą kaip du valdiklius, kurie turi sutapti, kad bet kurio jų pakeitimas būtų peržiūrėtas.
Kieno adresą NGINX iš tikrųjų mato?
Apkrovos balansuotojas, kitas proxy arba source NAT gali pastatyti tarpininką prieš NGINX, todėl stebimas peer nėra vidinis VPN kliento adresas. Ištirkite tikrąjį kelią prieš pasirinkdami prefiksą, nes neteisingam adresui parašyta allowlist arba įleidžia visus už vertėjo, arba nieko.
PROXY protokolas ir tikrojo IP apdorojimas yra teisėti atsakymai, ir jie turi būti konfigūruojami tik suderinamiems, aiškiai patikimiems siuntėjams. Abu mechanizmai tiki tuo, ką sako siuntėjas, ir būtent todėl siuntėjų sąrašas turi būti trumpas. Pasitikėjimas tapatybės antrašte iš bet kurio interneto kliento nepadaro šaltinio informacijos vėl patikimos; tai paverčia teisingą atmetimą suklastotu priėmimu.
Išbandykite abu rezultatus prieš reload
Patikrinkite konfigūraciją, atlikite reload, tada išbandykite du kartus: naują leidžiamą sesiją, kuri turi veikti, ir atmestą, kuri neturi. Palikite įprastą backend sertifikato tikrinimą leidžiamame teste, nes relay, kuris prisijungia, bet negali patikrinti backend, išsprendė vieną problemą ir sukūrė kitą.
nginx -t
ss -tnp | grep ':443'
Patikrinkite ir maršrutą į backend, ir atsakymą atskirai. Allowlist praėjimas įrodo tik tai, kad NGINX priėmė sesiją; jis negali priversti nepasiekiamo backend atsakyti ir negali sutaisyti grįžimo kelio, kurio trūko prieš pradedant.