Editar

Partilhar via


Preservar o nome de host HTTP original entre um proxy reverso e seu aplicativo Web back-end

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

Recomendamos que você preserve o nome de host HTTP original ao usar um proxy reverso na frente de um aplicativo Web. Ter um nome de host diferente no proxy reverso daquele que é fornecido ao servidor de aplicativos back-end pode levar a cookies ou redirecionar URLs que não funcionam corretamente. Por exemplo, o estado da sessão pode ser perdido, a autenticação pode falhar ou URLs de back-end podem ser inadvertidamente expostas 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.

Estas orientações aplicam-se especialmente a aplicações alojadas em ofertas de plataforma como serviço (PaaS), como do Serviço de Aplicações do Azure e Azure Spring Apps. Este artigo fornece de diretrizes de implementação de específicas para do Gateway de Aplicativo do Azure, da Porta da Frente do Azure e de Gerenciamento de API do Azure, que são serviços de proxy reverso comumente usados.

Observação

As APIs da Web geralmente são menos sensíveis aos problemas causados por incompatibilidades de nomes 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 sua API de back-end, por exemplo, em um padrão conhecido como Backends for Frontends. As APIs da Web geralmente não retornam URLs absolutas para si mesmas, exceto em determinados estilos de API, como Open Data Protocol (OData) e HATEOAS. Se a implementação da API depender de cookies ou gerar URLs absolutos, as orientações fornecidas neste artigo se aplicam.

Se você precisar de TLS/SSL de ponta a ponta (a conexão entre o proxy reverso e o serviço back-end usa HTTPS), o serviço back-end também precisará de um certificado TLS correspondente para o nome de host original. Esse requisito adiciona complexidade operacional quando você implanta e renova certificados, mas muitos serviços PaaS oferecem certificados TLS gratuitos que são 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. Este é o de host da solicitação. Pode ser um endereço IP, mas geralmente é um nome como contoso.com (que o navegador resolve para um endereço IP usando DNS). O valor do host normalmente é determinado a partir do componente 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, ele pode transferir o nome do host original da sessão do cliente ou definir um novo. Neste último caso, o proxy geralmente ainda envia o valor de host original 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 estiverem codificados para ler esses cabeçalhos.

Por que as plataformas da Web usam o nome do host

Os serviços PaaS multilocatários geralmente exigem um nome de host registrado e validado para rotear uma solicitação de entrada para o servidor 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 os primeiros passos, essas plataformas geralmente 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 que você cria 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 o 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 pode resolver nos bastidores do aplicativo Web contoso.azurewebsites.net no Serviço de Aplicativo, mas esse domínio não deve estar visível para um usuário final que visita o site. No entanto, esse nome de host de contoso.com personalizado deve ser registrado no serviço PaaS para que a plataforma possa identificar o servidor back-end que deve responder à solicitação.

Diagrama que ilustra o roteamento baseado em host no Serviço de Aplicativo.

Por que os aplicativos usam o nome do host

Duas razões comuns pelas quais um servidor de aplicativos precisa do nome do host são construir URLs absolutos 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 relativa em sua resposta HTTP (embora geralmente os sites tendam a renderizar links relativos quando possível).
  • Gere um URL para ser usado fora de sua resposta HTTP onde URLs relativos não podem ser usados, como para enviar um link para o site por e-mail para um usuário.
  • Gere um URL de redirecionamento absoluto 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.
  • Emitir 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 de 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 servir 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 em middleware no servidor de aplicativos sobre o qual você não tem controle total. Eis alguns exemplos:

  • No Serviço de Aplicativo, você pode impor HTTPS para seu aplicativo Web. Isso faz com que todas as solicitações HTTP que não são seguras redirecionem 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 adesivas, de modo que as solicitações da mesma instância do navegador sejam sempre atendidas pelo mesmo servidor back-end. Isso é realizado pelos front-ends do Serviço de Aplicativo, que adicionam um cookie à resposta HTTP. A Domain do cookie é definida para 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.

Por que você pode ficar 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 Application Gateway (ou qualquer serviço semelhante) na frente deste aplicativo, defina o registro DNS para contoso.com resolver para o endereço IP do Application Gateway. Portanto, ele recebe a solicitação de contoso.com do navegador e está configurado para encaminhar essa solicitação para o endereço IP para o qual 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 encaminhar a solicitação.

