Öndə Nginx, VPN-in arxasında özəl backend
Brauzer Nginx ilə danışır, Nginx isə tunelə ikinci bağlantı açır. Hər ikisini marşrutla, hər iki sertifikatı yoxla və ictimai yönləndirmələri ictimai saxla.
Bir sorğunu qatarda olan telefondan yalnız özəl şəbəkədə mövcud olan backendə qədər izlə. Telefon ictimai adı həll edir, 443 portunda ictimai ünvana qoşulur və normal TLS əl sıxışmasını tamamlayır. Nginx bu bağlantını qəbul edir və sonra VPN interfeysi vasitəsilə çatdığı ünvana ikinci, tamamilə ayrı bir bağlantı açır. Telefonda heç nə dəyişmir və telefon heç vaxt tunelin iştirak etdiyini bilmir.
Bir sorğunu iki bağlantı ilə izləmək
Daxil olan hissə ictimai HTTP əməliyyatıdır. Onun ictimai adı, ictimai sertifikatı və ziyarətçinin həmin anda malik olduğu istənilən ünvana işləməli olan cavab yolu var. Bu yolu pozan istənilən dəyişiklik bütün ziyarətçiləri birdən pozur. Buna görə ictimai hissə üzərində ən az eksperiment etmək istədiyiniz hissədir.
Çıxan hissə özəldir. Nginx müştəri olur, daxili adı həll edir və ya sabit ünvandan istifadə edir və internetdən gələn bağlantını rədd edəcək xidmətə çatır.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Onları beynində ayrı saxla və konfiqurasiya aydın olacaq. Onları birləşdirsən, sonda ictimai müştərini tuneldə iştirak etməyə məcbur etməyə çalışacaqsan və bu dizayndakı qarışıqlığın böyük hissəsi elə buradan gəlir. Özəl hissə kövrək ola bilər. İctimai hissə yox.
Bunlardan hər hansı birini qurmazdan əvvəl tətbiqin dərcinin qəsdən olduğunu təsdiqlə. İşləyən proksi həm də işləyən məruz qalmadır və autentifikasiya modeli qərar olmalıdır, yan təsir yox.
Şlüz adı tuneldən sağ çıxmalıdır
Ad həllində incə bir tələ var. Əgər özəl DNS VPN profilinin öz şlüzü üçün istifadə etdiyi eyni adı üzərinə yazırsa, yenidən qoşulma sonda həmin şlüzə özünün qurmalı olduğu tuneldən keçməklə çatmağa çalışa bilər. Müştəriyə bu ad tunel mövcud olmadan əvvəl həll olunmalıdır. Bir dəfə tunelin içində həll olunanda, bağlantı heç vaxt qurula bilməz.
Şlüz və backend üçün ayrı təsdiqlənmiş adlardan istifadə et və həlledici siyasətini elə məhdudlaşdır ki, hər ad öz istehlakçısına lazım olan ünvana həll olunsun. Tətbiqin Host başlığının dəyişdirilməsi burada kömək etmir, çünki axtarışı VPN müştərisi edir.
Sonra əhatə dairəsi haqqında düşün. Frontend backend ünvanına marşrut lazımdır və o, həm də ictimai müştərilərə cavab verməyə davam etməlidir. Həmin hostda tam tunel birinci tələbi ödəyə və ikincini poza bilər.
Siyasətin icazə verdiyi yerdə konkret təyinatlı tunel daha təmiz dizayndır. Siyasətin tam tunel tələb etdiyi yerdə frontend ayrı şəbəkə kontekstinə aiddir, tanınmış ziyarətçilər üçün ad hoc marşrutlarla yamaqlanmaq əvəzinə.
Server blokunu elə yaz ki, hər iki hissə yoxlasın
Tutaq ki, backend bu ad üçün sertifikat təqdim edir: backend.corp.example və özəl ünvanda cavab verir. Bir adı yoxlayarkən ünvana qoşulmaq məhz proksi modulunun SNI və ad seçimlərinin məqsədidir.
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;
}
}
Yuxarıdakı hər yol və ünvan yer tutucudur. Vacib olan yoxlamanı açıq saxlayan hissələrdir: yoxlanılacaq ad, ona qarşı yoxlanılacaq etimad paketi və təsdiqlənmiş zəncirə uyğun dərinlik.
proxy_set_header Host app.example.com qəsdəndir. Backend bu ictimai mənşəyi qəbul etmək üçün konfiqurasiya olunmalıdır və ötürülən başlıqlara yalnız bu frontend-dən etibar etməlidir. Üzərinə yazmaq X-Forwarded-For müştəri ünvanı ilə tək proksi üçün doğru, zəncir üçün səhvdir, ona görə çoxproksili yerləşdirmə öz etibarlı ünvan qaydasına ehtiyac duyur.
İctimai mənşəyi özünü ictimai kimi aparmağa məcbur et
Tətbiq ictimai mənşə üçün mütləq URL-lər, yönləndirmələr və cookie-lər yayımlamalıdır. Əgər ziyarətçini backend.corp.example-ə yönləndirirsə, həmin ziyarətçi həll edə bilmədiyi ada göndərilir.
Bunu tətbiqin dəstəklədiyi xarici URL parametri və nəzərdən keçirilmiş yönləndirmə siyasəti ilə düzəlt, cavab gövdələrində host adlarını yenidən yazmaqla yox. İxtiyari məzmunda sətir əvəzləməsi imzalanmış yükləri pozur və izlənməsi çətin olan səhvlər yaradır.
Cookie-lər də eyni qayğıya layiqdir. Özəl ada bağlanmış cookie yalnız ictimai adı bilən brauzer tərəfindən heç vaxt göndərilməyəcək.
Həm də təsdiqlə ki, Nginx həqiqətən ictimai soketin sahibi ola bilər. 443-də mövcud veb xidməti köçməlidir, ya da frontend başqa yerdə yaşamalıdır, çünki iki proses eyni ünvanı və portu bağlaya bilməz.
Hər hissəni həqiqətən işlədiyi yerdə yoxla
Konfiqurasiyanı quraşdırılmış parserlə hər yenidən yükləmədən əvvəl yoxla ki, yazı səhvi hazırda xidmət edən dinləyicini yerə salmasın.
Sonra backend hissəsini frontend hostunun özündən, Nginx-in istifadə etdiyi eyni şəbəkə kontekstində sına. Tuneldən keçən ping əlçatanlığı sübut edir və TLS, avtorizasiya və ya tətbiq haqqında heç nə demir.
Nəhayət real host adına normal sertifikat yoxlaması ilə təzə ictimai sorğu göndər və yalnız cavab gövdəsini deyil, cavab yolunu müşahidə et.
Hər iki müşahidəni yerləşdirilmiş konfiqurasiya ilə birlikdə saxla və tunel əlçatan olmayanda nə baş verdiyini qeyd et. Frontend idarə olunan upstream xətası qaytarmalıdır, heç kimin sənədləşdirmədiyi başqa backendə səssizcə keçməməlidir. Aydın log sətri ilə 502 yaxşı nəticədir. İstənilməyən mənşədən keşlənmiş səhifə belə deyil.