Mantenere il nome host HTTP originale tra un proxy inverso e l'applicazione Web back-end

Gestione API di Azure
Servizio app di Azure
Gateway applicazione di Azure
Frontdoor di Azure
Azure Spring Apps

È consigliabile mantenere il nome host HTTP originale quando si usa un proxy inverso davanti a un'applicazione Web. Avere un nome host diverso nel proxy inverso rispetto a quello fornito al server applicazioni back-end può causare cookie o URL di reindirizzamento che non funzionano correttamente. Ad esempio, lo stato della sessione può andare perso, l'autenticazione può non riuscire o gli URL back-end possono essere esposti inavvertitamente agli utenti finali. È possibile evitare questi problemi mantenendo il nome host della richiesta iniziale in modo che il server applicazioni veda lo stesso dominio del Web browser.

Queste linee guida si applicano in particolare alle applicazioni ospitate in offerte PaaS (Platform as a Service), ad esempio app Azure Service e Azure Spring Apps. Questo articolo fornisce indicazioni specifiche sull'implementazione per app Azure lication Gateway, Frontdoor di Azure e Azure Gestione API, che vengono comunemente usati servizi proxy inversi.

Nota

Le API Web sono in genere meno sensibili ai problemi causati dalla mancata corrispondenza del nome host. In genere non dipendono dai cookie, a meno che non si usino cookie per proteggere le comunicazioni tra un'app a pagina singola e l'API back-end, ad esempio, in un modello noto come back-end per i front-end. Le API Web spesso non restituiscono URL assoluti a se stessi, tranne in determinati stili api, ad esempio OData e HATEOAS. Se l'implementazione dell'API dipende dai cookie o genera URL assoluti, vengono applicate le indicazioni fornite in questo articolo.

Se è necessario TLS/SSL end-to-end (la connessione tra il proxy inverso e il servizio back-end usa HTTPS), il servizio back-end necessita anche di un certificato TLS corrispondente per il nome host originale. Questo requisito aggiunge complessità operativa quando si distribuiscono e si rinnovano i certificati, ma molti servizi PaaS offrono certificati TLS gratuiti completamente gestiti.

Contesto

Host di una richiesta HTTP

In molti casi, il server applicazioni o un componente nella pipeline di richiesta richiede il nome di dominio Internet usato dal browser per accedervi. Si tratta dell'host della richiesta. Può trattarsi di un indirizzo IP, ma in genere si tratta di un nome simile contoso.com al quale il browser viene quindi risolto in un indirizzo IP tramite DNS. Il valore host viene in genere determinato dal componente host dell'URI della richiesta, che il browser invia all'applicazione come Host intestazione HTTP.

Importante

Non usare mai il valore dell'host in un meccanismo di sicurezza. Il valore viene fornito dal browser o da un altro agente utente e può essere facilmente modificato da un utente finale.

In alcuni scenari, in particolare quando è presente un proxy inverso HTTP nella catena di richieste, l'intestazione host originale può essere modificata prima che raggiunga il server applicazioni. Un proxy inverso chiude la sessione di rete client e configura una nuova connessione al back-end. In questa nuova sessione può eseguire il trasporto del nome host originale della sessione client o impostarne uno nuovo. In quest'ultimo caso, il proxy spesso invia ancora il valore host originale in altre intestazioni HTTP, ad esempio Forwarded o X-Forwarded-Host. Questo valore consente alle applicazioni di determinare il nome host originale, ma solo se sono codificati per leggere queste intestazioni.

Perché le piattaforme Web usano il nome host

I servizi PaaS multi-tenant richiedono spesso un nome host registrato e convalidato per instradare una richiesta in ingresso al server back-end del tenant appropriato. Ciò è dovuto al fatto che in genere è presente un pool condiviso di servizi di bilanciamento del carico che accettano richieste in ingresso per tutti i tenant. I tenant usano in genere il nome host in ingresso per cercare il back-end corretto per il tenant del cliente.

Per iniziare, queste piattaforme in genere forniscono un dominio predefinito preconfigurato per instradare il traffico all'istanza distribuita. Per servizio app, questo dominio predefinito è azurewebsites.net. Ogni app Web creata ottiene il proprio sottodominio, contoso.azurewebsites.netad esempio . Analogamente, il dominio predefinito è azuremicroservices.io per Spring Apps e azure-api.net per Gestione API.

