Conservar el nombre de host HTTP original entre un proxy inverso y su aplicación web back-end

Azure API Management
Azure App Service
Azure Application Gateway
Azure Front Door
Azure Spring Apps

Se recomienda conservar el nombre de host HTTP original cuando se usa un proxy inverso delante de una aplicación web. Tener un nombre de host diferente en el proxy inverso que el que se proporciona al servidor de aplicaciones back-end puede provocar cookies o direcciones URL de redireccionamiento que no funcionan correctamente. Por ejemplo, el estado de sesión puede perderse, la autenticación puede producir un error o las direcciones URL de back-end se pueden exponer involuntariamente a los usuarios finales. Puede evitar estos problemas al conservar el nombre de host de la solicitud inicial para que el servidor de aplicaciones vea el mismo dominio que el explorador web.

Esta guía se aplica especialmente a las aplicaciones hospedadas en ofertas de plataforma como servicio (PaaS), como Azure App Service y Azure Spring Apps. En este artículo se proporcionan una guía de implementación específicas para Azure Application Gateway, Azure Front Door y Azure API Management, que se usan normalmente servicios de proxy inverso.

Nota:

Las API web suelen ser menos sensibles a los problemas causados por errores de coincidencia de nombres de host. Normalmente no dependen de las cookies, a menos que use cookies para proteger las comunicaciones entre una aplicación de una sola página y su API de back-end, por ejemplo, en un patrón conocido como back-end para front-end. Las API web a menudo no devuelven direcciones URL absolutas a sí mismas, excepto en determinados estilos de API, como OData y HATEOAS. Si la implementación de la API depende de cookies o genera direcciones URL absolutas, se aplica la guía proporcionada en este artículo.

Si necesita TLS/SSL de un extremo a otro (la conexión entre el proxy inverso y el servicio back-end usa HTTPS), el servicio back-end también necesita un certificado TLS correspondiente para el nombre de host original. Este requisito agrega complejidad operativa al implementar y renovar certificados, pero muchos servicios PaaS ofrecen certificados TLS gratuitos que están totalmente administrados.

Context

Host de una solicitud HTTP

En muchos casos, el servidor de aplicaciones o algún componente de la canalización de solicitudes necesita el nombre de dominio de Internet que usó el explorador para acceder a él. Este es el host de la solicitud. Puede ser una dirección IP, pero normalmente es un nombre como contoso.com (que el explorador resuelve en una dirección IP mediante DNS). Normalmente, el valor de host se determina a partir del componente host del URI de solicitud, que el explorador envía a la aplicación como Hostencabezado HTTP.

Importante

Nunca use el valor del host en un mecanismo de seguridad. El valor lo proporciona el explorador o algún otro agente de usuario y un usuario final puede manipularlo fácilmente.

En algunos escenarios, especialmente cuando hay un proxy inverso HTTP en la cadena de solicitudes, el encabezado de host original puede cambiarse antes de que llegue al servidor de aplicaciones. Un proxy inverso cierra la sesión de red del cliente y configura una nueva conexión al back-end. En esta nueva sesión, puede llevar el nombre de host original de la sesión de cliente o establecer uno nuevo. En el último caso, el proxy aún envía el valor de host original en otros encabezados HTTP, como Forwarded o X-Forwarded-Host. Este valor permite a las aplicaciones determinar el nombre de host original, pero solo si están codificadas para leer estos encabezados.

Por qué las plataformas web usan el nombre de host

Los servicios PaaS multiinquilino a menudo requieren un nombre de host registrado y validado para enrutar una solicitud entrante al servidor back-end del inquilino adecuado. Esto se debe a que normalmente hay un grupo compartido de equilibradores de carga que aceptan solicitudes entrantes para todos los inquilinos. Los inquilinos normalmente usan el nombre de host entrante para buscar el back-end correcto para el inquilino del cliente.

Para facilitar la introducción, estas plataformas suelen proporcionar un dominio predeterminado preconfigurado para enrutar el tráfico a la instancia implementada. Por App Service, este dominio predeterminado es azurewebsites.net. Cada aplicación web que cree obtiene su propio subdominio, por ejemplo, contoso.azurewebsites.net. Del mismo modo, el dominio predeterminado es azuremicroservices.io para Spring Apps y azure-api.net para API Management.