Pode parecer que a maneira mais fácil de fazer essa configuração funcionar é substituir ou reescrever o cabeçalho Host da solicitação HTTP no Application Gateway e defini-lo com o valor de contoso.azurewebsites.net. Se você fizer isso, a solicitação de saída do Application Gateway faz parecer que a solicitação original foi realmente destinada a contoso.azurewebsites.net em vez de contoso.com:

Diagrama que ilustra uma configuração com o nome do host substituído.

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, Application Gateway facilita a substituição do de cabeçalho do host pelo host do pool de back-end. Azure Front Door até o faz por padrão.

O problema com essa solução, no entanto, é que ela pode resultar em vários problemas quando o aplicativo não vê o nome de host original.

Problemas potenciais

URLs absolutos incorretos

Se o nome de host original não for preservado e o servidor de aplicativos usar o nome de host de entrada para gerar URLs absolutas, o domínio back-end poderá ser divulgado para um usuário final. Essas URLs absolutas podem ser geradas pelo código do aplicativo ou, como observado anteriormente, por recursos da plataforma, como o suporte para redirecionamento HTTP para HTTPS no Serviço de Aplicativo e nos Aplicativos Azure Spring. Este diagrama ilustra o problema:

Diagrama que ilustra o problema de URLs absolutos incorretos.

  1. O navegador envia uma solicitação de contoso.com para o proxy reverso.
  2. O proxy reverso regrava o nome do host para contoso.azurewebsites.net na solicitação para o aplicativo Web back-end (ou para um domínio padrão semelhante para outro serviço).
  3. O aplicativo gera uma URL absoluta baseada no nome do host de entrada contoso.azurewebsites.net, por exemplo, https://contoso.azurewebsites.net/.
  4. 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 direto para o aplicativo back-end e ignora o proxy reverso.

Importante

Devido a esse risco de segurança, você precisa garantir que o aplicativo Web back-end só 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 um URL absoluto incorreto seja gerado, pelo menos ele não funciona e não pode ser usado por um usuário mal-intencionado para contornar o firewall.

URLs de redirecionamento incorretos

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 o Microsoft Entra ID quando você usa protocolos de identidade baseados em navegador, como OpenID Connect, Open Authorization (OAuth) 2.0 ou Security Assertion Markup Language (SAML) 2.0. Essas URLs de redirecionamento podem ser geradas pelo próprio servidor de aplicativos ou middleware ou, como observado anteriormente, por recursos da plataforma, como o serviço de aplicativo os recursos de autenticação e autorização. Este diagrama ilustra o problema:

Diagrama que ilustra o problema de URLs de redirecionamento incorretas.

  1. O navegador envia uma solicitação de contoso.com para o proxy reverso.
  2. O proxy reverso regrava o nome do host para contoso.azurewebsites.net na solicitação para o aplicativo Web back-end (ou para um domínio padrão semelhante para outro serviço).
  3. O aplicativo gera uma URL de redirecionamento absoluto baseada no nome do host de entrada contoso.azurewebsites.net, por exemplo, https://contoso.azurewebsites.net/.
  4. 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.
  5. Os provedores de identidade normalmente exigem que as URLs de redirecionamento sejam registradas antecipadamente, portanto, neste momento, 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. Neste caso, o URL é https://contoso.azurewebsites.net/.
  6. 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 levar a problemas quando o servidor de aplicativos emite cookies e usa o nome de host de entrada para construir o atributo Domain do cookie. O atributo Domain garante que o cookie será usado apenas para esse domínio específico. Esses cookies podem ser gerados pelo código do aplicativo ou, como observado anteriormente, por recursos da plataforma, como o serviço do aplicativo a configuração de afinidade ARR. Este diagrama ilustra o problema:

Diagrama que ilustra um domínio de cookie incorreto.

  1. O navegador envia uma solicitação de contoso.com para o proxy reverso.
  2. O proxy reverso reescreve o nome do host a ser contoso.azurewebsites.net na solicitação para o aplicativo Web back-end (ou para um domínio padrão semelhante para outro serviço).
  3. O aplicativo gera um cookie que usa um domínio com base no nome de entrada contoso.azurewebsites.net host. O navegador armazena o cookie para este domínio específico em vez do domínio contoso.com que o usuário está realmente usando.
  4. O navegador não inclui o cookie em qualquer solicitação subsequente de contoso.com porque o domínio contoso.azurewebsites.net do cookie não corresponde ao domínio da solicitação. A aplicação não recebe o cookie que emitiu 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 é diretamente visível para o usuário final. Isso dificulta a solução de problemas.

