Alguien apunta un host público de HAProxy a una aplicación local y pregunta por qué el navegador no puede seguir. El proxy llega a la app por su VPN, la redirección devuelve una cabecera Location y el navegador intenta entonces una dirección que solo existe dentro del túnel. Desde fuera, la página simplemente se queda colgada. La decisión consiste en qué parte abre la segunda conexión, y eso es lo que separa una redirección de un backend.

Dos caminos que se parecen en la configuración

Una redirección termina el intercambio con una respuesta. El cliente lee Location y lanza una petición nueva desde donde esté, que es la red que usted nunca controló. El proxy ya no participa. Todo lo que sigue depende del DNS, la ruta y la confianza del propio cliente, así que el resultado varía según dónde abrió el navegador el usuario:

GET /app        client -> proxy
302 Location    proxy  -> client   (http://10.40.0.20:8080/)
GET /app        client -> 10.40.0.20:8080   client network, no route

Un backend del proxy mantiene la segunda etapa en el lado del servidor. El proxy la abre por el camino que ya tiene, y el cliente sigue hablando con un solo nombre público. Si el túnel cae, el cliente recibe un error en lugar de una URL que no puede seguir. Esa diferencia es también lo que hace diagnosticable el fallo, porque el error aparece donde están los registros:

GET /app        client -> proxy
GET /app        proxy  -> 10.40.0.20:8080   over the VPN
response        proxy  -> client

La documentación de redirecciones de HAProxy traza justo esa línea: responder al cliente con una redirección es una acción distinta de reenviar la petición a un backend. Las dos directivas están a pocas líneas de distancia en un archivo de configuración y no se parecen en nada. Una termina la petición y la otra empieza una segunda que es propiedad del proxy.

Lo que el navegador necesita y el VPN del servidor no le da

La petición del propio navegador necesita cuatro cosas que quizá no tenga: una respuesta DNS para el nombre privado, una ruta hacia esa dirección, permiso para alcanzar el servicio que escucha y confianza en el certificado que ese servicio presente. El host del proxy posee las cuatro a través de su túnel. Ninguna de ellas se transfiere a un cliente que nunca estuvo en ese túnel, porque el túnel es una propiedad del host, no de la URL.

Esa brecha explica el síntoma de casi funciona. La primera petición tiene éxito, la barra de direcciones cambia y la conexión se cuelga o falla mientras el proxy está sano todo el tiempo. En la configuración del proxy no hay nada roto, y ajustarla no ayuda a un cliente que no tiene camino hacia 10.40.0.20. O el cliente obtiene una ruta, o el proxy tiene que hacer la conexión en su nombre.

Cuando solo el proxy puede llegar a la app

Elimine la acción de redirección y envíe esas peticiones a un backend que apunte a la dirección privada. El frontend conserva su nombre público mientras el backend decide adónde va realmente la petición. Nada del camino del cliente cambia, porque el proxy deja de describir un destino y empieza a serlo. Para una aplicación que escucha a propósito en el puerto interno 8080, el bloque de servidor es corto:

backend private_app
    mode http
    option httpchk GET /health
    server app1 10.40.0.20:8080 check

Lea ese bloque como una afirmación sobre la tabla de rutas del proxy: 10.40.0.20 debe ser alcanzable desde el propio host del proxy, lo que aquí significa a través de la interfaz VPN y no de la ruta por defecto. La palabra clave check solo informa de lo que hace esa ruta, y la ruta de salud tiene que existir en la aplicación o cada sonda marcará el servidor como caído. Una comprobación correcta no demuestra nada sobre el cliente y no sustituye a la política que decide quién puede usar el backend.

El fragmento no es un frontend completo. Conserve el listener, la autenticación, la selección de host y ruta permitidos, y la regla que decide quién puede llegar a la aplicación. Ajuste también el protocolo del backend, porque un backend HTTPS necesita verificación de certificado y una configuración de identidad del servidor, y omitir esa comprobación convierte una conexión privada en una no verificada.

Confirme el camino de vuelta en ambos sentidos antes de declarar la victoria. La aplicación ahora ve una conexión desde el proxy, así que sus registros y cualquier metadato de dirección del cliente describen al proxy, salvo que organice otra cosa. Decida cómo se manejan la identidad y las direcciones reenviadas, y pruebe la decisión en lugar de suponerla.

Las redirecciones de la propia app siguen apuntando hacia dentro

Reenviar la primera petición es solo la mitad de la integración. La aplicación puede emitir redirecciones absolutas, URL de recursos codificadas a mano o cookies limitadas al nombre que conoce por dentro, y cada una de ellas devuelve el navegador a una dirección que no puede alcanzar. Una cabecera Location que apunta al nombre interno se ve idéntica al problema original, por eso se diagnostica mal como un fallo del proxy.

Configure la URL externa documentada de la aplicación y sus opciones de proxy, y haga que la cabecera Host coincida con el host virtual y con lo que espera el certificado. Una cookie limitada al nombre interno no volverá por el nombre público, y el bucle de inicio de sesión que sigue se lee como un fallo de autenticación. Cambie primero la URL externa, vuelva a probar con un perfil de navegador limpio y cuente con que una configuración a medio migrar produzca un inicio de sesión que funciona y una sesión que muere de inmediato.

Confíe en los metadatos reenviados solo desde el proxy designado. Una cabecera que cualquier cliente puede establecer jamás debe convertirse en un valor de autorización, o el proxy se transforma en una vía para que quien llama reclame la identidad de otro. Esa regla es independiente de la cuestión de la redirección y sobrevive a cualquier rediseño posterior.

Decida qué diseño tiene en realidad

Si todos los usuarios ya tienen acceso VPN autorizado, una redirección a una URL privada puede ser un diseño deliberado. Confirme ese requisito de forma explícita en lugar de darlo por hecho, porque los dos diseños sirven a poblaciones completamente distintas. Uno de ellos no funciona en absoluto desde una red de hotel, y el otro expone la aplicación a cualquiera que pueda cargar la URL pública. Esa distinción pertenece a la nota de diseño.

Ejecute la comprobación desde una máquina en la red de los usuarios y siga cada salto que hace el navegador, no solo la primera respuesta. Vigile la barra de direcciones y cada petición posterior, porque una sola URL absoluta en una etiqueta de recurso basta para romper un flujo que el primer salto superó. El inicio de sesión tiene que funcionar por el nombre público, y los recursos que deben denegarse tienen que seguir denegados.

Publicar un proxy inverso es una decisión de acceso aparte, no una extensión transparente del VPN del propio proxy a cualquiera que pueda cargar su URL pública. Los dos se parecen en un diagrama y difieren en quién puede entrar. Decidir esa cuestión después del despliegue es como una aplicación interna se vuelve pública por accidente.

Anote cuál de los dos construyó y por qué. La siguiente persona que toque la configuración dará por hecho el otro. Basta una sola redirección añadida por comodidad para recrear el fallo original, y el síntoma se verá exactamente como el que acaba de corregir.

Artículos relacionados