En el caso de las implementaciones de producción, no se usan estos dominios predeterminados. En su lugar, proporcione su propio dominio para alinearse con la marca de su organización o aplicación. Por ejemplo, contoso.com podría resolverse en segundo plano en la aplicación web contoso.azurewebsites.net en App Service, pero este dominio no debería ser visible para un usuario final que visite el sitio web. Sin embargo, este nombre de host personalizado contoso.com debe registrarse con el servicio PaaS para que la plataforma pueda identificar el servidor back-end que debe responder a la solicitud.

Diagram that illustrates host-based routing in App Service.

Por qué las aplicaciones usan el nombre de host

Dos razones comunes por las que un servidor de aplicaciones necesita el nombre de host son construir direcciones URL absolutas y emitir cookies para un dominio específico. Por ejemplo, cuando el código de la aplicación necesita:

  • Devuelve una dirección URL absoluta en lugar de una dirección URL relativa en su respuesta HTTP (aunque generalmente los sitios web tienden a representar vínculos relativos cuando es posible).
  • Genere una dirección URL que se usará fuera de su respuesta HTTP donde no se puedan usar direcciones URL relativas, como para enviar un vínculo al sitio web a un usuario por correo electrónico.
  • Genere una dirección URL de redireccionamiento absoluta para un servicio externo. Por ejemplo, en un servicio de autenticación como Microsoft Entra ID para indicar dónde debe devolver el usuario después de la autenticación correcta.
  • Emita cookies HTTP restringidas a un host determinado, tal como se define en el atributo de la Domain cookie.

Puede cumplir todos estos requisitos al agregar el nombre de host esperado a la configuración de la aplicación y al usar ese valor definido estáticamente en lugar del nombre de host entrante en la solicitud. Sin embargo, este enfoque complica el desarrollo y la implementación de aplicaciones. Además, una sola instalación de la aplicación puede atender a varios hosts. Por ejemplo, se puede usar una sola aplicación web para varios inquilinos de aplicación que tienen sus propios nombres de host únicos (como tenant1.contoso.com y tenant2.contoso.com).

Y a veces el nombre de host entrante lo usan los componentes fuera del código de la aplicación o en middleware en el servidor de aplicaciones sobre el que no tiene control total. Estos son algunos ejemplos:

  • En App Service, puede aplicar HTTPS para la aplicación web. Si lo hace, las solicitudes HTTP que no son seguras se redirigirán a HTTPS. En este caso, el nombre de host entrante se usa para generar la dirección URL absoluta para el encabezado Location de redireccionamiento HTTP.
  • Spring Apps usa una característica similar para aplicar HTTPS. También usa el host entrante para generar la dirección URL HTTPS.
  • App Service una configuración de afinidad de ARR para habilitar sesiones permanentes, de modo que el mismo servidor back-end siempre abate las solicitudes de la misma instancia del explorador. Esto lo realizan los front-end de App Service, que agregan una cookie a la respuesta HTTP. La propiedad de la cookie Domain se establece en el host entrante.
  • App Service proporciona funcionalidades de autenticación y autorización para permitir fácilmente a los usuarios iniciar sesión y acceder a los datos en las API.

Por qué podría verse tentado a invalidar el nombre de host

Por ejemplo, cree una aplicación web en App Service que tenga un dominio predeterminado de contoso.azurewebsites.net. (O bien, en otro servicio, como Spring Apps). No ha configurado un dominio personalizado en App Service. Para colocar un proxy inverso como Application Gateway (o cualquier servicio similar) delante de esta aplicación, establezca el registro DNS para contoso.com para resolver la dirección IP de Application Gateway. Por lo tanto, recibe la solicitud de contoso.com del explorador y está configurada para reenviar esa solicitud a la dirección IP que contoso.azurewebsites.net resuelve: se trata del servicio back-end final para el host solicitado. En este caso, sin embargo, App Service no reconoce el dominio personalizado contoso.com y rechaza todas las solicitudes entrantes para este nombre de host. No puede determinar dónde enrutar la solicitud.

Puede parecer que la manera fácil de hacer que esta configuración funcione es invalidar o volver a escribir el encabezado Host de la solicitud HTTP en Application Gateway y establecerlo en el valor de contoso.azurewebsites.net. Si lo hace, la solicitud saliente de Application Gateway hará que parezca que la solicitud original realmente estaba destinada a contoso.azurewebsites.net en lugar de contoso.com:

