Bir isteği trendeki bir telefondan yalnızca özel bir ağda var olan bir backend'e kadar izle. Telefon herkese açık bir adı çözer, 443 portunda herkese açık bir adrese bağlanır ve normal bir TLS el sıkışması tamamlar. Nginx bu bağlantıyı kabul eder ve ardından yalnızca bir VPN arayüzü üzerinden ulaştığı bir adrese ikinci, tamamen ayrı bir bağlantı açar. Telefonda hiçbir şey değişmez ve telefon bir tünelin işin içinde olduğunu asla öğrenmez.

Bir isteği iki bağlantı üzerinden izlemek

Gelen bacak herkese açık bir HTTP işlemidir. Herkese açık bir adı, herkese açık bir sertifikası ve ziyaretçinin o anda sahip olduğu her adres için çalışması gereken bir yanıt yolu vardır. Bu yolu bozan her değişiklik tüm ziyaretçileri aynı anda bozar. Bu yüzden herkese açık bacak, üzerinde en az deney yapmak isteyeceğiniz kısımdır.

Giden bacak özeldir. Nginx istemci olur, dahili bir adı çözer veya sabit bir adres kullanır ve internetten gelen bağlantıyı reddedecek bir hizmete ulaşır.

Public client  -> frontend public address:443   (TLS, public name)
Frontend       -> VPN private backend 10.40.0.20:8443  (TLS, private name)

Onları kafanda ayrı tut, yapılandırma apaçık hale gelir. Birleştirirsen sonunda herkese açık bir istemciyi bir tünele katmaya çalışırsın ve bu tasarımdaki karışıklığın büyük kısmı tam olarak buradan gelir. Özel bacak kırılgan olabilir. Herkese açık olan olamaz.

Bunlardan herhangi birini kurmadan önce uygulamanın yayınlanmasının kasıtlı olduğunu doğrula. Çalışan bir proxy aynı zamanda çalışan bir maruziyettir ve kimlik doğrulama modeli bir karar olmalı, yan etki değil.

Ağ geçidi adı tünelden sağ çıkmalı

Ad çözümlemede ince bir tuzak vardır. Özel DNS, VPN profilinin kendi ağ geçidi için kullandığı aynı adı geçersiz kılıyorsa, yeniden bağlanma sonunda o ağ geçidine kendi kurması gereken tünel üzerinden ulaşmaya çalışabilir. İstemcinin bu ada tünel var olmadan önce ihtiyacı vardır. Ad tünelin içinde çözüldüğünde, bağlantı bir daha asla kurulamaz.

Ağ geçidi ve backend için ayrı onaylanmış adlar kullan ve çözümleyici politikasını her ad, kendi tüketicisinin ihtiyaç duyduğu adrese çözülecek şekilde sınırla. Bir uygulamanın Host başlığını değiştirmek burada işe yaramaz, çünkü aramayı VPN istemcisi yapar.

Sonra kapsamı düşün. Frontend'in backend adresine bir rotaya ihtiyacı vardır ve aynı zamanda herkese açık istemcilere yanıt vermeye devam etmelidir. O ana bilgisayarda tam bir tünel ilk gereksinimi karşılayıp ikincisini bozabilir.

Politikanın izin verdiği yerde belirli bir hedefe tünel daha temiz tasarımdır. Politikanın tam tünel gerektirdiği yerde frontend, bilinen ziyaretçiler için ad hoc rotalarla yamanmak yerine ayrı bir ağ bağlamına aittir.

Sunucu bloğunu iki bacak da doğrulayacak şekilde yaz

Backend'in şu ad için bir sertifika sunduğunu varsayalım: backend.corp.example ve özel bir adreste yanıt verir. Bir adı doğrularken bir adrese bağlanmak, proxy modülünün SNI ve ad seçeneklerinin tam olarak amacıdır.

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;
    }
}

Yukarıdaki her yol ve adres bir yer tutucudur. Önemli olan, doğrulamayı açık tutan kısımlardır: kontrol edilecek bir ad, ona karşı kontrol edilecek bir güven paketi ve onaylanmış zincire uyan bir derinlik.

proxy_set_header Host app.example.com kasıtlıdır. Backend bu genel kaynağı kabul edecek şekilde yapılandırılmalı ve iletilen başlıklara yalnızca bu frontend'den güvenmelidir. Şunun üzerine yazmak X-Forwarded-For istemci adresiyle tek bir proxy için doğru, bir zincir için yanlıştır, bu yüzden çok proxy'li bir dağıtım kendi güvenilir adres düzenine ihtiyaç duyar.

Herkese açık kaynağın öyle davranmasını sağla

Uygulama herkese açık kaynak için mutlak URL'ler, yönlendirmeler ve çerezler üretmelidir. Bir ziyaretçiyi şuraya yönlendirirse: backend.corp.example, o ziyaretçi çözemeyeceği bir ada gönderilir.

Bunu uygulamanın desteklediği harici URL ayarı ve gözden geçirilmiş bir yönlendirme politikasıyla düzelt; yanıt gövdelerinde ana bilgisayar adlarını yeniden yazarak değil. Rastgele içerikte dize değiştirme imzalı yükleri bozar ve izlenmesi zor hatalar yaratır.

Çerezler de aynı özeni hak eder. Özel ada bağlanmış bir çerez, yalnızca herkese açık adı bilen bir tarayıcı tarafından asla gönderilmez.

Ayrıca Nginx'in herkese açık sokete gerçekten sahip olabildiğini doğrula. 443'te var olan bir web hizmeti taşınmalı ya da frontend başka bir yerde yaşamalıdır, çünkü iki süreç aynı adresi ve portu bağlayamaz.

Her bacağı gerçekte çalıştığı yerde kontrol et

Yapılandırmayı kurulu ayrıştırıcıyla her yeniden yüklemeden önce doğrula, böylece bir yazım hatası o anda hizmet veren dinleyiciyi devirmez.

Sonra backend bacağını frontend ana bilgisayarının kendisinden, Nginx'in kullandığı aynı ağ bağlamında test et. Tünel üzerinden bir ping erişilebilirliği kanıtlar ve TLS, yetkilendirme veya uygulama hakkında hiçbir şey kanıtlamaz.

Son olarak gerçek ana bilgisayar adına normal sertifika doğrulamasıyla yeni bir herkese açık istek gönder ve yalnızca yanıt gövdesini değil, yanıt yolunu da gözlemle.

Her iki gözlemi de dağıtılmış yapılandırmayla birlikte sakla ve tünel kullanılamadığında ne olduğunu kaydet. Frontend kontrollü bir upstream hatası döndürmeli, kimsenin belgelemediği başka bir backend'e sessizce düşmemelidir. Net bir günlük satırıyla 502 iyi bir sonuçtur. İstenmeyen bir kaynaktan önbelleğe alınmış sayfa değildir.

İlgili makaleler