Nginx përpara, backend privat pas VPN-së
Shfletuesi flet me Nginx, dhe Nginx hap një lidhje të dytë brenda tunelit. Drejto të dyja, verifiko të dy certifikatat dhe mbaji publikë ridrejtimet publike.
Ndiq një kërkesë nga një telefon në një tren deri te një backend që ekziston vetëm brenda një rrjeti privat. Telefoni zgjidh një emër publik, lidhet me një adresë publike në portën 443 dhe përfundon një shtrëngim dore TLS normal. Nginx e pranon atë lidhje dhe më pas hap një të dytë, plotësisht të veçantë, drejt një adrese që e arrin vetëm përmes një ndërfaqeje VPN. Asgjë në telefon nuk ndryshon, dhe telefoni nuk e mëson kurrë se ishte përfshirë një tunel.
Ndiqja e një kërkese përmes dy lidhjeve
Segmenti hyrës është një transaksion HTTP publik. Ai ka një emër publik, një certifikatë publike dhe një rrugë përgjigjeje që duhet të funksionojë për çdo adresë që vizitori ka në atë moment. Çdo ndryshim që e prish atë rrugë prish të gjithë vizitorët përnjëherë. Prandaj segmenti publik është ai ku dëshiron më së paku të eksperimentosh.
Segmenti dalës është privat. Nginx bëhet klient, zgjidh një emër të brendshëm ose përdor një adresë fikse, dhe arrin një shërbim që do të refuzonte një lidhje nga interneti.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Mbaji të ndarë në mendje dhe konfigurimi bëhet i dukshëm. Nëse i përziejnë, do të përfundosh duke u përpjekur të bësh një klient publik të marrë pjesë në një tunel, dhe që andej vjen pjesa më e madhe e konfuzionit në këtë dizajn. Segmenti privat mund të jetë i brishtë. Ai publik jo.
Përpara se të ndërtosh ndonjë nga këto, konfirmo që publikimi i aplikacionit është i qëllimshëm. Një proxy që funksionon është gjithashtu një ekspozim që funksionon, dhe modeli i autentikimit duhet të jetë një vendim, jo një efekt anësor.
Emri i portës duhet t'i mbijetojë tunelit
Ka një kurth delikat në zgjidhjen e emrave. Nëse DNS privat mbivendos të njëjtin emër që profili VPN përdor për portën e vet, një rilidhje mund të përfundojë duke u përpjekur ta arrijë atë portë përmes tunelit që supozohet se duhet të ndërtojë vetë. Klienti ka nevojë që ai emër të zgjidhet përpara se tuneli të ekzistojë. Pasi zgjidhet brenda tunelit, lidhja nuk mund të ndërtohet fare.
Përdor emra të miratuar të ndryshëm për portën dhe backend-in, dhe kufizo politikën e zgjidhësit që çdo emër të zgjidhet në adresën që i duhet konsumatorit të tij. Ndryshimi i kokës Host të një aplikacioni nuk ndihmon këtu, sepse klienti VPN është ai që bën kërkimin.
Pastaj mendo për shtrirjen. Frontend-i ka nevojë për një rrugë drejt adresës së backend-it, dhe gjithashtu duhet të vazhdojë t'u përgjigjet klientëve publikë. Një tunel i plotë në atë host mund të plotësojë kërkesën e parë dhe të prishë të dytën.
Aty ku politika e lejon, një tunel drejt një destinacioni të caktuar është dizajni më i pastër. Aty ku politika kërkon një tunel të plotë, frontend-i i përket një konteksti të veçantë rrjeti në vend që të arnohet me rrugë ad hoc për vizitorë të njohur.
Shkruaj bllokun e serverit që të dy segmentet të verifikojnë
Supozojmë se backend-i paraqet një certifikatë për këtë emër: backend.corp.example dhe përgjigjet në një adresë private. Lidhja me një adresë ndërsa verifikohet një emër është pikërisht qëllimi i opsioneve SNI dhe të emrit të modulit proxy.
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;
}
}
Çdo rrugë dhe adresë më sipër është një vendmbajtëse. Pjesët e rëndësishme janë ato që e mbajnë verifikimin të ndezur: një emër për të kontrolluar, një paketë besimi për ta kontrolluar kundrejt saj, dhe një thellësi që përputhet me zinxhirin e miratuar.
proxy_set_header Host app.example.com është i qëllimshëm. Backend-i duhet të konfigurohet të pranojë atë origjinë publike, dhe duhet t'u besojë kokave të përcjella vetëm nga ky frontend. Të mbishkruash X-Forwarded-For me adresën e klientit është e saktë për një proxy të vetëm dhe e gabuar për një zinxhir, prandaj një vendosje me shumë proxy ka nevojë për rregullimin e vet të adresave të besuara.
Bëje origjinën publike të sillet si origjinë publike
Aplikacioni duhet të lëshojë URL absolute, ridrejtime dhe cookie për origjinën publike. Nëse ridrejton një vizitor te backend.corp.example, ai vizitor dërgohet në një emër që nuk mund ta zgjidhë.
Rregulloje këtë përmes cilësimit të URL-së së jashtme që aplikacioni mbështet dhe një politike ridrejtimi të rishikuar, jo duke rishkruar emrat e hostit në trupat e përgjigjeve. Zëvendësimi i vargjeve në përmbajtje arbitrare prish ngarkesat e nënshkruara dhe krijon gabime të vështira për t'u gjurmuar.
Cookie-t meritojnë të njëjtin kujdes. Një cookie e kufizuar në emrin privat nuk do të dërgohet kurrë nga një shfletues që njeh vetëm atë publik.
Konfirmo gjithashtu se Nginx mund të zotërojë vërtet socket-in publik. Një shërbim web ekzistues në 443 duhet të zhvendoset ose frontend-i duhet të jetojë diku tjetër, sepse dy procese nuk mund të lidhin të njëjtën adresë dhe portë.
Kontrollo çdo segment aty ku ekzekutohet vërtet
Valido konfigurimin me analizuesin e instaluar përpara çdo ringarkimi, që një gabim shtypi të mos rrëzojë dëgjuesin që po shërben tani.
Pastaj provo segmentin e backend-it nga vetë hosti i frontend-it, në të njëjtin kontekst rrjeti që përdor Nginx. Një ping përmes tunelit provon arritshmërinë dhe asgjë për TLS, autorizimin ose aplikacionin.
Së fundi bëj një kërkesë publike të re drejt emrit të vërtetë të hostit me verifikim normal certifikate, dhe vëzhgo rrugën e përgjigjes e jo vetëm trupin.
Ruaj të dy vëzhgimet bashkë me konfigurimin e vendosur, dhe shëno çfarë ndodh kur tuneli nuk është i disponueshëm. Frontend-i duhet të kthejë një gabim upstream të kontrolluar, jo të bjerë në heshtje mbi një backend tjetër që askush nuk e ka dokumentuar. Një 502 me një rresht të qartë logu është rezultat i mirë. Një faqe e ruajtur në cache nga një origjinë e paqëllimshme nuk është.