Per le distribuzioni di produzione, non si usano questi domini predefiniti. Si fornisce invece il proprio dominio per allinearsi al marchio dell'organizzazione o dell'applicazione. Ad esempio, contoso.com potrebbe essere risolto in background nell'app contoso.azurewebsites.net Web in servizio app, ma questo dominio non dovrebbe essere visibile a un utente finale che visita il sito Web. Questo nome host personalizzato contoso.com deve essere registrato con il servizio PaaS, pertanto la piattaforma può identificare il server back-end che deve rispondere alla richiesta.

Diagram that illustrates host-based routing in App Service.

Perché le applicazioni usano il nome host

Due motivi comuni per cui un server applicazioni richiede il nome host sono la creazione di URL assoluti e l'emissione di cookie per un dominio specifico. Ad esempio, quando il codice dell'applicazione deve:

  • Restituisce un URL assoluto anziché un URL relativo nella risposta HTTP (anche se in genere i siti Web tendono a eseguire il rendering di collegamenti relativi quando possibile).
  • Generare un URL da usare all'esterno della risposta HTTP in cui non è possibile usare URL relativi, ad esempio per inviare un collegamento al sito Web a un utente.
  • Generare un URL di reindirizzamento assoluto per un servizio esterno. Ad esempio, a un servizio di autenticazione come Microsoft Entra ID per indicare dove deve restituire l'utente dopo l'autenticazione completata.
  • Rilasciare cookie HTTP limitati a un determinato host, come definito nell'attributo del Domain cookie.

È possibile soddisfare tutti questi requisiti aggiungendo il nome host previsto alla configurazione dell'applicazione e usando tale valore definito in modo statico anziché il nome host in ingresso nella richiesta. Tuttavia, questo approccio complica lo sviluppo e la distribuzione di applicazioni. Inoltre, una singola installazione dell'applicazione può gestire più host. Ad esempio, una singola app Web può essere usata per più tenant dell'applicazione con nomi host univoci , ad tenant1.contoso.com esempio e tenant2.contoso.com.

E talvolta il nome host in ingresso viene usato dai componenti al di fuori del codice dell'applicazione o nel middleware nel server applicazioni su cui non si ha il controllo completo. Di seguito vengono forniti alcuni esempi:

  • In servizio app è possibile applicare HTTPS per l'app Web. In questo modo, tutte le richieste HTTP che non sono sicure per il reindirizzamento a HTTPS. In questo caso, il nome host in ingresso viene usato per generare l'URL assoluto per l'intestazione del Location reindirizzamento HTTP.
  • Spring Apps usa una funzionalità simile per applicare HTTPS. Usa anche l'host in ingresso per generare l'URL HTTPS.
  • servizio app ha un Impostazione di affinità ARR per abilitare sessioni permanenti, in modo che le richieste provenienti dalla stessa istanza del browser vengano sempre gestite dallo stesso server back-end. Questa operazione viene eseguita dai front-end servizio app, che aggiungono un cookie alla risposta HTTP. Il cookie è impostato sull'host Domain in ingresso.
  • servizio app offre funzionalità di autenticazione e autorizzazione per consentire agli utenti di accedere e accedere facilmente ai dati nelle API.

Perché si potrebbe essere tentati di eseguire l'override del nome host

Si supponga di creare un'applicazione Web in servizio app con un dominio predefinito di contoso.azurewebsites.net. Oppure in un altro servizio, ad esempio Spring Apps. Non è stato configurato un dominio personalizzato in servizio app. Per inserire un proxy inverso come gateway applicazione (o qualsiasi servizio simile) davanti a questa applicazione, impostare il record DNS per per contoso.com risolvere l'indirizzo IP di gateway applicazione. Riceve quindi la richiesta per contoso.com dal browser ed è configurata per inoltrare tale richiesta all'indirizzo IP che contoso.azurewebsites.net si risolve in: si tratta del servizio back-end finale per l'host richiesto. In questo caso, tuttavia, servizio app non riconosce il contoso.com dominio personalizzato e rifiuta tutte le richieste in ingresso per questo nome host. Non è in grado di determinare dove indirizzare la richiesta.

Potrebbe sembrare che il modo più semplice per eseguire questa configurazione sia eseguire l'override o riscrivere l'intestazione Host della richiesta HTTP in gateway applicazione e impostarla sul valore di contoso.azurewebsites.net. In caso affermativo, la richiesta in uscita da gateway applicazione sembra che la richiesta originale sia stata effettivamente destinata invece contoso.azurewebsites.net di contoso.com:

