Nginx diante, backend privado detrás da VPN
O navegador fala con Nginx, e Nginx abre unha segunda conexión cara ao túnel. Encamiñe ambas, verifique os dous certificados e manteña públicas as redireccións públicas.
Siga unha petición desde un teléfono nun tren ata un backend que só existe dentro dunha rede privada. O teléfono resolve un nome público, conéctase a un enderezo público no porto 443 e completa un handshake TLS normal. Nginx acepta esa conexión e despois abre unha segunda, completamente separada, cara a un enderezo ao que só chega por unha interface VPN. Nada do teléfono cambia, e o teléfono nunca chega a saber que houbo un túnel.
Seguir unha petición a través de dúas conexións
O tramo de entrada é unha transacción HTTP pública. Ten un nome público, un certificado público e un camiño de resposta que debe funcionar para calquera enderezo que teña o visitante nese momento. Calquera cambio que altere ese camiño rompe todos os visitantes á vez. Por iso o tramo público é o que menos convén experimentar.
O tramo de saída é privado. Nginx pasa a ser cliente, resolve un nome interno ou usa un enderezo fixo, e chega a un servizo que rexeitaría unha conexión desde internet.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Manteñaos separados na cabeza e a configuración tórnase obvia. Mestúreos e acabará tentando facer que un cliente público participe nun túnel, que é de onde vén a maior parte da confusión neste deseño. O tramo privado pode ser fráxil. O público non.
Antes de construír nada disto, confirme que publicar a aplicación é intencionado. Un proxy que funciona tamén é unha exposición que funciona, e o modelo de autenticación ten que ser unha decisión e non un efecto secundario.
O nome da pasarela ten que sobrevivir ao túnel
Hai unha trampa sutil na resolución de nomes. Se o DNS privado sobrescribe o mesmo nome que o perfil de VPN usa para a súa propia pasarela, unha reconexión pode acabar tentando chegar a esa pasarela a través do túnel que se supón que debe establecer. O cliente necesita que ese nome se resolva antes de que exista o túnel. Unha vez que se resolve dentro do túnel, a conexión non se pode construír en primeiro lugar.
Use nomes aprobados distintos para a pasarela e o backend, e limite a política do resolvedor para que cada nome se resolva no enderezo que necesita o seu consumidor. Cambiar a cabeceira Host dunha aplicación non axuda con este problema, porque é o cliente de VPN quen fai a consulta.
Despois pense no alcance. O frontend necesita unha ruta cara ao enderezo do backend e tamén debe seguir atendendo clientes públicos. Un túnel completo nese host satisfai o primeiro requisito e rompe o segundo.
Onde a política o permite, un túnel cara a un destino concreto é o deseño máis limpo. Onde a política impón un túnel completo, o frontend pertence a un contexto de rede separado en vez de ser remendado con rutas ad hoc para visitantes coñecidos.
Escribir o bloque de servidor para que ambos os tramos verifiquen
Supoña que o backend presenta un certificado para backend.corp.example e responde nun enderezo privado. Conectarse a un enderezo mentres se verifica un nome é exactamente para o que están as opcións SNI e de nome do módulo de 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;
}
}
Cada camiño e enderezo de arriba é un marcador de posición. As partes importantes son as que manteñen a verificación activada: un nome que comprobar, un paquete de confianza co que comprobalo e unha profundidade que coincida coa cadea aprobada.
proxy_set_header Host app.example.com é deliberado. O backend debería configurarse para aceptar esa orixe pública, e debería confiar nas cabeceiras reenviadas só desde este frontend. Sobrescribir X-Forwarded-For co enderezo do cliente é correcto para un único proxy e erróneo para unha cadea, así que un despregamento con varios proxies necesita a súa propia disposición de enderezos de confianza.
Facer que a orixe pública se comporte como tal
A aplicación debería emitir URL absolutas, redireccións e cookies para a orixe pública. Se redirixe un visitante a backend.corp.example, ese visitante vai a un nome que non pode resolver.
Corrixa iso mediante o axuste de URL externa que admite a aplicación e unha política de redirección revisada, non reescribindo nomes de host nos corpos de resposta. A substitución de cadeas en contido arbitrario rompe cargas asinadas e crea erros difíciles de rastrexar.
As cookies merecen o mesmo coidado. Unha cookie limitada ao nome privado nunca a enviará un navegador que só coñece o público.
Confirme tamén que Nginx pode realmente posuír o socket público. Un servizo web existente no 443 ten que moverse ou o frontend ten que vivir noutro sitio, porque dous procesos non poden enlazar o mesmo enderezo e o mesmo porto.
Comprobar cada tramo onde realmente se executa
Valide a configuración co analizador instalado antes de calquera recarga, para que unha errata non derrube o oínte que está servindo nese momento.
Despois probe o tramo do backend desde o propio host do frontend, no mesmo contexto de rede que usa Nginx. Un ping a través do túnel demostra alcanzabilidade e nada sobre TLS, autorización ou a aplicación.
Por último faga unha petición pública nova ao nome de host real con verificación de certificado normal, e observe o camiño de resposta en vez de só o corpo.
Garde ambas as observacións coa configuración despregada e anote que pasa cando o túnel non está dispoñible. O frontend debería devolver un erro de upstream controlado, non recuar en silencio cara a outro backend que ninguén documentou. Un 502 cunha liña de rexistro clara é un bo resultado. Unha páxina en caché dunha orixe non pretendida non o é.