Diagram that illustrates a configuration with the host name overridden.

En este momento, App Service reconoce el nombre de host y acepta la solicitud sin necesidad de configurar un nombre de dominio personalizado. De hecho, Application Gateway facilita la invalidación del encabezado host por el host del grupo de back-end. Azure Front Door lo hace de forma predeterminada.

El problema con esta solución, sin embargo, es que puede dar lugar a varios problemas cuando la aplicación no ve el nombre de host original.

Problemas potenciales

Direcciones URL absolutas incorrectas

Si no se conserva el nombre de host original y el servidor de aplicaciones usa el nombre de host entrante para generar direcciones URL absolutas, el dominio back-end podría revelarse a un usuario final. Estas direcciones URL absolutas podrían generarse mediante el código de la aplicación o, como se indicó anteriormente, por características de la plataforma como la compatibilidad con el redireccionamiento de HTTP a HTTPS en App Service y Spring Apps. En este diagrama se muestra el problema:

Diagram that illustrates the problem of incorrect absolute URLs.

  1. El explorador envía una solicitud para contoso.com al proxy inverso.
  2. El proxy inverso reescribe el nombre de host a contoso.azurewebsites.net en la solicitud a la aplicación web de back-end (o a un dominio predeterminado similar para otro servicio).
  3. La aplicación genera una dirección URL absoluta basada en el nombre de host entrante contoso.azurewebsites.net, por ejemplo, https://contoso.azurewebsites.net/.
  4. El explorador sigue esta dirección URL, que va directamente al servicio back-end en lugar de volver al proxy inverso en contoso.com.

Esto puede suponer incluso un riesgo para la seguridad en el caso común en el que el proxy inverso también actúa como firewall de aplicaciones web. El usuario recibe una dirección URL que va directamente a la aplicación back-end y omite el proxy inverso.

Importante

Debido a este riesgo de seguridad, debe asegurarse de que la aplicación web back-end solo acepta directamente el tráfico de red del proxy inverso (por ejemplo, mediante restricciones de acceso en App Service). Si lo hace, incluso si se genera una dirección URL absoluta incorrecta, al menos no funciona y un usuario malintencionado no puede usarla para omitir el firewall.

Direcciones URL de redireccionamiento incorrectas

Un caso común y más específico del escenario anterior se produce cuando se generan direcciones URL de redireccionamiento absoluto. Estos servicios de identidad requieren estas direcciones URL, como Microsoft Entra ID, cuando se usan protocolos de identidad basados en explorador como OpenID Connect, OAuth 2.0 o SAML 2.0. El propio middleware o el servidor de aplicaciones pueden generar estas direcciones URL de redireccionamiento, o bien, como se indicó anteriormente, por características de plataforma como las capacidades de autorización y autenticación de App Service. En este diagrama se muestra el problema:

Diagram that illustrates the problem of incorrect redirect URLs.

  1. El explorador envía una solicitud para contoso.com al proxy inverso.
  2. El proxy inverso reescribe el nombre de host a contoso.azurewebsites.net en la solicitud a la aplicación web de back-end (o a un dominio predeterminado similar para otro servicio).
  3. La aplicación genera una dirección URL de redireccionamiento absoluta que se basa en el nombre de host entrante contoso.azurewebsites.net, por ejemplo, https://contoso.azurewebsites.net/.
  4. El explorador va al proveedor de identidades para autenticar al usuario. La solicitud incluye la dirección URL de redireccionamiento generada para indicar dónde se debe devolver al usuario después de la autenticación correcta.
  5. Los proveedores de identidades normalmente requieren que las direcciones URL de redireccionamiento se registren por adelantado, por lo que en este momento el proveedor de identidades debe rechazar la solicitud porque la dirección URL de redireccionamiento proporcionada no está registrada. (Se suponía que no se iba a usar). Si, por algún motivo, se registra la dirección URL de redireccionamiento, el proveedor de identidades redirige el explorador a la dirección URL de redireccionamiento especificada en la solicitud de autenticación. En este caso, la dirección URL es https://contoso.azurewebsites.net/.
  6. El explorador sigue esta dirección URL, que va directamente al servicio back-end en lugar de volver al proxy inverso.

Cookies rotas

