Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Di Chris Ross
Nella configurazione consigliata per ASP.NET Core, l'app viene ospitata usando ASP.NET Core Module (ANCM) per IIS, Nginx o Apache. Server proxy, servizi di bilanciamento del carico e altre appliance di rete spesso nascondono informazioni sulla richiesta prima che questa raggiunga l'app:
- Quando le richieste HTTPS vengono trasmesse tramite proxy su HTTP, lo schema originale (HTTPS) viene perso e deve essere inoltrato in un'intestazione.
- Poiché un'app riceve una richiesta dal proxy e non dall'effettiva origine su Internet o nella rete aziendale, anche l'indirizzo IP di origine del client deve essere inoltrato in un'intestazione.
Queste informazioni potrebbero essere importanti per l'elaborazione delle richieste, ad esempio per i reindirizzamenti, l'autenticazione, la generazione di collegamenti, la valutazione dei criteri e la georilevazione dei client.
Le app che devono essere eseguite nella Web farm devono leggere Host ASP.NET Core in una web farm.
Intestazioni inoltrate
Per convenzione, i proxy inoltrano le informazioni nelle intestazioni HTTP.
| Intestazione | Descrizione |
|---|---|
X-Forwarded-For (XFF) |
Contiene informazioni sul client che ha avviato la richiesta e sui proxy successivi in una catena di proxy. Questo parametro può contenere indirizzi IP e, facoltativamente, numeri di porta. In una catena di server proxy, il primo parametro indica il client in cui è stata eseguita inizialmente la richiesta. Seguono gli identificatori dei proxy successivi. L'ultimo proxy della catena non è incluso nell'elenco dei parametri. L'indirizzo IP dell'ultimo proxy e, facoltativamente, un numero di porta sono disponibili come indirizzo IP remoto a livello di trasporto. |
X-Forwarded-Proto (XFP) |
Valore dello schema di origine, HTTP o HTTPS. Il valore può essere anche un elenco di schemi, se la richiesta ha attraversato più proxy. |
X-Forwarded-Host (XFH) |
Il valore originale del campo dell'intestazione Host. I proxy in genere non modificano l'intestazione host. Vedere l'avviso di sicurezza Microsoft CVE-2018-0787 per informazioni su una vulnerabilità di elevazione dei privilegi che interessa i sistemi in cui il proxy non convalida o limita le intestazioni host a valori di riferimento noti. |
X-Forwarded-Prefix |
Percorso di base originale richiesto dal client. Questa intestazione può essere utile per le applicazioni per generare correttamente URL, reindirizzamenti o collegamenti di ritorno al cliente. |
Forwarded Headers Middleware, ForwardedHeadersMiddleware, legge queste intestazioni e compila i campi associati in HttpContext.
Il middleware aggiorna:
-
HttpContext.Connection.RemoteIpAddress: Impostato usando il valore dell'intestazioneX-Forwarded-For. Impostazioni aggiuntive influiscono sul modo in cui il middleware impostaRemoteIpAddress. Per informazioni dettagliate, consultare le opzioni del Middleware Intestazioni Inoltrate. I valori utilizzati vengono rimossi daX-Forwarded-Fore il valore precedente diHttpContext.Connection.RemoteIpAddressviene salvato in modo permanente inX-Original-For. Nota: questo processo può essere ripetuto più volte se sono presenti più valori inX-Forwarded-For/Proto/Host/Prefix, con conseguente spostamento di diversi valori inX-Original-*, incluso l'originaleRemoteIpAddress/Host/Scheme/PathBase. -
HttpContext.Request.Scheme: Valore dell'intestazione impostato utilizzandoX-Forwarded-Proto. Il valore utilizzato viene rimosso daX-Forwarded-Protoe il valore precedente diHttpContext.Request.Schemeviene salvato in modo permanente inX-Original-Proto. -
HttpContext.Request.Host: Impostare usando il valore dell'intestazioneX-Forwarded-Host. Il valore utilizzato viene rimosso daX-Forwarded-Hoste il valore precedente diHttpContext.Request.Hostviene salvato in modo permanente inX-Original-Host. -
HttpContext.Request.PathBase: impostato tramite il valore dell'intestazioneX-Forwarded-Prefix. Il valore utilizzato viene rimosso daX-Forwarded-Prefixe il valore precedente diHttpContext.Request.PathBaseviene salvato in modo permanente inX-Original-Prefix.
Per altre informazioni sull'esempio precedente, vedere questo problema di GitHub.
È possibile configurare le impostazioni predefinite del middleware delle intestazioni inoltrate. Per le impostazioni predefinite:
- È presente un solo proxy tra l'app e l'origine delle richieste.
- Sono configurati indirizzi di loopback solo per reti e proxy noti.
- Le intestazioni inoltrate sono denominate
X-Forwarded-For,X-Forwarded-Proto,X-Forwarded-HosteX-Forwarded-Prefix. - Il
ForwardedHeadersvalore èForwardedHeaders.None, i server d'inoltro desiderati devono essere impostati qui per abilitare il middleware.
Non tutte le appliance di rete aggiungono le intestazioni X-Forwarded-For e X-Forwarded-Proto senza alcuna configurazione aggiuntiva. Se le richieste trasmesse tramite proxy non contengono queste intestazioni quando raggiungono l'app, consultare le linee guida del produttore del dispositivo. Se l'appliance usa nomi di intestazione diversi da X-Forwarded-For e X-Forwarded-Proto, impostare le opzioni ForwardedForHeaderName e ForwardedProtoHeaderName in modo che corrispondano ai nomi di intestazione usati dall'appliance. Per altre informazioni, vedere Opzioni del middleware delle intestazioni inoltrate e Configurazione per un proxy che usa nomi di intestazione diversi.
IIS/IIS Express e ASP.NET Core Module
Il Middleware delle intestazioni inoltrate è abilitato per impostazione predefinita dal middleware di integrazione IIS quando l'app è ospitata in modalità out-of-process dietro IIS e il Modulo ASP.NET Core (ANCM) per IIS. Il middleware delle intestazioni inoltrate viene attivato per funzionare prima nella pipeline del middleware con una configurazione specifica e limitata del modulo ASP.NET Core. La configurazione con restrizioni è dovuta a preoccupazioni di attendibilità con le intestazioni inoltrate, ad esempio lo spoofing IP. Il middleware è configurato per inoltrare le intestazioni X-Forwarded-For e X-Forwarded-Proto ed è limitato a un singolo proxy localhost. Se è richiesta una configurazione aggiuntiva, vedere Opzioni del middleware per le intestazioni inoltrate.
Altri scenari con server proxy e servizi di bilanciamento del carico
Al di fuori dell'uso dell'integrazione IIS quando si ospita out-of-process, il Middleware delle intestazioni inoltrate non è abilitato per impostazione predefinita. Il middleware delle intestazioni inoltrate deve essere abilitato per consentire a un'app di elaborare le intestazioni inoltrate con UseForwardedHeaders. Dopo aver abilitato il middleware, se non sono specificate opzioni ForwardedHeadersOptions per il middleware, le intestazioni ForwardedHeadersOptions.ForwardedHeaders predefinite sono ForwardedHeaders.None.
Configurare il middleware con ForwardedHeadersOptions per inoltrare le intestazioni X-Forwarded-For e X-Forwarded-Proto.
Ordine delle intestazioni inoltrate nel middleware
Il middleware delle intestazioni inoltrate deve essere eseguito prima di altri middleware. Questo ordine garantisce che il middleware che si basa su intestazioni inoltrate possa usare i valori delle intestazioni per l'elaborazione. Il middleware delle intestazioni inoltrate può essere eseguito dopo la diagnostica ed la gestione degli errori, ma deve essere eseguito prima di chiamare UseHsts:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
In alternativa, chiamare UseForwardedHeaders prima della diagnostica:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Nota
Se non ForwardedHeadersOptions viene specificato o applicato direttamente al metodo di estensione con UseForwardedHeaders, le intestazioni predefinite da inoltrare sono ForwardedHeaders.None. La proprietà ForwardedHeaders deve essere configurata con le intestazioni da inoltrare.
Configurazione Nginx
Per inoltrare le X-Forwarded-For intestazioni e X-Forwarded-Proto, consultare Host ASP.NET Core su Linux con Nginx. Per altre informazioni, vedere NGINX: Using the Forwarded header (NGINX: Uso dell'intestazione Forwarded).
Configurazione Apache
X-Forwarded-For viene aggiunto automaticamente. Per altre informazioni, vedere Apache Module mod_proxy: Reverse Proxy Request Headers .For more information, see Apache Module mod_proxy: Reverse Proxy Request Headers.
Opzioni del middleware per le intestazioni inoltrate
ForwardedHeadersOptions controllare il comportamento del Middleware delle Intestazioni Inoltrate. L'esempio seguente modifica i valori predefiniti:
- Limita il numero di voci nelle intestazioni inoltrate a
2. - Aggiunge un indirizzo proxy noto di
127.0.10.1. - Modifica il nome dell'intestazione inoltrata dal valore predefinito
X-Forwarded-ForaX-Forwarded-For-My-Custom-Header-Name.
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
| Opzione | Descrizione |
|---|---|
| AllowedHosts | Limita gli host mediante l'intestazione X-Forwarded-Host ai valori specificati.
IList<string> vuoto. |
| ForwardedForHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedForHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-For ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-For. |
| ForwardedHeaders | Identifica i server d'inoltro che devono essere processati. Consultare ForwardedHeaders Enum per l'elenco dei campi applicabili. I valori tipici assegnati a questa proprietà sono ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.Il valore predefinito è ForwardedHeaders.None. |
| ForwardedHostHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedHostHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-Host ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-Host. |
| ForwardedProtoHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedProtoHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-Proto ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-Proto. |
| ForwardLimit | Limita il numero di voci nelle intestazioni che vengono elaborate. Impostare su null per disabilitare il limite, ma solo se è configurato KnownProxies o KnownNetworks. L'impostazione di un valore nonnull è una precauzione (ma non una garanzia) per la protezione da proxy non configurati in modo errato e richieste dannose provenienti da canali laterali nella rete.Il middleware delle intestazioni inoltrate elabora le intestazioni in ordine inverso partendo da destra verso sinistra. Se viene usato il valore predefinito ( 1), viene elaborato solo il valore più a destra delle intestazioni, a meno che non venga aumentato il valore di ForwardLimit.Il valore predefinito è 1. |
| KnownNetworks | Intervalli di indirizzi delle reti note da cui accettare le intestazioni inoltrate. Specificare gli intervalli IP usando la notazione CIDR (Classless Interdomain Routing). Se il server usa socket dual mode, gli indirizzi IPv4 vengono forniti in un formato IPv6 (ad esempio, 10.0.0.1 in IPv4 rappresentato in IPv6 come ::ffff:10.0.0.1). Vedere IPAddress.MapToIPv6. Determinare se questo formato è richiesto esaminando HttpContext.Connection.RemoteIpAddress.Il valore predefinito è un oggetto IList<IPNetwork> contenente una singola voce per new IPNetwork(IPAddress.Loopback, 8). |
| KnownProxies | Indirizzi dei proxy noti da cui accettare le intestazioni di inoltro. Usare KnownProxies per specificare le corrispondenze esatte degli indirizzi IP.Se il server usa socket dual mode, gli indirizzi IPv4 vengono forniti in un formato IPv6 (ad esempio, 10.0.0.1 in IPv4 rappresentato in IPv6 come ::ffff:10.0.0.1). Vedere IPAddress.MapToIPv6. Determinare se questo formato è richiesto esaminando HttpContext.Connection.RemoteIpAddress.Il valore predefinito è un oggetto IList<IPAddress> contenente una singola voce per IPAddress.IPv6Loopback. |
| OriginalForHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalForHeaderName. Il valore predefinito è X-Original-For. |
| OriginalHostHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalHostHeaderName. Il valore predefinito è X-Original-Host. |
| OriginalProtoHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalProtoHeaderName. Il valore predefinito è X-Original-Proto. |
| RequireHeaderSymmetry | Richiedere che il numero di valori delle intestazioni sia sincronizzato tra i ForwardedHeadersOptions.ForwardedHeaders in fase di elaborazione. Il valore predefinito in ASP.NET Core 1.x è true. Il valore predefinito in ASP.NET Core 2.0 o versione successiva è false. |
Scenari e casi d'uso
Quando non è possibile aggiungere le intestazioni inoltrate e tutte le richieste sono sicure
In alcuni casi, potrebbe non essere possibile aggiungere le intestazioni inoltrate alle richieste trasmesse tramite proxy all'app. Se il proxy applica che tutte le richieste esterne pubbliche sono HTTPS, lo schema può essere impostato manualmente prima di usare qualsiasi tipo di middleware:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Questo codice può essere disabilitato con una variabile di ambiente o un'altra impostazione di configurazione in un ambiente di sviluppo o staging:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsProduction())
{
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
}
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Lavora con la base del percorso e i proxy che alterano il percorso della richiesta
Alcuni proxy passano il percorso senza modifiche, ma con un percorso di base dell'app che deve essere rimosso per consentire il corretto funzionamento del routing. Il middleware UsePathBaseExtensions.UsePathBase suddivide il percorso in HttpRequest.Path e il percorso di base dell'app in HttpRequest.PathBase.
Se /foo è il percorso di base dell'app per un percorso proxy passato come /foo/api/1, il middleware imposta Request.PathBase su /foo e Request.Path su /api/1 con il comando seguente:
app.UsePathBase("/foo");
// ...
app.UseRouting();
Nota
Quando si usa WebApplication (vedere Eseguire la migrazione da ASP.NET Core in .NET 5 a .NET 6), app.UseRouting deve essere chiamato dopo UsePathBase in modo che il middleware di routing possa osservare il percorso modificato prima delle route corrispondenti. In caso contrario, le route vengono confrontate prima che il percorso venga riscritto da UsePathBase come descritto in ASP.NET core middleware e routing in ASP.NET Core.
Il percorso originale e la base del percorso vengono riapplicati quando il middleware viene chiamato nuovamente in direzione inversa. Per ulteriori informazioni sul middleware per l'elaborazione degli ordini, vedere ASP.NET Core Middleware.
Se il proxy taglia il percorso (ad esempio, inoltrando /foo/api/1 a /api/1), correggere i reindirizzamenti e i collegamenti impostando la proprietà PathBase della richiesta:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next(context);
});
Se il proxy aggiunge i dati del percorso, eliminare parte del percorso per correggere i reindirizzamenti e i collegamenti usando StartsWithSegments ed eseguendo l'assegnazione alla proprietà Path:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next(context);
});
Configurazione per un proxy che usa nomi di intestazione diversi
Se il proxy non usa intestazioni denominate X-Forwarded-For e X-Forwarded-Proto per inoltrare l'indirizzo del proxy e la porta e le informazioni sullo schema originale, impostare le opzioni ForwardedForHeaderName e ForwardedProtoHeaderName in modo che corrispondano ai nomi delle intestazioni usati dal proxy.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "HeaderNamUsedByProxy_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "HeaderNamUsedByProxy_X-Forwarded-Proto_Header";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Reindirizzare lo schema per Linux e i proxy inversi diversi da IIS
Con le app che chiamano UseHttpsRedirection e UseHsts il sito si ritrova in un ciclo infinito se distribuito in un servizio app Linux di Azure, in una macchina virtuale Linux di Azure o dietro eventuali altri proxy inversi diversi da IIS. TLS viene terminato dal proxy inverso e Kestrel non è a conoscenza dello schema di richiesta corretto. Si verificano errori anche per OAuth e OIDC in questa configurazione perché generano reindirizzamenti non corretti. UseIISIntegration aggiunge e configura il middleware delle intestazioni inoltrate in caso di esecuzione dietro IIS, ma non esiste alcuna configurazione automatica corrispondente per Linux (integrazione di Apache o Nginx).
Per inoltrare lo schema delle intestazioni dal proxy in scenari non IIS, abilitare il Middleware Intestazioni Inoltrate impostando ASPNETCORE_FORWARDEDHEADERS_ENABLED su true. Avviso: questo flag utilizza impostazioni progettate per gli ambienti cloud e non abilita funzionalità come il KnownProxies option per limitare da quali indirizzi IP vengono accettati i server di inoltro.
Inoltro di certificati
Azzurro
Per configurare Azure App Service per l'inoltro dei certificati, vedere Configurare l'autenticazione reciproca di TLS per Azure App Service. Le indicazioni seguenti riguardano la configurazione dell'app ASP.NET Core.
- Configurare Middleware di inoltro dei certificati per specificare il nome dell'intestazione usato da Azure. Aggiungere il codice seguente per configurare l'intestazione da cui il middleware compila un certificato.
- Chiamare UseCertificateForwarding prima della chiamata a UseAuthentication.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Altri proxy Web
Se viene utilizzato un proxy che non è né IIS né Application Request Routing (ARR) di Azure App Service, configurare il proxy per inoltrare il certificato ricevuto attraverso un'intestazione HTTP.
- Configurare il middleware di inoltro certificati per specificare il nome dell'intestazione. Aggiungere il codice seguente per configurare l'intestazione da cui il middleware compila un certificato.
- Chiamare UseCertificateForwarding prima della chiamata a UseAuthentication.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Se il proxy non esegue la codifica base64 del certificato, come nel caso di Nginx, impostare l'opzione HeaderConverter . Si consideri l'esempio seguente:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
// Conversion logic to create an X509Certificate2.
var clientCertificate = ConversionLogic.CreateAnX509Certificate2();
return clientCertificate;
};
});
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Risoluzione dei problemi
Quando le intestazioni non vengono inoltrate come previsto, abilitare la debug registrazione a livello e la registrazione delle richieste HTTP.
UseHttpLogging deve essere chiamato dopo UseForwardedHeaders:
using Microsoft.AspNetCore.HttpLogging;
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddHttpLogging(options =>
{
options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders;
});
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
// Connection: RemoteIp
app.Logger.LogInformation("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next(context);
});
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Se sono presenti più valori in una determinata intestazione, il middleware delle intestazioni inoltrate elabora le intestazioni in ordine inverso da destra a sinistra. Il valore predefinito di ForwardLimit è 1 (uno) e, pertanto, viene elaborato solo il valore più a destra delle intestazioni, a meno che non venga aumentato il valore di ForwardLimit.
L'indirizzo IP remoto originale della richiesta deve corrispondere a una voce negli elenchi KnownProxies o KnownNetworks prima dell'elaborazione delle intestazioni inoltrate. Questo riduce lo spoofing delle intestazioni non accettando inoltri da proxy non attendibili. Quando viene rilevato un proxy sconosciuto, la registrazione indica l'indirizzo del proxy:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Nell'esempio precedente, 10.0.0.100 è un server proxy. Se il server è un proxy attendibile, aggiungere l'indirizzo IP del server a KnownProxieso aggiungere una rete attendibile a KnownNetworks. Per altre informazioni, consultare la sezione Opzioni del middleware delle intestazioni inoltrate.
using Microsoft.AspNetCore.HttpOverrides;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Per visualizzare i log, aggiungere "Microsoft.AspNetCore.HttpLogging": "Information" al appsettings.Development.json file:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging": "Information"
}
}
}
Importante
Consenti solo a proxy e reti attendibili di inoltrare le intestazioni. In caso contrario, possono verificarsi attacchi di spoofing degli indirizzi IP.
Risorse aggiuntive
Nella configurazione consigliata per ASP.NET Core, l'app è ospitata mediante IIS e il modulo ASP.NET Core, Nginx o Apache. Server proxy, servizi di bilanciamento del carico e altre appliance di rete spesso nascondono informazioni sulla richiesta prima che questa raggiunga l'app:
- Quando le richieste HTTPS vengono trasmesse tramite proxy su HTTP, lo schema originale (HTTPS) viene perso e deve essere inoltrato in un'intestazione.
- Poiché un'app riceve una richiesta dal proxy e non dall'effettiva origine su Internet o nella rete aziendale, anche l'indirizzo IP di origine del client deve essere inoltrato in un'intestazione.
Queste informazioni potrebbero essere importanti per l'elaborazione delle richieste, ad esempio per i reindirizzamenti, l'autenticazione, la generazione di collegamenti, la valutazione dei criteri e la georilevazione dei client.
Intestazioni inoltrate
Per convenzione, i proxy inoltrano le informazioni nelle intestazioni HTTP.
| Intestazione | Descrizione |
|---|---|
| X-Forwarded-For | Contiene informazioni sul client che ha avviato la richiesta e sui proxy successivi in una catena di proxy. Questo parametro può contenere indirizzi IP (e, facoltativamente, numeri di porta). In una catena di server proxy, il primo parametro indica il client in cui è stata eseguita inizialmente la richiesta. Seguono gli identificatori dei proxy successivi. L'ultimo proxy della catena non è incluso nell'elenco dei parametri. L'indirizzo IP dell'ultimo proxy e, facoltativamente, un numero di porta sono disponibili come indirizzo IP remoto a livello di trasporto. |
| X-Forwarded-Proto | Il valore dello schema di origine (HTTP/HTTPS). Il valore può essere anche un elenco di schemi, se la richiesta ha attraversato più proxy. |
| X-Forwarded-Host | Il valore originale del campo dell'intestazione Host. I proxy in genere non modificano l'intestazione host. Vedere l'avviso di sicurezza Microsoft CVE-2018-0787 per informazioni su una vulnerabilità di elevazione dei privilegi che interessa i sistemi in cui il proxy non convalida o limita le intestazioni host a valori di riferimento noti. |
Il middleware delle intestazioni inoltrate (ForwardedHeadersMiddleware), legge queste intestazioni e compila i campi associati in HttpContext.
Il middleware aggiorna:
-
HttpContext.Connection.RemoteIpAddress: impostare usando il valore dell'intestazione
X-Forwarded-For. Impostazioni aggiuntive influiscono sul modo in cui il middleware impostaRemoteIpAddress. Per informazioni dettagliate, consultare le opzioni del Middleware Intestazioni Inoltrate. I valori utilizzati vengono rimossi daX-Forwarded-Fore i valori precedenti vengono salvati in modo permanente inX-Original-For. Lo stesso schema viene applicato alle altre intestazioniHosteProto. -
HttpContext.Request.Scheme: impostato usando il valore dell'intestazione
X-Forwarded-Proto. -
HttpContext.Request.Host: viene impostato usando il valore dell'intestazione
X-Forwarded-Host.
Per altre informazioni sull'esempio precedente, vedere questo problema di GitHub.
È possibile configurare le impostazioni predefinite del middleware delle intestazioni inoltrate. Per le impostazioni predefinite:
- È presente un solo proxy tra l'app e l'origine delle richieste.
- Sono configurati indirizzi di loopback solo per reti e proxy noti.
- Le intestazioni inoltrate sono denominate
X-Forwarded-ForeX-Forwarded-Proto. - Il
ForwardedHeadersvalore èForwardedHeaders.None, i server d'inoltro desiderati devono essere impostati qui per abilitare il middleware.
Non tutte le appliance di rete aggiungono le intestazioni X-Forwarded-For e X-Forwarded-Proto senza alcuna configurazione aggiuntiva. Se le richieste trasmesse tramite proxy non contengono queste intestazioni quando raggiungono l'app, consultare le linee guida del produttore del dispositivo. Se l'appliance usa nomi di intestazione diversi da X-Forwarded-For e X-Forwarded-Proto, impostare le opzioni ForwardedForHeaderName e ForwardedProtoHeaderName in modo che corrispondano ai nomi di intestazione usati dall'appliance. Per altre informazioni, vedere Opzioni del middleware delle intestazioni inoltrate e Configurazione per un proxy che usa nomi di intestazione diversi.
IIS/IIS Express e ASP.NET Core Module
Il middleware delle intestazioni inoltrate è abilitato per impostazione predefinita dal middleware di integrazione IIS quando l'app è ospitata out-of-process dietro IIS e il modulo ASP.NET Core. Il middleware delle intestazioni inoltrate viene attivato per essere eseguito per primo nella pipeline del middleware con una configurazione limitata specifica per il modulo ASP.NET Core a causa di problemi di fiducia con le intestazioni inoltrate, ad esempio il spoofing IP. Il middleware è configurato per inoltrare le intestazioni X-Forwarded-For e X-Forwarded-Proto ed è limitato a un singolo proxy localhost. Se è richiesta una configurazione aggiuntiva, vedere Opzioni del middleware per le intestazioni inoltrate.
Altri scenari con server proxy e servizi di bilanciamento del carico
Al di fuori dell'uso del middleware di integrazione IIS per l'hosting out-of-process, il middleware delle intestazioni inoltrate non è abilitato per impostazione predefinita. Il middleware delle intestazioni inoltrate deve essere abilitato per consentire a un'app di elaborare le intestazioni inoltrate con UseForwardedHeaders. Dopo aver abilitato il middleware, se non sono specificate opzioni ForwardedHeadersOptions per il middleware, le intestazioni ForwardedHeadersOptions.ForwardedHeaders predefinite sono ForwardedHeaders.None.
Configurare il middleware con ForwardedHeadersOptions per inoltrare le intestazioni X-Forwarded-For e X-Forwarded-Proto in Startup.ConfigureServices.
Ordine delle intestazioni inoltrate nel middleware
Il middleware delle intestazioni inoltrate deve essere eseguito prima degli altri middleware. Questo ordine garantisce che il middleware che si basa su intestazioni inoltrate possa usare i valori delle intestazioni per l'elaborazione. Il middleware delle intestazioni inoltrate può essere eseguito dopo la diagnostica ed la gestione degli errori, ma deve essere eseguito prima di chiamare UseHsts:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
In alternativa, chiamare UseForwardedHeaders prima della diagnostica:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Nota
Se non vengono specificate ForwardedHeadersOptions in Startup.ConfigureServices o direttamente nel metodo di estensione con UseForwardedHeaders, le intestazioni predefinite da inoltrare sono ForwardedHeaders.None. La proprietà ForwardedHeaders deve essere configurata con le intestazioni da inoltrare.
Configurazione Nginx
Per inoltrare le X-Forwarded-For intestazioni e X-Forwarded-Proto, consultare Host ASP.NET Core su Linux con Nginx. Per altre informazioni, vedere NGINX: Using the Forwarded header (NGINX: Uso dell'intestazione Forwarded).
Configurazione Apache
X-Forwarded-For viene aggiunta automaticamente. Vedere Apache Module mod_proxy: Reverse Proxy Request Headers (Modulo Apache mod_proxy: Intestazioni delle richieste del proxy inverso).
Opzioni del middleware per le intestazioni inoltrate
ForwardedHeadersOptions controlla il comportamento del middleware delle intestazioni inoltrate. L'esempio seguente modifica i valori predefiniti:
- Limitare il numero di voci nelle intestazioni inoltrate a
2. - Aggiungere un indirizzo proxy noto di
127.0.10.1. - Modificare il nome dell'intestazione inoltrata dal nome predefinito
X-Forwarded-ForaX-Forwarded-For-My-Custom-Header-Name.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
| Opzione | Descrizione |
|---|---|
| AllowedHosts | Limita gli host mediante l'intestazione X-Forwarded-Host ai valori specificati.
IList<string> vuoto. |
| ForwardedHeaders | Identifica i server d'inoltro che devono essere processati. Consultare ForwardedHeaders Enum per l'elenco dei campi applicabili. I valori tipici assegnati a questa proprietà sono ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.Il valore predefinito è ForwardedHeaders.None. |
| ForwardedForHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedForHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-For ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-For. |
| ForwardedHostHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedHostHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-Host ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-Host. |
| ForwardedProtoHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedProtoHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-Proto ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-Proto. |
| ForwardedPrefixHeaderName | Utilizzare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XForwardedPrefixHeaderName. Questa opzione viene usata quando il proxy o il server d'inoltro non usa l'intestazione X-Forwarded-Prefix ma usa un'altra intestazione per inoltrare le informazioni.Il valore predefinito è X-Forwarded-Prefix. |
| ForwardLimit | Limita il numero di voci nelle intestazioni che vengono elaborate. Impostare su null per disabilitare il limite, ma solo se è configurato KnownProxies o KnownNetworks. L'impostazione di un valore nonnull è una precauzione (ma non una garanzia) per la protezione da proxy non configurati in modo errato e richieste dannose provenienti da canali laterali nella rete.Il middleware delle intestazioni inoltrate elabora le intestazioni in ordine inverso partendo da destra verso sinistra. Se viene usato il valore predefinito ( 1), viene elaborato solo il valore più a destra delle intestazioni, a meno che non venga aumentato il valore di ForwardLimit.Il valore predefinito è 1. |
| KnownNetworks | Intervalli di indirizzi delle reti note da cui accettare le intestazioni inoltrate. Specificare gli intervalli IP usando la notazione CIDR (Classless Interdomain Routing). Se il server usa socket dual mode, gli indirizzi IPv4 vengono forniti in un formato IPv6 (ad esempio, 10.0.0.1 in IPv4 rappresentato in IPv6 come ::ffff:10.0.0.1). Vedere IPAddress.MapToIPv6. Determinare se questo formato è richiesto esaminando HttpContext.Connection.RemoteIpAddress.Il valore predefinito è un oggetto IList<IPNetwork> contenente una singola voce per new IPNetwork(IPAddress.Loopback, 8). |
| KnownProxies | Indirizzi dei proxy noti da cui accettare le intestazioni di inoltro. Usare KnownProxies per specificare le corrispondenze esatte degli indirizzi IP.Se il server usa socket dual mode, gli indirizzi IPv4 vengono forniti in un formato IPv6 (ad esempio, 10.0.0.1 in IPv4 rappresentato in IPv6 come ::ffff:10.0.0.1). Vedere IPAddress.MapToIPv6. Determinare se questo formato è richiesto esaminando HttpContext.Connection.RemoteIpAddress.Il valore predefinito è un oggetto IList<IPAddress> contenente una singola voce per IPAddress.IPv6Loopback. |
| OriginalForHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalForHeaderName. Il valore predefinito è X-Original-For. |
| OriginalHostHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalHostHeaderName. Il valore predefinito è X-Original-Host. |
| OriginalProtoHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalProtoHeaderName. Il valore predefinito è X-Original-Proto. |
| OriginalPrefixHeaderName | Usare l'intestazione specificata da questa proprietà anziché quella specificata da ForwardedHeadersDefaults.XOriginalPrefixHeaderName. Il valore predefinito è X-Original-Prefix. |
| RequireHeaderSymmetry | Richiedere che il numero di valori delle intestazioni sia sincronizzato tra i ForwardedHeadersOptions.ForwardedHeaders in fase di elaborazione. Il valore predefinito in ASP.NET Core 1.x è true. Il valore predefinito in ASP.NET Core 2.0 o versione successiva è false. |
Scenari e casi d'uso
Quando non è possibile aggiungere le intestazioni inoltrate e tutte le richieste sono sicure
In alcuni casi, potrebbe non essere possibile aggiungere le intestazioni inoltrate alle richieste trasmesse tramite proxy all'app. Se il proxy impone che tutte le richieste esterne pubbliche siano HTTPS, lo schema può essere impostato manualmente in Startup.Configure prima di usare qualsiasi tipo di middleware:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
Questo codice può essere disabilitato tramite una variabile di ambiente o un'altra impostazione di configurazione in un ambiente di sviluppo o di gestione temporanea.
Gestire la base del percorso e i proxy che modificano il percorso della richiesta
Alcuni proxy passano il percorso senza modifiche, ma con un percorso di base dell'app che deve essere rimosso per consentire il corretto funzionamento del routing. Il middleware UsePathBaseExtensions.UsePathBase suddivide il percorso in HttpRequest.Path e il percorso di base dell'app in HttpRequest.PathBase.
Se /foo è il percorso di base dell'app per un percorso proxy passato come /foo/api/1, il middleware imposta Request.PathBase su /foo e Request.Path su /api/1 con il comando seguente:
app.UsePathBase("/foo");
Il percorso originale e la base del percorso vengono riapplicati quando il middleware viene chiamato nuovamente in direzione inversa. Per ulteriori informazioni sull'elaborazione degli ordini tramite middleware, vedere ASP.NET Core Middleware.
Se il proxy taglia il percorso (ad esempio, inoltrando /foo/api/1 a /api/1), correggere i reindirizzamenti e i collegamenti impostando la proprietà PathBase della richiesta:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next();
});
Se il proxy aggiunge i dati del percorso, eliminare parte del percorso per correggere i reindirizzamenti e i collegamenti usando StartsWithSegments ed eseguendo l'assegnazione alla proprietà Path:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next();
});
Configurazione per un proxy che usa nomi di intestazione diversi
Se il proxy non usa intestazioni con i nomi X-Forwarded-For e X-Forwarded-Proto per inoltrare l'indirizzo o la porta del proxy e le informazioni dello schema originali, impostare le opzioni ForwardedForHeaderName e ForwardedProtoHeaderName in modo che corrispondano ai nomi di intestazione usati dal proxy:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});
Inoltrare lo schema per Linux e proxy inversi non IIS
Con le app che chiamano UseHttpsRedirection e UseHsts il sito si ritrova in un ciclo infinito se distribuito in un servizio app Linux di Azure, in una macchina virtuale Linux di Azure o dietro eventuali altri proxy inversi diversi da IIS. TLS viene terminato dal proxy inverso e Kestrel non è a conoscenza dello schema di richiesta corretto. Si verificano errori anche per OAuth e OIDC in questa configurazione perché generano reindirizzamenti non corretti. UseIISIntegration aggiunge e configura il middleware per le intestazioni inoltrate quando viene eseguito dietro IIS, ma non esiste una configurazione automatica corrispondente per Linux (integrazione con Apache o Nginx).
Per inoltrare lo schema dal proxy in scenari non IIS, aggiungere e configurare il middleware "Forwarded Headers". In Startup.ConfigureServices usare il codice seguente:
// using Microsoft.AspNetCore.HttpOverrides;
if (string.Equals(
Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"),
"true", StringComparison.OrdinalIgnoreCase))
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
// Only loopback proxies are allowed by default.
// Clear that restriction because forwarders are enabled by explicit
// configuration.
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
}
Inoltro di certificati
Azzurro
Per configurare Azure App Service per l'inoltro dei certificati, vedere Configurare l'autenticazione reciproca di TLS per Azure App Service. Le indicazioni seguenti riguardano la configurazione dell'app ASP.NET Core.
In Startup.Configureaggiungere il codice seguente prima della chiamata a app.UseAuthentication();:
app.UseCertificateForwarding();
Configurare il middleware di inoltro certificati per specificare il nome dell'intestazione usato da Azure. In Startup.ConfigureServicesaggiungere il codice seguente per configurare l'intestazione da cui il middleware compila un certificato:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
Altri proxy Web
Se viene utilizzato un proxy che non è né IIS né Application Request Routing (ARR) di Azure App Service, configurare il proxy per inoltrare il certificato ricevuto attraverso un'intestazione HTTP. In Startup.Configureaggiungere il codice seguente prima della chiamata a app.UseAuthentication();:
app.UseCertificateForwarding();
Configurare il middleware di inoltro certificati per specificare il nome dell'intestazione. In Startup.ConfigureServicesaggiungere il codice seguente per configurare l'intestazione da cui il middleware compila un certificato:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
Se il proxy non esegue la codifica base64 del certificato (come nel caso di Nginx), impostare l'opzione HeaderConverter . Si consideri l'esempio seguente in Startup.ConfigureServices:
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
var clientCertificate =
/* some conversion logic to create an X509Certificate2 */
return clientCertificate;
}
});
Risoluzione dei problemi
Quando le intestazioni non vengono inoltrate come previsto, abilitare la registrazione. Se i log non forniscono informazioni sufficienti per risolvere il problema, enumerare le intestazioni delle richieste ricevute dal server. Usare il middleware inline per scrivere le intestazioni di richiesta in una risposta dell'applicazione o per registrare le intestazioni.
Per scrivere le intestazioni nella risposta dell'app, aggiungere il middleware di terminale inline seguente immediatamente dopo la chiamata a UseForwardedHeaders in Startup.Configure:
app.Run(async (context) =>
{
context.Response.ContentType = "text/plain";
// Request method, scheme, and path
await context.Response.WriteAsync(
$"Request Method: {context.Request.Method}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Scheme: {context.Request.Scheme}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Path: {context.Request.Path}{Environment.NewLine}");
// Headers
await context.Response.WriteAsync($"Request Headers:{Environment.NewLine}");
foreach (var header in context.Request.Headers)
{
await context.Response.WriteAsync($"{header.Key}: " +
$"{header.Value}{Environment.NewLine}");
}
await context.Response.WriteAsync(Environment.NewLine);
// Connection: RemoteIp
await context.Response.WriteAsync(
$"Request RemoteIp: {context.Connection.RemoteIpAddress}");
});
È possibile scrivere nei log invece che nel corpo della risposta. La scrittura nei log permette il normale funzionamento del sito durante il debug.
Per scrivere nei log invece che nel corpo della risposta:
-
ILogger<Startup>Inserire nellaStartupclasse come descritto in Creare messaggi di log. - Posizionare il middleware inline seguente immediatamente dopo la chiamata a UseForwardedHeaders in
Startup.Configure.
app.Use(async (context, next) =>
{
// Request method, scheme, path, and base path
_logger.LogDebug("Request Method: {Method}", context.Request.Method);
_logger.LogDebug("Request Scheme: {Scheme}", context.Request.Scheme);
_logger.LogDebug("Request Path: {Path}", context.Request.Path);
_logger.LogDebug("Request Path Base: {PathBase}", context.Request.PathBase);
// Headers
foreach (var header in context.Request.Headers)
{
_logger.LogDebug("Header: {Key}: {Value}", header.Key, header.Value);
}
// Connection: RemoteIp
_logger.LogDebug("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next();
});
Durante l'elaborazione, i valori di X-Forwarded-{For|Proto|Host|Prefix} vengono spostati in X-Original-{For|Proto|Host|Prefix}. Se sono presenti più valori in una determinata intestazione, il middleware delle intestazioni inoltrate elabora le intestazioni in ordine inverso da destra a sinistra. Il valore predefinito di ForwardLimit è 1 (uno) e, pertanto, viene elaborato solo il valore più a destra delle intestazioni, a meno che non venga aumentato il valore di ForwardLimit.
L'indirizzo IP remoto originale della richiesta deve corrispondere a una voce negli elenchi KnownProxies o KnownNetworks prima dell'elaborazione delle intestazioni inoltrate. Questo riduce lo spoofing delle intestazioni non accettando inoltri da proxy non attendibili. Quando viene rilevato un proxy sconosciuto, la registrazione indica l'indirizzo del proxy:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Nell'esempio precedente, 10.0.0.100 è un server proxy. Se il server è un proxy attendibile, aggiungere l'indirizzo IP del server a KnownProxies (o aggiungere una rete attendibile a KnownNetworks) in Startup.ConfigureServices. Per altre informazioni, consultare la sezione Opzioni del middleware delle intestazioni inoltrate.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
Importante
Consenti solo a proxy e reti attendibili di inoltrare le intestazioni. In caso contrario, possono verificarsi attacchi di spoofing degli indirizzi IP.