Nginx sa harap, pribadong backend sa likod ng VPN
Ang browser ay kausap ang Nginx, at ang Nginx ay nagbubukas ng ikalawang koneksyon papasok sa tunnel. I-route ang dalawa, i-verify ang dalawang certificate, at panatilihing pampubliko ang mga pampublikong redirect.
Sundan ang isang request mula sa teleponong nasa tren hanggang sa backend na umiiral lamang sa loob ng pribadong network. Nire-resolve ng telepono ang pampublikong pangalan, kumokonekta sa pampublikong address sa port 443, at tinatapos ang normal na TLS handshake. Tinatanggap ng Nginx ang koneksyong iyon at pagkatapos ay nagbubukas ng ikalawa, ganap na hiwalay, patungo sa address na naaabot lamang nito sa pamamagitan ng VPN interface. Walang nagbabago sa telepono, at hindi kailanman nalalaman ng telepono na may tunnel na kasangkot.
Sundan ang isang request sa dalawang koneksyon
Ang papasok na bahagi ay isang pampublikong HTTP transaction. Mayroon itong pampublikong pangalan, pampublikong certificate, at landas ng tugon na dapat gumana para sa anumang address na hawak ng bisita sa sandaling iyon. Ang anumang pagbabago na gumugulo sa landas na iyon ay sabay na sisira sa lahat ng bisita. Kaya nga ang pampublikong bahagi ang pinakaaayaw mong subukan.
Ang palabas na bahagi ay pribado. Nagiging kliyente ang Nginx, nire-resolve ang panloob na pangalan o gumagamit ng nakapirming address, at naaabot ang serbisyong tatanggihan ang koneksyon mula sa internet.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Panatilihin silang hiwalay sa isip at magiging malinaw ang configuration. Pagsamahin sila, at sa huli ay susubukan mong ipasali ang isang pampublikong kliyente sa tunnel, at doon nagmumula ang karamihan ng kalituhan sa disenyong ito. Ang pribadong bahagi ay maaaring marupok. Ang pampublikong bahagi ay hindi.
Bago magtayo ng anuman dito, tiyakin na sinasadya ang paglalathala ng aplikasyon. Ang gumaganang proxy ay gumaganang paglalantad din, at ang modelo ng pagpapatotoo ay dapat maging desisyon, hindi side effect.
Dapat mabuhay ang pangalan ng gateway sa tunnel
May banayad na bitag sa pag-resolve ng pangalan. Kung ang pribadong DNS ay nagsasapaw sa parehong pangalan na ginagamit ng VPN profile para sa sarili nitong gateway, ang muling pagkonekta ay maaaring mauwi sa pagtatangkang maabot ang gateway na iyon sa pamamagitan ng tunnel na dapat sana nitong itayo. Kailangan ng kliyente na ma-resolve ang pangalang iyon bago pa umiral ang tunnel. Kapag ito ay na-resolve sa loob ng tunnel, hindi na maitatayo ang koneksyon.
Gumamit ng magkaibang aprubadong pangalan para sa gateway at backend, at limitahan ang patakaran ng resolver upang ang bawat pangalan ay ma-resolve sa address na kailangan ng gumagamit nito. Walang tulong dito ang pagpapalit ng Host header ng aplikasyon, dahil ang VPN client ang gumagawa ng paghahanap.
Pagkatapos, isipin ang saklaw. Kailangan ng frontend ang ruta patungo sa address ng backend, at kailangan din nitong patuloy na sagutin ang mga pampublikong kliyente. Ang buong tunnel sa host na iyon ay maaaring matugunan ang unang pangangailangan at sirain ang pangalawa.
Kung saan pinapayagan ng patakaran, ang tunnel patungo sa tiyak na destinasyon ay ang mas malinaw na disenyo. Kung saan ipinag-uutos ng patakaran ang buong tunnel, nabibilang ang frontend sa hiwalay na konteksto ng network sa halip na tagpian ng pansamantalang ruta para sa mga kilalang bisita.
Isulat ang server block upang parehong bahagi ay mag-verify
Ipagpalagay na ang backend ay nagpapakita ng certificate para sa pangalang ito: backend.corp.example at tumutugon sa pribadong address. Ang kumonekta sa address habang nagbe-verify ng pangalan ay eksaktong layunin ng SNI at pangalan na mga opsyon ng proxy module.
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;
}
}
Ang bawat landas at address sa itaas ay placeholder. Ang mahalaga ay ang mga bahaging nagpapanatiling bukas ang verification: isang pangalang susuriin, isang trust bundle na pagbabatayan, at lalim na tumutugma sa aprubadong chain.
proxy_set_header Host app.example.com ay sinasadya. Dapat i-configure ang backend na tanggapin ang pampublikong pinagmulan na iyon, at dapat lamang itong magtiwala sa mga forwarded header mula sa frontend na ito. Ang pag-overwrite ng X-Forwarded-For gamit ang address ng kliyente ay tama para sa isang proxy at mali para sa isang chain, kaya ang deployment na may maraming proxy ay nangangailangan ng sarili nitong kaayusan ng pinagkakatiwalaang address.
Gawing kumilos ang pampublikong pinagmulan na parang pampublikong pinagmulan
Dapat maglabas ang aplikasyon ng absolute na URL, redirect, at cookie para sa pampublikong pinagmulan. Kung ire-redirect nito ang bisita sa backend.corp.example, ipapadala ang bisitang iyon sa pangalang hindi nito ma-resolve.
Ayusin iyon sa pamamagitan ng sinusuportahang external URL setting ng aplikasyon at sinuring patakaran sa redirect, hindi sa pamamagitan ng muling pagsulat ng mga hostname sa mga response body. Ang pagpapalit ng string sa arbitraryong nilalaman ay sisira sa mga signed payload at lilikha ng mga bug na mahirap hanapin.
Ang mga cookie ay karapat-dapat sa parehong pag-iingat. Ang cookie na limitado sa pribadong pangalan ay hindi kailanman ipapadala ng browser na alam lamang ang pampubliko.
Tiyakin din na tunay na maaaring magmay-ari ang Nginx ng pampublikong socket. Ang umiiral na web service sa 443 ay dapat lumipat o ang frontend ay dapat tumira sa ibang lugar, dahil hindi maaaring mag-bind ang dalawang proseso sa parehong address at port.
Suriin ang bawat bahagi sa lugar kung saan talaga ito tumatakbo
I-validate ang configuration gamit ang naka-install na parser bago ang bawat reload, upang hindi mapatumba ng typo ang listener na naglilingkod ngayon.
Pagkatapos, subukan ang backend na bahagi mula sa host ng frontend mismo, sa parehong konteksto ng network na ginagamit ng Nginx. Ang ping sa tunnel ay nagpapatunay ng maabot at wala tungkol sa TLS, awtorisasyon, o aplikasyon.
Sa huli, gumawa ng bagong pampublikong request sa tunay na hostname na may normal na certificate verification, at obserbahan ang landas ng tugon hindi lamang ang response body.
Itago ang dalawang obserbasyon kasama ng naka-deploy na configuration, at itala ang nangyayari kapag hindi available ang tunnel. Dapat magbalik ang frontend ng kontroladong upstream error, hindi tahimik na babagsak sa ibang backend na walang nakadokumento. Ang 502 na may malinaw na log line ay magandang resulta. Isang naka-cache na pahina mula sa hindi sinasadyang pinagmulan ay hindi magandang resulta.