Una discrepancia de nombre de host también puede provocar problemas cuando el servidor de aplicaciones emite cookies y usa el nombre de host entrante para construir el atributo Domain de la cookie. El atributo Domain garantiza que la cookie solo se usará para ese dominio específico. Estas cookies se pueden generar mediante el código de la aplicación o, como se indicó anteriormente, por características de la plataforma como App Service de conjunto de afinidad de ARR. En este diagrama se muestra el problema:

Diagram that illustrates an incorrect cookie domain.

  1. El explorador envía una solicitud para contoso.com al proxy inverso.
  2. El proxy inverso reescribe el nombre de host para que sea contoso.azurewebsites.net en la solicitud a la aplicación web de back-end (o a un dominio predeterminado similar para otro servicio).
  3. La aplicación genera una cookie que usa un dominio basado en el nombre de host contoso.azurewebsites.net entrante. El explorador almacena la cookie para este dominio específico en lugar del dominio contoso.com que el usuario está usando realmente.
  4. El explorador no incluye la cookie en ninguna solicitud posterior de contoso.com porque el dominio de la cookie contoso.azurewebsites.net no coincide con el dominio de la solicitud. La aplicación no recibe la cookie que emitió anteriormente. Como consecuencia, el usuario puede perder el estado que se supone que debe estar en la cookie, o características como la afinidad ARR no funcionen. Desafortunadamente, ninguno de estos problemas genera un error o es directamente visible para el usuario final. Esto dificulta la solución de problemas.

Guía de implementación para servicios comunes de Azure

Para evitar los posibles problemas que se deban tratar aquí, se recomienda conservar el nombre de host original en la llamada entre el proxy inverso y el servidor de aplicaciones back-end:

Diagram that shows a configuration in which the host name is preserved.

Configuración de back-end

Muchas plataformas de hospedaje web requieren que configure explícitamente los nombres de host entrantes permitidos. En las secciones siguientes se describe cómo implementar esta configuración para los servicios de Azure más comunes. Otras plataformas suelen proporcionar métodos similares para configurar dominios personalizados.

Si hospeda la aplicación web en App Service, puede adjuntar un nombre de dominio personalizado a la aplicación web y evitar el uso del nombre de host predeterminado azurewebsites.net hacia el back-end. No es necesario cambiar la resolución DNS al adjuntar un dominio personalizado a la aplicación web: puede comprobar el dominio mediante un registro TXT sin que ello afecte a los registros normales CNAME o A. (Estos registros se resolverán aún en la dirección IP del proxy inverso). Si necesita TLS/SSL de un extremo a otro, puede importar un certificado existente de Key Vault o usar un App Service Certificate para el dominio personalizado. (Tenga en cuenta que el certificado administrado de App Service gratuito no se puede usar en este caso, ya que requiere que el registro DNS del dominio se resuelva directamente en App Service, no en el proxy inverso).

De forma similar, si usa Spring Apps, puede usar un dominio personalizado para la aplicación para evitar el uso del nombre de host azuremicroservices.io. Puede importar un certificado existente o autofirmado si necesita TLS/SSL de un extremo a otro.

Si tiene un proxy inverso delante de API Management (que también actúa como proxy inverso), puede configurar un dominio personalizado en la instancia de API Management para evitar el uso del nombre de host azure-api.net. Puede importar un certificado administrado existente o gratuito si necesita TLS/SSL de un extremo a otro. Sin embargo, como se indicó anteriormente, las API son menos sensibles a los problemas causados por las discrepancias de nombres de host, por lo que es posible que esta configuración no sea tan importante.

Si hospeda las aplicaciones en otras plataformas, como en Kubernetes o directamente en máquinas virtuales, no hay ninguna funcionalidad integrada que dependa del nombre de host entrante. Usted es responsable de cómo se usa el nombre de host en el propio servidor de aplicaciones. La recomendación de conservar el nombre de host se sigue aplicando normalmente a todos los componentes de la aplicación que dependen de ella, a menos que la aplicación tenga en cuenta específicamente los servidores proxy inversos y respete los encabezados forwarded o X-Forwarded-Host, por ejemplo.

Configuración de proxy inverso

