Nginx voor, privaat backend agter die VPN
Die blaaier praat met Nginx, en Nginx open ’n tweede verbinding in die tonnel in. Lei beide, verifieer beide sertifikate en hou openbare aansturings openbaar.
Volg een versoek van ’n selfoon in ’n trein tot by ’n backend wat net binne ’n private netwerk bestaan. Die selfoon los ’n openbare naam op, verbind na ’n openbare adres op poort 443 en voltooi ’n normale TLS-handdruk. Nginx aanvaar daardie verbinding en open dan ’n tweede, heeltemal aparte een na ’n adres wat dit net deur ’n VPN-koppelvlak bereik. Niks aan die selfoon verander nie, en die selfoon weet nooit dat ’n tonnel betrokke was nie.
Een versoek deur twee verbindings volg
Die inkomende been is ’n openbare HTTP-transaksie. Dit het ’n openbare naam, ’n openbare sertifikaat en ’n antwoordpad wat moet werk vir watter adres die besoeker ook al op daardie oomblik het. Enige verandering wat daardie pad versteur, breek alle besoekers gelyk. Daarom is die openbare been die een waarmee jy die minste wil eksperimenteer.
Die uitgaande been is privaat. Nginx word ’n kliënt, los ’n interne naam op of gebruik ’n vaste adres, en bereik ’n diens wat ’n verbinding van die internet sou weier.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Hou hulle apart in jou kop en die konfigurasie word vanselfsprekend. Smelt hulle saam, en jy eindig deur ’n openbare kliënt aan ’n tonnel te probeer laat deelneem, en dit is waar die meeste van die verwarring in hierdie ontwerp vandaan kom. Die private been mag broos wees. Die openbare been nie.
Voordat jy enigiets hiervan bou, bevestig dat die publikasie van die toepassing opsetlik is. ’n Werkende proxy is ook ’n werkende blootstelling, en die verifikasiemodel moet ’n besluit wees, nie ’n neweproduk nie.
Die poortnaam moet die tonnel oorleef
Daar skuil ’n subtiele lokval in naamoplossing. As private DNS dieselfde naam oorskryf wat die VPN-profiel vir sy eie poort gebruik, kan ’n herverbinding uiteindelik probeer om daardie poort deur die tonnel te bereik wat dit self moet bou. Die kliënt het daardie naam nodig voordat die tonnel bestaan. Sodra dit binne die tonnel opgelos word, kan die verbinding glad nie gebou word nie.
Gebruik afsonderlike goedgekeurde name vir die poort en die backend, en beperk die oplosser se beleid sodat elke naam na die adres oplos wat sy gebruiker nodig het. Om ’n toepassing se Host-opskrif te verander help niks hier nie, want dit is die VPN-kliënt wat die opsoek doen.
Dink dan aan omvang. Die frontend het ’n roete na die backend-adres nodig, en dit moet ook aanhou om openbare kliënte te antwoord. ’n Volle tonnel op daardie gasheer kan aan die eerste vereiste voldoen en die tweede breek.
Waar die beleid dit toelaat, is ’n tonnel na ’n spesifieke bestemming die skoner ontwerp. Waar die beleid ’n volle tonnel vereis, hoort die frontend in ’n aparte netwerkverband eerder as om met ad hoc-roetes vir bekende besoekers gelap te word.
Skryf die bedienerblok sodat albei bene verifieer
Veronderstel die backend bied ’n sertifikaat aan vir hierdie naam: backend.corp.example en antwoord op ’n private adres. Om aan ’n adres te koppel terwyl ’n naam geverifieer word, is presies waarvoor die proxy-module se SNI- en naamopsies is.
upstream private_app {
server 10.40.0.20:8443;
}
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/nginx/tls/app-fullchain.pem;
ssl_certificate_key /etc/nginx/tls/app-key.pem;
location / {
proxy_pass https://private_app;
proxy_ssl_server_name on;
proxy_ssl_name backend.corp.example;
proxy_ssl_trusted_certificate /etc/nginx/trust/backend-ca.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_set_header Host app.example.com;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Elke pad en adres hierbo is ’n plekhouer. Die belangrike dele is dié wat verifikasie aangeskakel hou: ’n naam om te kontroleer, ’n vertrouensbundel om dit teen te kontroleer, en ’n diepte wat by die goedgekeurde ketting pas.
proxy_set_header Host app.example.com is opsetlik. Die backend moet gekonfigureer word om daardie openbare oorsprong te aanvaar, en dit moet deurgestuurde opskrifte net van hierdie frontend vertrou. Om die X-Forwarded-For met die kliëntadres te oorskryf is reg vir ’n enkele proxy en verkeerd vir ’n ketting, so ’n ontplooiing met meer as een proxy het sy eie reëling vir vertroude adresse nodig.
Laat die openbare oorsprong soos een optree
Die toepassing moet absolute URL’s, aansturings en koekies vir die openbare oorsprong uitstuur. As dit ’n besoeker na backend.corp.example aanstuur, word daardie besoeker na ’n naam gestuur wat hy nie kan oplos nie.
Maak dit reg deur die toepassing se ondersteunde eksterne URL-instelling en ’n nagesiene aansturingsbeleid, nie deur gasheername in antwoordliggame te herskryf nie. Stringvervanging oor willekeurige inhoud breek ondertekende loonvragte en skep foute wat moeilik is om op te spoor.
Koekies verdien dieselfde sorg. ’n Koekie wat tot die private naam beperk is, sal nooit deur ’n blaaier gestuur word wat net die openbare een ken nie.
Bevestig ook dat Nginx werklik die openbare socket kan besit. ’n Bestaande webdiens op 443 moet skuif of die frontend moet elders woon, want twee prosesse kan nie dieselfde adres en poort bind nie.
Kontroleer elke been waar dit werklik loop
Valideer die konfigurasie met die geïnstalleerde ontleder voor enige herlaai, sodat ’n tikfout nie die luisteraar wat tans bedien, laat val nie.
Toets dan die backend-been vanaf die frontend-gasheer self, in dieselfde netwerkverband wat Nginx gebruik. ’n Ping deur die tonnel bewys bereikbaarheid en niks oor TLS, magtiging of die toepassing nie.
Laastens maak ’n vars openbare versoek na die werklike gasheernaam met normale sertifikaatverifikasie, en waarneem die antwoordpad eerder as net die antwoordliggaam.
Bewaar albei waarnemings saam met die ontplooide konfigurasie, en teken op wat gebeur wanneer die tonnel nie beskikbaar is nie. Die frontend behoort ’n beheerde upstream-fout te terugstuur, nie stilweg na ’n ander backend te val wat niemand gedokumenteer het nie. ’n 502 met ’n duidelike logreël is ’n goeie uitkoms. ’n Gekaste bladsy van ’n onbedoelde oorsprong is nie.