Diagram that illustrates a configuration with the host name overridden.

A questo punto, servizio app riconosce il nome host e accetta la richiesta senza che sia necessario configurare un nome di dominio personalizzato. In effetti, gateway applicazione semplifica l'override dell'intestazione host con l'host del pool back-end. Frontdoor di Azure esegue anche questa operazione per impostazione predefinita.

Il problema con questa soluzione, tuttavia, è che può causare vari problemi quando l'app non visualizza il nome host originale.

Potenziali problemi

URL assoluti non corretti

Se il nome host originale non viene mantenuto e il server applicazioni usa il nome host in ingresso per generare URL assoluti, il dominio back-end potrebbe essere divulgato a un utente finale. Questi URL assoluti possono essere generati dal codice dell'applicazione o, come indicato in precedenza, da funzionalità della piattaforma come il supporto per il reindirizzamento da HTTP a HTTPS in servizio app e Spring Apps. Questo diagramma illustra il problema:

Diagram that illustrates the problem of incorrect absolute URLs.

  1. Il browser invia una richiesta per contoso.com al proxy inverso.
  2. Il proxy inverso riscrive il nome host in contoso.azurewebsites.net nella richiesta all'applicazione Web back-end (o a un dominio predefinito simile per un altro servizio).
  3. L'applicazione genera un URL assoluto basato sul nome host in ingresso contoso.azurewebsites.net , https://contoso.azurewebsites.net/ad esempio .
  4. Il browser segue questo URL, che passa direttamente al servizio back-end anziché al proxy inverso in contoso.com.

Ciò potrebbe anche rappresentare un rischio per la sicurezza nel caso comune in cui il proxy inverso funge anche da web application firewall. L'utente riceve un URL che passa direttamente all'applicazione back-end e ignora il proxy inverso.

Importante

A causa di questo rischio di sicurezza, è necessario assicurarsi che l'applicazione Web back-end accetti direttamente il traffico di rete dal proxy inverso, ad esempio usando restrizioni di accesso in servizio app. In tal caso, anche se viene generato un URL assoluto non corretto, almeno non funziona e non può essere usato da un utente malintenzionato per ignorare il firewall.

URL di reindirizzamento non corretti

Un caso comune e più specifico dello scenario precedente si verifica quando vengono generati URL di reindirizzamento assoluti. Questi URL sono richiesti da servizi di identità come Microsoft Entra ID quando si usano protocolli di identità basati su browser come OpenID Connessione, OAuth 2.0 o SAML 2.0. Questi URL di reindirizzamento possono essere generati dal server applicazioni o dal middleware stesso oppure, come indicato in precedenza, da funzionalità della piattaforma come le funzionalità di autenticazione e autorizzazione servizio app. Questo diagramma illustra il problema:

Diagram that illustrates the problem of incorrect redirect URLs.

  1. Il browser invia una richiesta per contoso.com al proxy inverso.
  2. Il proxy inverso riscrive il nome host su contoso.azurewebsites.net nella richiesta all'applicazione Web back-end (o a un dominio predefinito simile per un altro servizio).
  3. L'applicazione genera un URL di reindirizzamento assoluto basato sul nome host in ingresso contoso.azurewebsites.net , https://contoso.azurewebsites.net/ad esempio .
  4. Il browser passa al provider di identità per autenticare l'utente. La richiesta include l'URL di reindirizzamento generato per indicare dove restituire l'utente dopo l'autenticazione riuscita.
  5. I provider di identità richiedono in genere la registrazione iniziale degli URL di reindirizzamento, quindi a questo punto il provider di identità deve rifiutare la richiesta perché l'URL di reindirizzamento specificato non è registrato. (Non doveva essere usato). Se per qualche motivo l'URL di reindirizzamento viene registrato, tuttavia, il provider di identità reindirizza il browser all'URL di reindirizzamento specificato nella richiesta di autenticazione. In questo caso, l'URL è https://contoso.azurewebsites.net/.
  6. Il browser segue questo URL, che passa direttamente al servizio back-end anziché al proxy inverso.

Biscotti interrotti