Al definir los back-ends dentro del proxy inverso, todavía puede usar el dominio predeterminado del servicio back-end, por ejemplo, https://contoso.azurewebsites.net/. El proxy inverso usa esta dirección URL para resolver la dirección IP correcta para el servicio back-end. Si usa el dominio predeterminado de la plataforma, siempre se garantiza que la dirección IP sea correcta. Normalmente no se puede usar el dominio de acceso público, como contoso.com, porque debe resolverse en la dirección IP del propio proxy inverso. (A menos que use técnicas de resolución DNS más avanzadas, como DNS de horizonte dividido).

Importante

Si tiene un firewall de próxima generación como Azure Firewall Premium entre el proxy inverso y el back-end final, es posible que tenga que usar DNS de horizonte dividido. Este tipo de firewall podría comprobar explícitamente si el encabezado Host HTTP se resuelve en la dirección IP de destino. En estos casos, el nombre de host original que usa el explorador debe resolverse en la dirección IP del proxy inverso cuando se accede a él desde la red pública de Internet. Sin embargo, desde el punto de vista del firewall, ese nombre de host debe resolverse en la dirección IP del servicio back-end final. Para más información, consulte Red de confianza cero para aplicaciones web con Azure Firewall y Application Gateway.

La mayoría de los servidores proxy inversos permiten configurar qué nombre de host se pasa al servicio back-end. La siguiente información explica cómo garantizar, para los servicios de Azure más comunes, que se usa el nombre de host original de la solicitud entrante.

Nota:

En todos los casos, también puede optar por invalidar el nombre de host por un dominio personalizado definido explícitamente en lugar de tomarlo de la solicitud entrante. Si la aplicación solo usa un dominio único, ese enfoque podría funcionar bien. Si la misma implementación de aplicación acepta solicitudes de varios dominios (por ejemplo, en escenarios multiinquilino), no se puede definir estáticamente un dominio único. Debe tomar el nombre de host de la solicitud entrante (de nuevo, a menos que la aplicación esté codificada explícitamente para tener en cuenta encabezados HTTP adicionales). Por lo tanto, la recomendación general es que no debe invalidar el nombre de host en absoluto. Pase el nombre de host entrante sin modificar al back-end.

Application Gateway

Si usa Application Gateway como proxy inverso, puede asegurarse de que el nombre de host original se conserva al deshabilitar Invalidar con el nuevo nombre de host en el valor HTTP de back-end. Al hacerlo, se deshabilitan Elegir nombre de host de la dirección de back-end e Invalidar por un nombre de dominio específico. (Ambas configuraciones invalidan el nombre de host). En las propiedades de Azure Resource Manager de Application Gateway, esta configuración corresponde a establecer la propiedad hostName en null y pickHostNameFromBackendAddress en false.

Dado que los sondeos de estado se envían fuera del contexto de una solicitud entrante, no pueden determinar dinámicamente el nombre de host correcto. En su lugar, debe crear un sondeo de estado personalizado, deshabilitar Elegir nombre de host de la configuración HTTP de back-end y especificar explícitamente el nombre de host. Para este nombre de host, también debe usar un dominio personalizado adecuado para mantener la coherencia. (Sin embargo, aquí podría usar el dominio predeterminado de la plataforma de hospedaje, porque los sondeos de estado omiten cookies incorrectas o redirigen direcciones URL en la respuesta).

Azure Front Door

Si usa Azure Front Door, puede evitar invalidar el nombre de host si deja el encabezado host de back-end en blanco en la definición del grupo de back-end. En el Resource Manager del grupo de back-end, esta configuración corresponde a establecer backendHostHeaderen null.

Si usa Azure Front Door Estándar o Premium, puede conservar el nombre de host si deja el encabezado de host de origen en blanco en la definición de origen. En la definición de Resource Manager del origen, esta configuración corresponde al valor originHostHeader de null.

API Management

De manera predeterminada, API Management invalida el nombre de host que se envía al back-end con el componente host de la dirección URL del servicio web de la API (que corresponde al valor serviceUrl de la definición de Resource Manager de la API).

Puede forzar a API Management usar en su lugar el nombre de host de la solicitud entrante al agregar una inbounddirectiva Establecer encabezado, como se muestra a continuación:

<inbound>
  <base />
  <set-header name="Host" exists-action="override">
    <value>@(context.Request.OriginalUrl.Host)</value>
  </set-header>
</inbound>

Sin embargo, como se indicó anteriormente, las API son menos sensibles a los problemas causados por las discrepancias de nombres de host, por lo que es posible que esta configuración no sea tan importante.

Pasos siguientes