Diretrizes de implementação para serviços comuns do Azure

Para evitar os possíveis problemas discutidos aqui, recomendamos que você preserve o nome do host original na chamada entre o proxy reverso e o servidor de aplicativos back-end:

Diagrama que mostra uma configuração na qual o nome do host é preservado.

Configuração de back-end

Muitas plataformas de hospedagem na 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 no Serviço de Aplicativo , poderá anexar um nome de domínio personalizado ao do aplicativo Web e evitar usar o nome de host azurewebsites.net padrão no back-end. Não é necessário alterar a resolução DNS quando anexa um domínio personalizado à aplicação Web: pode verificar o domínio utilizando um registo TXT sem afetar os seus registos 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 Cofre da Chave ou usar um de Certificado do Serviço de Aplicativo para seu domínio personalizado. (Observe que o de certificado gerenciado gratuito do Serviço de Aplicativo não pode ser usado nesse caso, pois requer que o registro DNS do domínio seja resolvido diretamente para o Serviço de Aplicativo, não para o proxy reverso.)

Da mesma forma, se você estiver usando Spring Apps, poderá usar um domínio personalizado para sua de aplicativo para evitar o uso do nome de 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 de 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 nomes 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á 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 de preservar o nome do host normalmente ainda se aplica a quaisquer componentes em seu aplicativo que dependam dele, a menos que você especificamente torne seu aplicativo ciente de proxies reversos e respeite os cabeçalhos forwarded ou X-Forwarded-Host, por exemplo.

Configuração de proxy reverso

Ao definir os back-ends dentro do proxy reverso, você ainda pode usar o domínio padrão do serviço 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 back-end. Se você usar o domínio padrão da plataforma, o endereço IP é sempre garantido como 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 de DNS mais avançadas, como DNS de horizonte dividido).

Importante

Se você tiver um firewall de próxima geração, como Premium do Firewall do Azure 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 de host original usado pelo navegador deve ser resolvido para o endereço IP do proxy reverso quando ele é acessado pela Internet pública. Do ponto de vista do firewall, no entanto, esse nome de host deve ser resolvido para o endereço IP do serviço 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 back-end. As informações a seguir explicam como garantir, para os serviços mais comuns do Azure, que o nome de host original da solicitação de entrada seja usado.

Observação

Em todos os casos, você também pode optar por substituir o nome do host por um domínio personalizado explicitamente definido em vez de retirá-lo da solicitação de entrada. Se o aplicativo usa apenas um único domínio, essa abordagem pode funcionar bem. Se a mesma implantação de aplicativo aceitar solicitações de vários domínios (por exemplo, em cenários multilocatário), você não poderá definir estaticamente um único domínio. Você deve pegar o nome do host da solicitação de entrada (novamente, a menos que o aplicativo seja 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 sem modificações para o back-end.

Gateway de aplicativo

Se você usar do Gateway de Aplicativo como proxy reverso, poderá garantir que o nome do host original seja preservado desativando Substituição com novo nome de host na configuração HTTP de back-end. Isso desativa o Escolher nome de host do endereço back-end e Substituir com nome de domínio específico. (Ambas as configurações substituem o nome do host.) No propriedades do Azure Resource Manager para o Application Gateway, essa configuração corresponde à definição da propriedade hostName como null e pickHostNameFromBackendAddress como false.

Como os testes de integridade são enviados fora do contexto de uma solicitação de entrada, eles não podem determinar dinamicamente o nome de host correto. Em vez disso, você precisa criar uma investigação de integridade personalizada, desabilitar Escolher nome do host nas 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. (Você pode, no entanto, usar o domínio padrão da plataforma de hospedagem aqui, porque as sondas de integridade ignoram cookies incorretos ou redirecionam URLs 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, de Gerenciamento de API substitui o nome do host enviado para o back-end pelo componente host da URL do serviço Web da API (que corresponde ao valor serviceUrl da definição do Resource Manager da API).

Você pode forçar o Gerenciamento de API a usar o nome do host da solicitação de entrada adicionando um cabeçalho inboundDefinir 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 nomes de host, portanto, essa configuração pode não ser tão importante.

Próximos passos