Recomendamos preservar o nome do host HTTP original ao usar um proxy reverso na frente de um aplicativo Web. Ter um nome de host diferente no proxy reverso do que o fornecido para o servidor de aplicativos de back-end pode levar a cookies ou URLs de redirecionamento que não funcionam corretamente. Por exemplo, o estado da sessão pode se perder, a autenticação pode falhar ou as URLs de back-end podem ser expostas inadvertidamente aos usuários finais. Você pode evitar esses problemas preservando o nome do host da solicitação inicial para que o servidor de aplicativos veja o mesmo domínio que o navegador da Web.
Essas diretrizes se aplicam especialmente a aplicativos hospedados em ofertas de PaaS (plataforma como serviço), como do Serviço de Aplicativo do Azure e do Azure Spring Apps. Este artigo fornece diretrizes específicas de implementação de
Nota
As APIs Web geralmente são menos sensíveis aos problemas causados por incompatibilidades de nome de host. Eles geralmente não dependem de cookies, a menos que você usar cookies para proteger as comunicações entre um aplicativo de página única e seude API de back-end, por exemplo, em um padrão conhecido como back-ends para front-ends. As APIs Web geralmente não retornam URLs absolutas de volta para si mesmas, exceto em determinados estilos de API, como OData (Open Data Protocol) e HATEOAS. Se a implementação da API depender de cookies ou gerar URLs absolutas, as diretrizes fornecidas neste artigo se aplicarão.
Se você precisar de TLS/SSL de ponta a ponta (a conexão entre o proxy reverso e o serviço de back-end usa HTTPS), o serviço de back-end também precisará de um certificado TLS correspondente para o nome do host original. Esse requisito adiciona complexidade operacional quando você implanta e renova certificados, mas muitos serviços de PaaS oferecem certificados TLS gratuitos totalmente gerenciados.
Contexto
O host de uma solicitação HTTP
Em muitos casos, o servidor de aplicativos ou algum componente no pipeline de solicitação precisa do nome de domínio da Internet que foi usado pelo navegador para acessá-lo. Esta é a de host contoso.com
(que o navegador resolve para um endereço IP usando DNS). O valor do host normalmente é determinado do componente de host do URI de solicitação, que o navegador envia para o aplicativo como o cabeçalho HTTP Host
.
Importante
Nunca use o valor do host em um mecanismo de segurança. O valor é fornecido pelo navegador ou por algum outro agente de usuário e pode ser facilmente manipulado por um usuário final.
Em alguns cenários, especialmente quando há um proxy reverso HTTP na cadeia de solicitações, o cabeçalho do host original pode ser alterado antes de chegar ao servidor de aplicativos. Um proxy reverso fecha a sessão de rede do cliente e configura uma nova conexão com o back-end. Nesta nova sessão, ela pode carregar o nome do host original da sessão do cliente ou definir uma nova. No último caso, o proxy geralmente ainda envia o valor original do host em outros cabeçalhos HTTP, como Forwarded
ou X-Forwarded-Host
. Esse valor permite que os aplicativos determinem o nome do host original, mas somente se eles estiverem codificados para ler esses cabeçalhos.
Por que as plataformas Web usam o nome do host
Os serviços de PaaS multilocatário geralmente exigem um nome de host registrado e validado para rotear uma solicitação de entrada para o servidor de back-end do locatário apropriado. Isso ocorre porque normalmente há um pool compartilhado de balanceadores de carga que aceitam solicitações de entrada para todos os locatários. Os locatários geralmente usam o nome do host de entrada para procurar o back-end correto para o locatário do cliente.
Para facilitar a introdução, essas plataformas normalmente fornecem um domínio padrão pré-configurado para rotear o tráfego para sua instância implantada. Para o Serviço de Aplicativo, esse domínio padrão é azurewebsites.net
. Cada aplicativo Web criado obtém seu próprio subdomínio, por exemplo, contoso.azurewebsites.net
. Da mesma forma, o domínio padrão é azuremicroservices.io
para o Azure Spring Apps e azure-api.net
para Gerenciamento de API.
Para implantações de produção, você não usa esses domínios padrão. Em vez disso, você fornece seu próprio domínio para se alinhar com a marca da sua organização ou aplicativo. Por exemplo, contoso.com
poderia resolver nos bastidores para o aplicativo Web contoso.azurewebsites.net
no Serviço de Aplicativo, mas esse domínio não deve ser visível para um usuário final visitando o site. No entanto, esse nome de host contoso.com
personalizado deve ser registrado no serviço PaaS, para que a plataforma possa identificar o servidor de back-end que deve responder à solicitação.
Por que os aplicativos usam o nome do host
Dois motivos comuns pelos quais um servidor de aplicativos precisa do nome do host são construir URLs absolutas e emitir cookies para um domínio específico. Por exemplo, quando o código do aplicativo precisa:
- Retorne uma URL absoluta em vez de uma URL relativa em sua resposta HTTP (embora geralmente sites tendem a renderizar links relativos quando possível).
- Gere uma URL a ser usada fora de sua resposta HTTP em que AS URLs relativas não podem ser usadas, como enviar por email um link para o site para um usuário.
- Gere uma URL de redirecionamento absoluta para um serviço externo. Por exemplo, para um serviço de autenticação como o Microsoft Entra ID para indicar onde ele deve retornar o usuário após a autenticação bem-sucedida.
- Emita cookies HTTP restritos a um determinado host, conforme definido no atributo
Domain
do cookie.
Você pode atender a todos esses requisitos adicionando o nome de host esperado à configuração do aplicativo e usando esse valor definido estaticamente em vez do nome do host de entrada na solicitação. No entanto, essa abordagem complica o desenvolvimento e a implantação de aplicativos. Além disso, uma única instalação do aplicativo pode atender a vários hosts. Por exemplo, um único aplicativo Web pode ser usado para vários locatários de aplicativos que têm seus próprios nomes de host exclusivos (como tenant1.contoso.com
e tenant2.contoso.com
).
E, às vezes, o nome do host de entrada é usado por componentes fora do código do aplicativo ou no middleware no servidor de aplicativos sobre o qual você não tem controle total. Aqui estão alguns exemplos:
- No Serviço de Aplicativo, você pode impor HTTPS para seu aplicativo Web. Isso faz com que qualquer solicitação HTTP que não esteja segura para redirecionar para HTTPS. Nesse caso, o nome do host de entrada é usado para gerar a URL absoluta para o cabeçalho
Location
do redirecionamento HTTP. - O Azure Spring Apps usa um recurso semelhante para impor https. Ele também usa o host de entrada para gerar a URL HTTPS.
- O Serviço de Aplicativo tem uma configuração de afinidade ARR para habilitar sessões autoadesivas, de modo que as solicitações da mesma instância do navegador sejam sempre atendidas pelo mesmo servidor de back-end. Isso é executado pelos front-ends do Serviço de Aplicativo, que adicionam um cookie à resposta HTTP. O
Domain
do cookie está definido como o host de entrada. - O Serviço de Aplicativo fornece recursos de autenticação e autorização para permitir facilmente que os usuários entrem e acessem dados em APIs.
- O nome do host de entrada é usado para construir a URL de redirecionamento para a qual o provedor de identidade precisa retornar o usuário após a autenticação bem-sucedida.
- Habilitar esse recurso por padrão também ativa ode redirecionamento HTTP para HTTPS. Novamente, o nome do host de entrada é usado para gerar o local de redirecionamento.
Por que você pode ser tentado a substituir o nome do host
Digamos que você crie um aplicativo Web no Serviço de Aplicativo que tenha um domínio padrão de contoso.azurewebsites.net
. (Ou em outro serviço como o Azure Spring Apps.) Você não configurou um domínio personalizado no Serviço de Aplicativo. Para colocar um proxy reverso como o Gateway de Aplicativo (ou qualquer serviço semelhante) na frente desse aplicativo, defina o registro DNS para contoso.com
para resolver para o endereço IP do Gateway de Aplicativo. Portanto, ele recebe a solicitação de contoso.com
do navegador e está configurado para encaminhar essa solicitação para o endereço IP que contoso.azurewebsites.net
resolve: este é o serviço de back-end final para o host solicitado. Nesse caso, no entanto, o Serviço de Aplicativo não reconhece o domínio personalizado contoso.com
e rejeita todas as solicitações de entrada para esse nome de host. Ele não pode determinar para onde rotear a solicitação.
Pode parecer que a maneira fácil de fazer essa configuração funcionar é substituir ou reescrever o cabeçalho Host
da solicitação HTTP no Gateway de Aplicativo e defini-lo com o valor de contoso.azurewebsites.net
. Se você fizer isso, a solicitação de saída do Gateway de Aplicativo fará parecer que a solicitação original foi realmente destinada a contoso.azurewebsites.net
em vez de contoso.com
:
Neste ponto, o Serviço de Aplicativo reconhece o nome do host e aceita a solicitação sem exigir que um nome de domínio personalizado seja configurado. Na verdade, Gateway de Aplicativo facilita a substituição do cabeçalho do host com o host do pool de back-end. Azure Front Door faz isso por padrão.
O problema com essa solução, no entanto, é que ela pode resultar em vários problemas quando o aplicativo não vir o nome do host original.
Possíveis problemas
URLs absolutas incorretas
Se o nome do host original não for preservado e o servidor de aplicativos usar o nome do host de entrada para gerar URLs absolutas, o domínio de back-end poderá ser divulgado para um usuário final. Essas URLs absolutas podem ser geradas pelo código do aplicativo ou, conforme observado anteriormente, por recursos da plataforma, como o suporte para redirecionamento HTTP-to-HTTPS no Serviço de Aplicativo e no Azure Spring Apps. Este diagrama ilustra o problema:
- O navegador envia uma solicitação de
contoso.com
para o proxy reverso. - O proxy reverso reescreve o nome do host para
contoso.azurewebsites.net
na solicitação para o aplicativo Web de back-end (ou para um domínio padrão semelhante para outro serviço). - O aplicativo gera uma URL absoluta baseada no nome do host de
contoso.azurewebsites.net
de entrada, por exemplo,https://contoso.azurewebsites.net/
. - O navegador segue essa URL, que vai diretamente para o serviço de back-end em vez de voltar para o proxy reverso em
contoso.com
.
Isso pode até representar um risco de segurança no caso comum em que o proxy reverso também serve como um firewall de aplicativo Web. O usuário recebe uma URL que vai diretamente para o aplicativo de back-end e ignora o proxy reverso.
Importante
Devido a esse risco de segurança, você precisa garantir que o aplicativo Web de back-end aceite diretamente o tráfego de rede do proxy reverso (por exemplo, usando restrições de acesso no Serviço de Aplicativo). Se você fizer isso, mesmo que uma URL absoluta incorreta seja gerada, pelo menos ela não funcionará e não poderá ser usada por um usuário mal-intencionado para ignorar o firewall.
URLs de redirecionamento incorretas
Um caso comum e mais específico do cenário anterior ocorre quando URLs de redirecionamento absoluto são geradas. Essas URLs são exigidas por serviços de identidade como a ID do Microsoft Entra quando você usa protocolos de identidade baseados em navegador, como OpenID Connect, Open Authorization (OAuth) 2.0 ou SAML (Security Assertion Markup Language) 2.0. Essas URLs de redirecionamento podem ser geradas pelo próprio servidor de aplicativos ou middleware ou, conforme observado anteriormente, por recursos de plataforma como o serviço de aplicativo recursos de autenticação e autorização. Este diagrama ilustra o problema:
- O navegador envia uma solicitação de
contoso.com
para o proxy reverso. - O proxy reverso reescreve o nome do host para
contoso.azurewebsites.net
na solicitação para o aplicativo Web de back-end (ou para um domínio padrão semelhante para outro serviço). - O aplicativo gera uma URL de redirecionamento absoluta baseada no nome do host de
contoso.azurewebsites.net
de entrada, por exemplo,https://contoso.azurewebsites.net/
. - O navegador vai para o provedor de identidade para autenticar o usuário. A solicitação inclui a URL de redirecionamento gerada para indicar onde retornar o usuário após a autenticação bem-sucedida.
- Os provedores de identidade normalmente exigem que as URLs de redirecionamento sejam registradas antecipadamente, portanto, neste ponto, o provedor de identidade deve rejeitar a solicitação porque a URL de redirecionamento fornecida não está registrada. (Não era para ser usado.) Se, por algum motivo, a URL de redirecionamento estiver registrada, no entanto, o provedor de identidade redirecionará o navegador para a URL de redirecionamento especificada na solicitação de autenticação. Nesse caso, a URL é
https://contoso.azurewebsites.net/
. - O navegador segue essa URL, que vai diretamente para o serviço de back-end em vez de voltar para o proxy reverso.
Cookies quebrados
Uma incompatibilidade de nome de host também pode causar problemas quando o servidor de aplicativos emite cookies e usa o nome do host de entrada para construir o atributo Domain
do cookie. O atributo Domínio garante que o cookie será usado somente para esse domínio específico. Esses cookies podem ser gerados pelo código do aplicativo ou, conforme observado anteriormente, por recursos da plataforma, como o serviço de aplicativo configuração de afinidade ARR. Este diagrama ilustra o problema:
- O navegador envia uma solicitação de
contoso.com
para o proxy reverso. - O proxy reverso reescreve o nome do host a ser
contoso.azurewebsites.net
na solicitação para o aplicativo Web de back-end (ou para um domínio padrão semelhante para outro serviço). - O aplicativo gera um cookie que usa um domínio com base na entrada
contoso.azurewebsites.net
nome do host. O navegador armazena o cookie para esse domínio específico em vez do domíniocontoso.com
que o usuário está realmente usando. - O navegador não inclui o cookie em nenhuma solicitação subsequente para
contoso.com
porque o domíniocontoso.azurewebsites.net
do cookie não corresponde ao domínio da solicitação. O aplicativo não recebe o cookie emitido anteriormente. Como consequência, o usuário pode perder o estado que deveria estar no cookie ou recursos como afinidade ARR não funcionam. Infelizmente, nenhum desses problemas gera um erro ou fica diretamente visível para o usuário final. Isso os torna difíceis de solucionar problemas.
Diretrizes de implementação para serviços comuns do Azure
Para evitar os possíveis problemas discutidos aqui, recomendamos preservar o nome do host original na chamada entre o proxy reverso e o servidor de aplicativos de back-end:
Configuração de back-end
Muitas plataformas de hospedagem da Web exigem que você configure explicitamente os nomes de host de entrada permitidos. As seções a seguir descrevem como implementar essa configuração para os serviços mais comuns do Azure. Outras plataformas geralmente fornecem métodos semelhantes para configurar domínios personalizados.
Se você hospedar seu aplicativo Web em serviço de aplicativo, poderá anexar um nome de domínio personalizado ao aplicativo Web e evitar usar o nome de host azurewebsites.net
padrão no back-end. Você não precisa alterar sua resolução DNS ao anexar um domínio personalizado ao aplicativo Web: você pode verificar o domínio usando um registro TXT
sem afetar seus registros de CNAME
ou A
regulares. (Esses registros ainda serão resolvidos para o endereço IP do proxy reverso.) Se você precisar de TLS/SSL de ponta a ponta, poderá importar um certificado existente do Key Vault ou usar um certificado do Serviço de Aplicativo para seu domínio personalizado. (Observe que o certificado gerenciado do Serviço de Aplicativo
Da mesma forma, se você estiver usando do Spring Apps, poderá usar um domínio personalizado para o aplicativo para evitar o uso do nome do host azuremicroservices.io
. Você pode importar um certificado existente ou autoassinado se precisar de TLS/SSL de ponta a ponta.
Se você tiver um proxy reverso na frente de de Gerenciamento de API (que também atua como um proxy reverso), poderá configurar um domínio personalizado em sua instância de Gerenciamento de API para evitar o uso do nome do host azure-api.net
. Você pode importar um certificado gerenciado existente ou gratuito se precisar de TLS/SSL de ponta a ponta. Como observado anteriormente, no entanto, as APIs são menos sensíveis aos problemas causados por incompatibilidades de nome de host, portanto, essa configuração pode não ser tão importante.
Se você hospedar seus aplicativos em outras plataformas, como no Kubernetes ou diretamente em máquinas virtuais, não haverá nenhuma funcionalidade interna que dependa do nome do host de entrada. Você é responsável por como o nome do host é usado no próprio servidor de aplicativos. A recomendação para preservar o nome do host normalmente ainda se aplica a todos os componentes em seu aplicativo que dependem dele, a menos que você lembre especificamente seu aplicativo de proxies reversos e respeite os cabeçalhos forwarded
ou X-Forwarded-Host
, por exemplo.
Configuração de proxy reverso
Quando você define os back-ends dentro do proxy reverso, ainda pode usar o domínio padrão do serviço de back-end, por exemplo, https://contoso.azurewebsites.net/
. Essa URL é usada pelo proxy reverso para resolver o endereço IP correto para o serviço de back-end. Se você usar o domínio padrão da plataforma, o endereço IP sempre terá a garantia de estar correto. Normalmente, você não pode usar o domínio voltado para o público, como contoso.com
, porque ele deve ser resolvido para o endereço IP do próprio proxy reverso. (A menos que você use técnicas de resolução DNS mais avançadas, como DNS de horizonte dividido).
Importante
Se você tiver um firewall de última geração como o Firewall do Azure Premium entre o proxy reverso e o back-end final, talvez seja necessário usar o DNS de horizonte dividido. Esse tipo de firewall pode verificar explicitamente se o cabeçalho http Host
é resolvido para o endereço IP de destino. Nesses casos, o nome do host original usado pelo navegador deve ser resolvido para o endereço IP do proxy reverso quando ele for acessado da Internet pública. No entanto, do ponto de vista do firewall, esse nome de host deve ser resolvido para o endereço IP do serviço de back-end final. Para obter mais informações, consulte rede de confiança zero para aplicativos Web com o Firewall do Azure e o Gateway de Aplicativo.
A maioria dos proxies reversos permite configurar qual nome de host é passado para o serviço de back-end. As informações a seguir explicam como garantir que, para os serviços mais comuns do Azure, o nome do host original da solicitação de entrada seja usado.
Nota
Em todos os casos, você também pode optar por substituir o nome do host por um domínio personalizado definido explicitamente em vez de retirá-lo da solicitação de entrada. Se o aplicativo usar apenas um único domínio, essa abordagem poderá funcionar bem. Se a mesma implantação de aplicativo aceitar solicitações de vários domínios (por exemplo, em cenários multilocatários), você não poderá definir estaticamente um único domínio. Você deve levar o nome do host da solicitação de entrada (novamente, a menos que o aplicativo esteja explicitamente codificado para levar em conta cabeçalhos HTTP adicionais). Portanto, a recomendação geral é que você não deve substituir o nome do host. Passe o nome do host de entrada não modificado para o back-end.
Gateway de Aplicativo
Se você usar Gateway de Aplicativo como proxy reverso, poderá garantir que o nome do host original seja preservado desabilitando Substituição com o novo nome de host na configuração HTTP de back-end. Isso desabilita Escolher o nome do host do endereço de back-end e Substituir com o nome de domínio específico. (Ambas as configurações substituem o nome do host.) No propriedades do Azure Resource Manager para o Gateway de Aplicativo, essa configuração corresponde à configuração da propriedade hostName
como null
e pickHostNameFromBackendAddress
para false
.
Como as investigações de integridade são enviadas fora do contexto de uma solicitação de entrada, elas não podem determinar dinamicamente o nome correto do host. Em vez disso, você precisa criar uma investigação de integridade personalizada, desabilitar Escolher o nome do host das configurações http de back-ende especificar explicitamente o nome do host. Para esse nome de host, você também deve usar um domínio personalizado apropriado para consistência. (No entanto, você pode usar o domínio padrão da plataforma de hospedagem aqui, pois as investigações de integridade ignoram cookies incorretos ou URLs de redirecionamento na resposta.)
Azure Front Door
Se você usar do Azure Front Door, poderá preservar o nome do host deixando o cabeçalho do host de origem em branco na definição de origem. Na definição do Resource Manager dode origem, essa configuração corresponde à configuração originHostHeader
para null
.
Gerenciamento de API
Por padrão, gerenciamento de API substitui o nome do host que é enviado para o back-end com o componente host da URL do serviço Web da API (que corresponde ao valor serviceUrl
da definição do Resource Manager dode API).
Você pode forçar o Gerenciamento de API a usar o nome do host da solicitação de entrada adicionando um cabeçalho inbound
Definir política, da seguinte maneira:
<inbound>
<base />
<set-header name="Host" exists-action="override">
<value>@(context.Request.OriginalUrl.Host)</value>
</set-header>
</inbound>
Como observado anteriormente, no entanto, as APIs são menos sensíveis aos problemas causados por incompatibilidades de nome de host, portanto, essa configuração pode não ser tão importante.
Próximas etapas
- do Serviço de Aplicativo
- do
Spring Apps - do Gateway de Aplicativo
- do Azure Front Door
- de Gerenciamento de API