Una mancata corrispondenza del nome host può anche causare problemi quando il server applicazioni emette cookie e usa il nome host in ingresso per costruire l'attributo Domain del cookie. L'attributo Domain garantisce che il cookie venga usato solo per quel dominio specifico. Questi cookie possono essere generati dal codice dell'applicazione o, come indicato in precedenza, dalle funzionalità della piattaforma come l'impostazione di affinità ARR servizio app. Questo diagramma illustra il problema:

Diagram that illustrates an incorrect cookie domain.

  1. Il browser invia una richiesta per contoso.com al proxy inverso.
  2. Il proxy inverso riscrive il nome host da inserire contoso.azurewebsites.net nella richiesta all'applicazione Web back-end (o a un dominio predefinito simile per un altro servizio).
  3. L'applicazione genera un cookie che usa un dominio basato sul nome host in ingresso contoso.azurewebsites.net . Il browser archivia il cookie per questo dominio specifico anziché il contoso.com dominio in uso dell'utente.
  4. Il browser non include il cookie in alcuna richiesta successiva perché contoso.com il dominio del contoso.azurewebsites.net cookie non corrisponde al dominio della richiesta. L'applicazione non riceve il cookie rilasciato in precedenza. Di conseguenza, l'utente potrebbe perdere lo stato che dovrebbe trovarsi nel cookie o funzionalità come l'affinità ARR non funziona. Sfortunatamente, nessuno di questi problemi genera un errore o è direttamente visibile all'utente finale. Questo li rende difficili da risolvere.

Indicazioni sull'implementazione per i servizi comuni di Azure

Per evitare i potenziali problemi descritti qui, è consigliabile mantenere il nome host originale nella chiamata tra il proxy inverso e il server applicazioni back-end:

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

Configurazione back-end

Molte piattaforme di hosting Web richiedono di configurare in modo esplicito i nomi host in ingresso consentiti. Le sezioni seguenti descrivono come implementare questa configurazione per i servizi di Azure più comuni. Altre piattaforme in genere forniscono metodi simili per la configurazione di domini personalizzati.

