HAProxy 302 cap a una app privada: qui obre el segon salt?
Una redirecció torna la segona connexió al navegador. Envia la petició a un backend i després corregeix les redireccions absolutes i les galetes de l’app.
Algú apunta un host públic de HAProxy a una aplicació interna i pregunta per què el navegador no pot seguir. El proxy arriba a l’app per la seva VPN, la redirecció retorna una capçalera Location i el navegador intenta llavors una adreça que només existeix dins del túnel. Des de fora, la pàgina simplement es penja. La decisió és quina part obre la segona connexió, i això és el que separa una redirecció d’un backend.
Dos camins que a la configuració semblen iguals
Una redirecció acaba l’intercanvi amb una resposta. El client llegeix Location i inicia una petició nova des d’on sigui, és a dir, la xarxa que mai no has controlat. El proxy ja no hi participa. Tot el que segueix depèn del DNS, la ruta i la confiança del mateix client, així que el resultat varia segons on l’usuari va obrir el navegador:
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 manté la segona etapa al costat del servidor. El proxy l’obre pel camí que ja té, i el client continua parlant amb un sol nom públic. Si el túnel cau, el client rep un error en lloc d’una URL que no pot seguir. Aquesta diferència és també el que fa diagnosticable la fallada, perquè l’error apareix on són els registres:
GET /app client -> proxy
GET /app proxy -> 10.40.0.20:8080 over the VPN
response proxy -> client
La documentació de redireccions de HAProxy traça exactament aquesta línia: respondre al client amb una redirecció és una acció diferent de reenviar la petició a un backend. Les dues directives són a poques línies de distància en un fitxer de configuració i es comporten de manera ben diferent. Una acaba la petició, l’altra n’inicia una segona que és propietat del proxy.
Què necessita el navegador i la VPN del servidor no li dóna
La petició del mateix navegador necessita quatre coses que potser no té: una resposta DNS per al nom privat, una ruta cap a aquesta adreça, permís per arribar al servei que escolta i confiança en el certificat que aquest servei presenta. L’host del proxy les té totes quatre gràcies al seu túnel. Cap d’elles no es transfereix a un client que mai no ha estat en aquest túnel, perquè el túnel és una propietat de l’host, no de la URL.
Aquest buit explica el símptoma de gairebé funciona. La primera petició té èxit, la barra d’adreces canvia i la connexió es penja o falla mentre el proxy és sa tot el temps. A la configuració del proxy no hi ha res trencat, i ajustar-la no ajuda un client que no té camí cap a 10.40.0.20. O el client obté una ruta, o el proxy ha de fer la connexió en nom seu.
Quan només el proxy pot arribar a l’app
Treu l’acció de redirecció i envia aquestes peticions a un backend que apunti a l’adreça privada. El frontend conserva el seu nom públic mentre el backend decideix on va realment la petició. Res del camí del client no canvia, perquè el proxy deixa de descriure una destinació i comença a ser-ne una. Per a una aplicació que escolta expressament al port intern 8080, el bloc de servidor és curt:
backend private_app
mode http
option httpchk GET /health
server app1 10.40.0.20:8080 check
Llegeix aquest bloc com una afirmació sobre la taula d’encaminament del proxy: 10.40.0.20 ha de ser abastable des del mateix host del proxy, cosa que aquí vol dir per la interfície VPN i no per la ruta per defecte. La paraula clau check només informa del que fa aquesta ruta, i el camí de salut ha d’existir a l’aplicació o cada sonda marcarà el servidor com a caigut. Una comprovació correcta no demostra res sobre el client i no substitueix la política que decideix qui pot usar el backend.
El fragment no és un frontend complet. Conserva l’oient, l’autenticació, la selecció d’host i camí permesos i la regla que decideix qui pot arribar a l’aplicació. Ajusta també el protocol del backend, perquè un backend HTTPS necessita verificació de certificat i una configuració d’identitat del servidor, i ometre aquesta comprovació converteix una connexió privada en una de no verificada.
Confirma el camí de tornada en tots dos sentits abans de declarar la victòria. L’aplicació ara veu una connexió del proxy, així que els seus registres i qualsevol metadada d’adreça del client descriuen el proxy, tret que ho organitzis d’una altra manera. Decideix com es tracten la identitat i les adreces reenviades, i prova la decisió en lloc de suposar-la.
Les redireccions de l’app encara apunten cap a dins
Reenviar la primera petició és només la meitat de la integració. L’aplicació pot emetre redireccions absolutes, URL de recursos codificades a mà o galetes limitades al nom que coneix internament, i cadascuna d’aquestes torna el navegador a una adreça que no pot abastar. Una capçalera Location que apunta al nom intern es veu idèntica al problema original, i per això es diagnostica malament com una fallada del proxy.
Estableix la URL externa documentada de l’aplicació i les seves opcions de proxy, i fes que la capçalera Host coincideixi amb l’host virtual i amb les expectatives del certificat. Una galeta limitada al nom intern no tornarà pel nom públic, i el bucle d’inici de sessió que segueix es llegeix com un error d’autenticació. Canvia primer la URL externa, torna a provar des d’un perfil de navegador net i espera que una configuració migrada a mitges produeixi un inici de sessió que funciona i una sessió que mor immediatament.
Confia en les metadades reenviades només des del proxy designat. Una capçalera que qualsevol client pot establir no ha de convertir-se mai en un valor d’autorització, o el proxy es converteix en una manera que qui crida reivindiqui la identitat d’un altre. Aquesta regla és independent de la qüestió de la redirecció i sobreviu a qualsevol redisseny posterior.
Decideix quin disseny tens realment
Si cada usuari ja té accés VPN autoritzat, una redirecció a una URL privada pot ser un disseny deliberat. Confirma aquest requisit explícitament en lloc de suposar-lo, perquè els dos dissenys serveixen poblacions completament diferents. Un d’ells no funciona de cap manera des d’una xarxa d’hotel, i l’altre exposa l’aplicació a qualsevol que pugui carregar la URL pública. Aquesta distinció pertany a la nota de disseny.
Executa la comprovació des d’una màquina a la xarxa dels usuaris i segueix cada salt que fa el navegador, no només la primera resposta. Vigila la barra d’adreces i cada petició posterior, perquè una sola URL absoluta en una etiqueta de recurs és prou per trencar un flux que el primer salt va superar. L’inici de sessió ha de funcionar pel nom públic, i els recursos que s’han de denegar han de continuar denegats.
Publicar un proxy invers és una decisió d’accés a part, no una extensió transparent de la VPN del mateix proxy a qualsevol que pugui carregar la seva URL pública. Els dos s’assemblen en un diagrama, i difereixen en qui hi pot entrar. Decidir aquesta qüestió després del desplegament és com una aplicació interna es converteix en pública per accident.
Anota quin dels dos has construït i per què. La següent persona que toqui la configuració suposarà l’altre. Una sola redirecció afegida per comoditat és prou per recrear la fallada original, i el símptoma serà exactament com el que acabes de corregir.