Seuraa yhtä pyyntöä junassa olevasta puhelimesta backendiin, joka on olemassa vain yksityisverkossa. Puhelin selvittää julkisen nimen, yhdistää julkiseen osoitteeseen portissa 443 ja suorittaa normaalin TLS-kättelyn. Nginx hyväksyy yhteyden ja avaa sitten toisen, täysin erillisen yhteyden osoitteeseen, johon se pääsee vain VPN-rajapinnan kautta. Puhelimessa ei muutu mikään, eikä puhelin koskaan saa tietää, että tunneli oli mukana.

Seuraa yhtä pyyntöä kahden yhteyden läpi

Saapuva osuus on julkinen HTTP-tapahtuma. Sillä on julkinen nimi, julkinen varmenne ja vastauspolku, jonka täytyy toimia mille tahansa osoitteelle, joka kävijällä sattuu olemaan. Mikä tahansa muutos, joka häiritsee tuota polkua, rikkoo kaikki kävijät kerralla. Siksi julkinen osuus on se, jolla haluat vähiten kokeilla.

Lähtevä osuus on yksityinen. Nginxistä tulee asiakas, se selvittää sisäisen nimen tai käyttää kiinteää osoitetta ja tavoittaa palvelun, joka hylkäisi internetistä tulevan yhteyden.

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

Pidä ne erillään päässäsi, niin kokoonpano muuttuu ilmeiseksi. Yhdistä ne, niin päädyt yrittämään saada julkinen asiakas osallistumaan tunneliin, ja siitä tulee suurin osa tämän suunnittelun sekaannuksesta. Yksityinen osuus saa olla hauras. Julkinen ei.

Ennen kuin rakennat mitään tästä, varmista, että sovelluksen julkaiseminen on tarkoitus. Toimiva välityspalvelin on myös toimiva altistus, ja todennusmallin on oltava päätös eikä sivutuote.

Yhdyskäytävän nimen täytyy selvitä tunnelista

Nimien selvityksessä on hienovarainen ansa. Jos yksityinen DNS korvaa saman nimen, jota VPN-profiili käyttää omalle yhdyskäytävälleen, uudelleenyhdistäminen voi päätyä yrittämään tavoittaa sen yhdyskäytävän tunnelin kautta, joka sen pitäisi muodostaa. Asiakas tarvitsee nimen selvitetyksi ennen kuin tunneli on olemassa. Kun se selvitetään tunnelin sisällä, yhteyttä ei voi koskaan rakentaa.

Käytä erillisiä hyväksyttyjä nimiä yhdyskäytävälle ja backendille ja rajaa selvittäjän käytäntö niin, että kukin nimi selvittää osoitteen, jonka sen käyttäjä tarvitsee. Sovelluksen Host-otsikon muuttaminen ei auta tässä, koska VPN-asiakas tekee haun.

Mieti sitten laajuutta. Frontend tarvitsee reitin backendin osoitteeseen ja sen täytyy myös vastata julkisille asiakkaille. Täysi tunneli tällä isännällä voi täyttää ensimmäisen vaatimuksen ja rikkoa toisen.

Missä käytäntö sallii, tunneli tiettyyn kohteeseen on siistimpi ratkaisu. Missä käytäntö vaatii täyden tunnelin, frontend kuuluu erilliseen verkkoympäristöön sen sijaan, että sitä paikattaisiin ad hoc -reiteillä tunnetuille kävijöille.

Kirjoita palvelinlohko niin, että molemmat osuudet varmistavat

Oletetaan, että backend esittää varmenteen nimelle backend.corp.example ja vastaa yksityisessä osoitteessa. Yhteyden avaaminen osoitteeseen nimeä varmistaen on juuri se, mihin välityspalvelinmoduulin SNI- ja nimivaihtoehdot on tarkoitettu.

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

Jokainen yllä oleva polku ja osoite on paikkamerkki. Tärkeitä ovat ne osat, jotka pitävät varmistuksen päällä: tarkistettava nimi, luottamusnippu, jota vasten se tarkistetaan, ja syvyys, joka vastaa hyväksyttyä ketjua.

proxy_set_header Host app.example.com on tarkoituksellinen. Backend pitäisi määrittää hyväksymään tämä julkinen alkuperä, ja sen pitäisi luottaa välitettyihin otsikoihin vain tältä frontendilta. Kohdan X-Forwarded-For korvaaminen asiakkaan osoitteella on oikein yhdelle välityspalvelimelle ja väärin ketjulle, joten monen välityspalvelimen käyttöönotto tarvitsee oman luotettujen osoitteiden järjestelynsä.

Saa julkinen alkuperä käyttäytymään sellaisena

Sovelluksen pitäisi tuottaa absoluuttiset URL-osoitteet, uudelleenohjaukset ja evästeet julkiselle alkuperälle. Jos se ohjaa kävijän osoitteeseen backend.corp.example, kävijä lähetetään nimeen, jota hän ei voi selvittää.

Korjaa se sovelluksen tukemalla ulkoisen URL-osoitteen asetuksella ja tarkistetulla uudelleenohjauskäytännöllä, ei kirjoittamalla isäntänimiä uudelleen vastausrunkoihin. Merkkijonojen korvaaminen mielivaltaisessa sisällössä rikkoo allekirjoitetut hyötykuormat ja luo bugeja, joita on vaikea jäljittää.

Evästeet ansaitsevat saman huolen. Yksityiseen nimeen rajattua evästettä ei koskaan lähetä selaimesta, joka tuntee vain julkisen nimen.

Varmista myös, että Nginx voi todella omistaa julkisen pistokkeen. Nykyisen verkkopalvelun portissa 443 on siirryttävä tai frontendin on elettävä muualla, koska kaksi prosessia ei voi sitoa samaa osoitetta ja porttia.

Tarkista kukin osuus siellä, missä se todella toimii

Validoi kokoonpano asennetulla jäsentimellä ennen jokaista uudelleenlatausta, jotta kirjoitusvirhe ei kaada kuuntelijaa, joka palvelee juuri nyt.

Testaa sitten backend-osuus frontend-isännältä itseltään samassa verkkoympäristössä, jota Nginx käyttää. Ping tunnelin läpi todistaa tavoitettavuuden eikä mitään TLS:stä, valtuutuksesta tai sovelluksesta.

Tee lopuksi tuore julkinen pyyntö todelliseen isäntänimeen normaalilla varmenteen varmistuksella ja tarkkaile vastauspolkua pelkän vastausrungon sijaan.

Säilytä molemmat havainnot käyttöönotetun kokoonpanon kanssa ja kirjaa, mitä tapahtuu, kun tunneli ei ole käytettävissä. Frontendin pitäisi palauttaa hallittu upstream-virhe, ei vaihtaa hiljaa toiseen backendiin, jota kukaan ei ole dokumentoinut. 502 ja selkeä lokirivi on hyvä tulos. Välimuistiin tallennettu sivu tahattomasta alkuperästä ei ole.

Aiheeseen liittyvät artikkelit