Se si ospita l'applicazione Web in servizio app, è possibile collegare un nome di dominio personalizzato all'app Web ed evitare di usare il nome host predefinito azurewebsites.net verso il back-end. Non è necessario modificare la risoluzione DNS quando si collega un dominio personalizzato all'app Web: è possibile verificare il dominio usando un TXT record senza influire sui normali CNAME record o A . Questi record verranno comunque risolti nell'indirizzo IP del proxy inverso. Se è necessario TLS/SSL end-to-end, è possibile importare un certificato esistente da Key Vault o usare un certificato servizio app per il dominio personalizzato. (Si noti che la versione gratuita servizio app certificato gestito non può essere usato in questo caso, perché richiede che il record DNS del dominio venga risolto direttamente in servizio app, non il proxy inverso.

Analogamente, se si usa Spring Apps, è possibile usare un dominio personalizzato per l'app per evitare di usare il azuremicroservices.io nome host. È possibile importare un certificato esistente o autofirmato se è necessario TLS/SSL end-to-end.

Se si dispone di un proxy inverso davanti a Gestione API (che funge anche da proxy inverso), è possibile configurare un dominio personalizzato nell'istanza di Gestione API per evitare di usare il azure-api.net nome host. È possibile importare un certificato gestito esistente o gratuito se è necessario TLS/SSL end-to-end. Come indicato in precedenza, tuttavia, le API sono meno sensibili ai problemi causati dalla mancata corrispondenza del nome host, quindi questa configurazione potrebbe non essere importante.

Se si ospitano le applicazioni in altre piattaforme, ad esempio in Kubernetes o direttamente nelle macchine virtuali, non è disponibile alcuna funzionalità predefinita che dipende dal nome host in ingresso. Si è responsabili del modo in cui il nome host viene usato nel server applicazioni stesso. È consigliabile mantenere il nome host in genere ancora valido per tutti i componenti dell'applicazione che dipendono da esso, a meno che l'applicazione non sia specificamente consapevole dei proxy inversi e rispetti le forwarded intestazioni o X-Forwarded-Host , ad esempio.

Configurazione del proxy inverso

Quando si definiscono i back-end all'interno del proxy inverso, è comunque possibile usare il dominio predefinito del servizio back-end, https://contoso.azurewebsites.net/ad esempio . Questo URL viene usato dal proxy inverso per risolvere l'indirizzo IP corretto per il servizio back-end. Se si usa il dominio predefinito della piattaforma, l'indirizzo IP è sempre corretto. In genere non è possibile usare il dominio pubblico, ad esempio contoso.com, perché deve essere risolto nell'indirizzo IP del proxy inverso stesso. (A meno che non si usino tecniche di risoluzione DNS più avanzate, ad esempio DNS split-horizon).

Importante

Se si dispone di un firewall di nuova generazione come Firewall di Azure Premium tra il proxy inverso e il back-end finale, potrebbe essere necessario usare DNS split-horizon. Questo tipo di firewall potrebbe controllare in modo esplicito se l'intestazione HTTP Host viene risolta nell'indirizzo IP di destinazione. In questi casi, il nome host originale usato dal browser deve essere risolto nell'indirizzo IP del proxy inverso quando si accede dalla rete Internet pubblica. Dal punto di vista del firewall, tuttavia, tale nome host deve essere risolto nell'indirizzo IP del servizio back-end finale. Per altre informazioni, vedere Rete zero-trust per le applicazioni Web con Firewall di Azure e gateway applicazione.

La maggior parte dei proxy inversi consente di configurare il nome host passato al servizio back-end. Le informazioni seguenti illustrano come assicurarsi che, per i servizi di Azure più comuni, venga usato il nome host originale della richiesta in ingresso.

Nota

In tutti i casi, è anche possibile scegliere di eseguire l'override del nome host con un dominio personalizzato definito in modo esplicito anziché eseguirne l'acquisizione dalla richiesta in ingresso. Se l'applicazione usa solo un singolo dominio, questo approccio potrebbe funzionare correttamente. Se la stessa distribuzione dell'applicazione accetta richieste da più domini (ad esempio, in scenari multi-tenant), non è possibile definire in modo statico un singolo dominio. È consigliabile prendere in considerazione il nome host dalla richiesta in ingresso (anche in questo caso, a meno che l'applicazione non sia codificata in modo esplicito per prendere in considerazione intestazioni HTTP aggiuntive). Pertanto, la raccomandazione generale è che non è consigliabile eseguire l'override del nome host. Passare il nome host in ingresso non modificato al back-end.

Gateway applicazione

Se si usa gateway applicazione come proxy inverso, è possibile assicurarsi che il nome host originale venga mantenuto disabilitando Override con nuovo nome host nell'impostazione HTTP back-end. In questo modo vengono disabilitati sia Pick host name from back-end address (Seleziona nome host dall'indirizzo back-end) sia Override con un nome di dominio specifico. Entrambe queste impostazioni sostituiscono il nome host. Nelle proprietà di Azure Resource Manager per gateway applicazione questa configurazione corrisponde all'impostazione della hostName proprietà su null e pickHostNameFromBackendAddress su false.

Poiché i probe di integrità vengono inviati all'esterno del contesto di una richiesta in ingresso, non possono determinare dinamicamente il nome host corretto. È invece necessario creare un probe di integrità personalizzato, disabilitare Seleziona nome host dalle impostazioni HTTP back-end e specificare in modo esplicito il nome host. Per questo nome host, è consigliabile usare anche un dominio personalizzato appropriato per la coerenza. È tuttavia possibile usare il dominio predefinito della piattaforma di hosting, perché i probe di integrità ignorano i cookie non corretti o gli URL di reindirizzamento nella risposta.

Frontdoor di Azure

Se si usa Frontdoor di Azure, è possibile evitare di eseguire l'override del nome host lasciando vuota l'intestazione host back-end nella definizione del pool back-end. Nella definizione di Resource Manager del pool back-end questa configurazione corrisponde all'impostazione backendHostHeader su null.

Se si usa Frontdoor di Azure Standard o Premium, è possibile mantenere il nome host lasciando vuota l'intestazione host di origine nella definizione di origine. Nella definizione di Resource Manager dell'origine questa configurazione corrisponde all'impostazione originHostHeader su null.

Gestione API

Per impostazione predefinita, Gestione API sostituisce il nome host inviato al back-end con il componente host dell'URL del servizio Web dell'API (che corrisponde al serviceUrl valore della definizione di Resource Manager dell'API).

È possibile forzare Gestione API a usare invece il nome host della richiesta in ingresso aggiungendo un inboundcriterio Imposta intestazione HTTP, come indicato di seguito:

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

Come indicato in precedenza, tuttavia, le API sono meno sensibili ai problemi causati dalla mancata corrispondenza del nome host, quindi questa configurazione potrebbe non essere importante.

Passaggi successivi