Konfigurieren von ASP.NET Core zur Verwendung mit Proxyservern und Lastenausgleich
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der Supportrichtlinie für .NET und .NET Core. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Von Chris Ross
In der für ASP.NET Core empfohlenen Konfiguration wird die App mit dem ASP.NET Core-Modul (ANCM) für IIS, Nginx oder Apache gehostet. Proxyserver, Lastenausgleichsmodule und anderen Netzwerkgeräte verdecken häufig Informationen über die Anforderung, bevor diese die App erreicht:
- Wenn HTTPS-Anforderungen über HTTP-Proxy ausgeführt werden, geht das ursprüngliche Schema (HTTPS) verloren und muss in einem Header weitergeleitet werden.
- Da eine App eine Anforderung über den Proxy empfängt und nicht über ihre echte Quelle im Internet oder Unternehmensnetzwerk, muss die ursprüngliche Client-IP-Adresse ebenfalls in einem Header weitergeleitet werden.
Diese Informationen können im Anforderungsprozess, z.B. in Umleitungen, bei der Authentifizierung, der Linkgenerierung, der Richtlinienauswertung und der Client-Geolocation wichtig sein.
Informationen zu Apps, die in einer Webfarm ausgeführt werden sollen, finden Sie unterHosten von ASP.NET Core in einer Webfarm.
Weitergeleitete Header
Gemäß der Konvention leiten Proxys Informationen in HTTP-Headern weiter.
Header | BESCHREIBUNG |
---|---|
X-Forwarded-For (XFF) |
Enthält Informationen zum Client, der die Anforderung und die nachfolgenden Proxys in einer Kette von Proxys initiiert hat. Dieser Parameter kann IP-Adressen und optional Portnummern enthalten. Der erste Parameter in einer Kette von Proxyservern gibt den Client an, auf dem die Anforderung zuerst gesendet wurde. Darauf folgen weitere Proxybezeichner. Der letzte Proxy in der Kette ist nicht in der Liste der Parameter. Die IP-Adresse des letzten Proxys und optional eine Portnummer stehen als Remote IP-Adresse auf der Transportschicht zur Verfügung. |
X-Forwarded-Proto (XFP) |
Der Wert des ursprünglichen Schemas, HTTP oder HTTPS. Der Wert kann auch eine Liste von Schemas sein, wenn die Anforderung mehrere Proxys durchlaufen hat. |
X-Forwarded-Host (XFH) |
Der ursprüngliche Wert des Felds „Hostheader“. In der Regel ändern Proxys den Hostheader nicht. Informationen zu einem Sicherheitsrisiko, das Rechteerweiterungen ermöglicht und sich auf Systeme auswirkt, in denen der Proxy Hostheader nicht validiert oder auf als unbedenklich bekannte Werte beschränkt, finden Sie in der Microsoft-Sicherheitsempfehlung CVE-2018-0787. |
X-Forwarded-Prefix |
Der ursprüngliche Basispfad, der vom Client angefordert wurde. Dieser Header kann für Anwendungen hilfreich sein, um URLs, Umleitungen oder Links zurück zum Client zu generieren. |
Die Middleware für weitergeleitete Header, ForwardedHeadersMiddleware, liest die Header und füllt die zugehörigen Felder in HttpContext aus.
Die Middleware aktualisiert:
HttpContext.Connection.RemoteIpAddress
: Wird mit dem HeaderwertX-Forwarded-For
festgelegt. Zusätzliche Einstellungen beeinflussen, wie die MiddlewareRemoteIpAddress
festlegt. Einzelheiten finden Sie unter Middleware für weitergeleitete Header: Optionen. Die genutzten Werte werden ausX-Forwarded-For
entfernt, und die alten Werte vonHttpContext.Connection.RemoteIpAddress
werden inX-Original-For
beibehalten. Hinweis: Dieser Vorgang kann mehrmals wiederholt werden, wenn mehrere Werte inX-Forwarded-For/Proto/Host/Prefix
vorhanden sind, was dazu führt, dass mehrere Werte nachX-Original-*
verschoben werden, einschließlich des ursprünglichenRemoteIpAddress/Host/Scheme/PathBase
.HttpContext.Request.Scheme
: Wird mit dem HeaderwertX-Forwarded-Proto
festgelegt. Die genutzten Werte werden ausX-Forwarded-Proto
entfernt, und die alten Werte vonHttpContext.Request.Scheme
werden inX-Original-Proto
beibehalten.HttpContext.Request.Host
: Wird mit dem HeaderwertX-Forwarded-Host
festgelegt. Die genutzten Werte werden ausX-Forwarded-Host
entfernt, und die alten Werte vonHttpContext.Request.Host
werden inX-Original-Host
beibehalten.HttpContext.Request.PathBase
: Wird mit dem HeaderwertX-Forwarded-Prefix
festgelegt. Die genutzten Werte werden ausX-Forwarded-Prefix
entfernt, und die alten Werte vonHttpContext.Request.PathBase
werden inX-Original-Prefix
beibehalten.
Weitere Informationen hierzu finden Sie in diesem GitHub-Issue.
Die Standardeinstellungen der Middleware für weitergeleitete Header können konfiguriert werden. Für die Standardeinstellungen:
- Zwischen App und Quelle der Anforderungen ist nur ein Proxy vorhanden.
- Loopbackadressen sind für bekannte Proxys und bekannte Netzwerke konfiguriert.
- Die weitergeleiteten Kopfzeilen werden
X-Forwarded-For
,X-Forwarded-Proto
,X-Forwarded-Host
undX-Forwarded-Prefix
benannt. - Der Wert
ForwardedHeaders
lautetForwardedHeaders.None
, und die gewünschten Forwarder müssen hier festgelegt werden, um die Middleware zu aktivieren.
Beachten Sie, dass bei manchen Netzwerkgeräten eine zusätzliche Konfiguration erforderlich ist, damit die Header X-Forwarded-For
und X-Forwarded-Proto
hinzugefügt werden. Lesen Sie in der Anleitung des Geräteherstellers nach, wenn über einen Proxy übermittelte Anfragen ohne diese Header in der Anwendung eingehen. Verwendet das Gerät andere Headernamen als X-Forwarded-For
und X-Forwarded-Proto
, passen Sie die Optionen ForwardedForHeaderName und ForwardedProtoHeaderName entsprechend an. Weitere Informationen finden Sie in den Abschnitten Middleware für weitergeleitete Header: Optionen und Konfiguration für einen Proxy, der andere Headernamen nutzt.
IIS-/IIS Express und ASP.NET Core-Modul
Middleware für weitergeleitete Header wird standardmäßig durch Middleware für die Integration von IIS aktiviert, wenn die App hinter IIS und dem ASP.NET Core-Modul (ANCM) für IIS von einem Out-of-Process-Host gehostet wird. Middleware für weitergeleitete Header wird aktiviert, damit sie zuerst in der Middlewarepipeline mit einer eingeschränkten Konfiguration speziell für das ASP.NET Core-Modul ausgeführt wird. Die eingeschränkte Konfiguration wird aufgrund der Sicherheitsbedenken bei weitergeleiteten Headern angewendet, z. B. im Hinblick auf IP-Spoofing. Die Middleware wird so konfiguriert, dass sie die Header X-Forwarded-For
und X-Forwarded-Proto
weiterleitet, und ist auf einen einzelnen localhost-Proxy beschränkt. Wenn zusätzliche Konfigurationsschritte erforderlich sind, finden Sie weitere Informationen unter Middleware für weitergeleitete Header: Optionen.
Andere Proxyserver- und Lastenausgleichsszenarios
Abgesehen von der Verwendung zur IIS-Integration wird Middleware für weitergeleitete Header beim Out-of-Process-Hosting nicht standardmäßig aktiviert. Middleware für weitergeleitete Header muss aktiviert sein, damit eine App weitergeleitete Header mit UseForwardedHeaders verarbeitet. Sind nach der Aktivierung der Middleware keine ForwardedHeadersOptions für die Middleware angegeben, sind die standardmäßigen ForwardedHeadersOptions gleich ForwardedHeaders.None.
Konfigurieren Sie die Middleware mit ForwardedHeadersOptions so, dass die Header X-Forwarded-For
und X-Forwarded-Proto
weitergeleitet werden.
Middleware für weitergeleitete Header: Auftrag
Middleware für weitergeleitete Header muss vor anderen Middlewarekomponenten ausgeführt werden. Mit dieser Reihenfolge wird sichergestellt, dass die auf Informationen von weitergeleiteten Headern basierende Middleware die zu verarbeitenden Headerwerte nutzen kann. Die Middleware für weitergeleitete Header kann nach der Diagnose und Fehlerbehandlung ausgeführt werden. Sie muss jedoch vor dem Aufrufen von UseHstsausgeführt werden:
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();
Rufen Sie alternativ vor der Diagnose UseForwardedHeaders
auf:
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();
Hinweis
Sind keine ForwardedHeadersOptions in UseForwardedHeaders oder direkt für die Erweiterungsmethode angegeben, entsprechen die weiterzuleitenden Standardheader ForwardedHeadersOptions. Die ForwardedHeaders-Eigenschaft muss mit den weiterzuleitenden Headern konfiguriert werden.
Nginx-Konfiguration
Informationen zur Weiterleitung der Header X-Forwarded-For
und X-Forwarded-Proto
finden Sie unter X-Forwarded-For
. Weitere Informationen finden Sie unter NGINX: Using the Forwarded header (NGINX: Verwenden des weitergeleiteten Headers).
Apache-Konfiguration
X-Forwarded-For
wird automatisch hinzugefügt. Weitere Informationen finden Sie unter Apache-Modul mod_proxy: Reverseproxy-Anforderungsheader.
Middleware für weitergeleitete Header: Optionen
ForwardedHeadersOptions steuern das Verhalten der ForwardedHeadersOptions. Im folgenden Beispiel werden die Standardwerte geändert:
- Die Anzahl von Einträgen in den weitergeleiteten Headern wird auf
2
beschränkt. - Es wird die bekannte Proxyadresse
127.0.10.1
hinzugefügt. - Der Name des weitergeleiteten Headers wird vom Standardwert
X-Forwarded-For
in den WertX-Forwarded-For-My-Custom-Header-Name
geändert.
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();
Option | Beschreibung |
---|---|
AllowedHosts | Begrenzt Hosts durch den X-Forwarded-Host -Header auf die angegebenen Werte.
IList<string> . |
ForwardedForHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedForHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-For sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-For . |
ForwardedHeaders | Gibt an, welche Weiterleitungen verarbeitet werden sollen. Weitere Informationen zur Liste der anzuwendenden Felder finden Sie unter ForwardedHeaders Enum. Typische Werte, die dieser Eigenschaft zugewiesen wurden, sind ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto .Der Standardwert ist ForwardedHeaders.None. |
ForwardedHostHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedHostHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-Host sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-Host . |
ForwardedProtoHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedProtoHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-Proto sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-Proto . |
ForwardLimit | Schränkt die Anzahl der Einträge in den Headern ein, die verarbeitet werden. Legen Sie den Wert null fest, um die Einschränkung zu deaktivieren. Diese Einstellung sollte jedoch nur vorgenommen werden, wenn KnownProxies oder KnownNetworks konfiguriert sind. Das Festlegen eines Werts ungleich null ist eine Vorsichtsmaßnahme (aber keine Garantie) zum Schutz vor falsch konfigurierten Proxys und schädlichen Anforderungen aus Seitenkanälen im Netzwerk.Die Middleware der Weiterleitungsheader verarbeitet Header in umgekehrter Reihenfolge von rechts nach links. Wenn der Standardwert von ( 1 ) verwendet wird, wird nur der äußere rechte Wert aus den Headern verarbeitet, es sei denn, der Wert von ForwardLimit wird erhöht.Der Standardwert ist 1 . |
KnownNetworks | Adressbereiche bekannter Netzwerke; von dort weitergeleitete Header müssen akzeptiert werden. Geben Sie IP-Adressbereiche mithilfe der CIDR-Notation (Classless Interdomain Routing) an. Wenn der Server Dualmodussockets verwendet, werden IPv4-Adressen in einem IPv6-Format bereitgestellt (z.B. wird 10.0.0.1 in IPv4 in IPv6 als ::ffff:10.0.0.1 dargestellt). Siehe IPAddress.MapToIPv6. Bestimmen Sie mithilfe der HttpContext.Connection.RemoteIpAddress, ob dieses Format erforderlich ist.Der Standardwert lautet IList <IPNetwork> mit einem einzelnen Eintrag für new IPNetwork(IPAddress.Loopback, 8) . |
KnownProxies | Adressen bekannter Proxys, von denen weitergeleitete Header akzeptiert werden müssen. Verwenden Sie KnownProxies , um genaue IP-Adressübereinstimmungen anzugeben.Wenn der Server Dualmodussockets verwendet, werden IPv4-Adressen in einem IPv6-Format bereitgestellt (z.B. wird 10.0.0.1 in IPv4 in IPv6 als ::ffff:10.0.0.1 dargestellt). Siehe IPAddress.MapToIPv6. Bestimmen Sie mithilfe der HttpContext.Connection.RemoteIpAddress, ob dieses Format erforderlich ist.Der Standardwert lautet IList <IPAddress> mit einem einzelnen Eintrag für IPAddress.IPv6Loopback . |
OriginalForHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalForHeaderName angegebenen. Der Standardwert ist X-Original-For . |
OriginalHostHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalHostHeaderName angegebenen. Der Standardwert ist X-Original-Host . |
OriginalProtoHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalProtoHeaderName angegebenen. Der Standardwert ist X-Original-Proto . |
RequireHeaderSymmetry | Die Anzahl von Headerwerten muss in den ForwardedHeadersOptions.ForwardedHeaders übereinstimmen, die verarbeitet werden. Die Standardeinstellung in ASP.NET Core 1.x ist true . Die Standardeinstellung in ASP.NET Core 2.0 oder höher ist false . |
Szenarios und Anwendungsfälle
Wenn keine weitergeleiteten Header hinzugefügt werden können und alle Anforderungen sicher sind
In einigen Fällen ist es möglicherweise ausgeschlossen, weitergeleitete Header den Anforderungen hinzuzufügen, die über einen Proxy an die App übermittelt werden. Wenn der Proxy erzwingt, dass alle öffentlichen externen Anforderungen HTTPS-Anforderungen sein müssen, kann das Schema manuell festgelegt werden, bevor ein beliebiger Middlewaretyp verwendet wird:
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();
Dieser Code kann mit einer Umgebungsvariablen oder einer anderen Konfigurationseinstellung in einer Entwicklungs- oder Stagingumgebung deaktiviert werden:
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();
Arbeiten mit Pfadbasis und Proxys, die den Anforderungspfad ändern
Einige Proxys übergeben den Pfad intakt, aber mit einem App-basierten Pfad, der entfernt werden sollte, damit das Routing ordnungsgemäß funktioniert. UsePathBaseExtensions.UsePathBase-Middleware teilt den Pfad in HttpRequest.Path und den App-Basispfad in HttpRequest.PathBase.
Wenn /foo
der App-Basispfad für einen als /foo/api/1
übergebenen Proxypfad ist, setzt die Middleware mit dem folgenden Befehl Request.PathBase
auf /foo
und Request.Path
auf /api/1
:
app.UsePathBase("/foo");
// ...
app.UseRouting();
Hinweis
Wenn Sie WebApplication verwenden (siehe Migrieren von ASP.NET Core 5.0 zu 6.0), muss app.UseRouting
nach UsePathBase
aufgerufen werden, damit die Routingmiddleware den geänderten Pfad beobachten kann, bevor Routen abgeglichen werden. Andernfalls werden Routen abgeglichen, bevor der Pfad durch UsePathBase
neu geschrieben wird. Weitere Informationen hierzu finden Sie in den Artikeln Festlegen der Reihenfolge für Middleware und Routing.
Der ursprüngliche Pfad und die Pfadbasis werden erneut angewendet, wenn die Middleware in umgekehrter Reihenfolge erneut aufgerufen wird. Weitere Informationen zur Reihenfolge der Middlewareverarbeitung finden Sie unter ASP.NET Core-Middleware.
Wenn der Proxy den Pfad abschneidet (z.B. Weiterleitung von /foo/api/1
zu /api/1
), korrigieren Sie Umleitungen und Links, indem Sie die Eigenschaft /foo/api/1
der Anforderungen setzen:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next(context);
});
Wenn der Proxy Pfaddaten hinzufügt, verwerfen Sie einen Teil des Pfads, um Umleitungen und Links zu korrigieren, indem Sie StartsWithSegments verwenden und der Path-Eigenschaft zuweisen:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next(context);
});
Konfiguration für einen Proxy, der andere Headernamen verwendet
Verwendet der Proxy zum Weiterleiten der Proxyadresse/des Ports und zum Erzeugen der Schemainformationen andere Headernamen als X-Forwarded-For
und X-Forwarded-Proto
, passen Sie die Optionen ForwardedForHeaderName und ForwardedProtoHeaderName entsprechend an:
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();
Das Schema für Linux- und Nicht-IIS-Reverseproxys weiterleiten
Apps, die UseHttpsRedirection und UseHsts aufrufen, versetzen eine Site in eine Endlosschleife, falls die Bereitstellung in einem Azure Linux App Service, auf einem virtuellen Azure Linux-Computer, oder hinter einem anderen Reverseproxy als IIS erfolgt. TLS wird vom Reverseproxy beendet, und Kestrel wird nicht auf das richtige Anforderungsschema aufmerksam gemacht. OAuth und OIDC schlagen in dieser Konfiguration ebenfalls fehl, weil sie falsche Umleitungen generieren. UseIISIntegration fügt die Middleware für weitergeleitete Header hinzu und konfiguriert sie, wenn es hinter IIS ausgeführt wird, aber es gibt keine entsprechende automatische Konfiguration für Linux (Apache- oder Nginx-Integration).
Um das Schema aus dem Proxy in Nicht-IIS-Szenarien weiterzuleiten, aktivieren Sie die Middleware für weitergeleitete Header, indem Sie ASPNETCORE_FORWARDEDHEADERS_ENABLED
auf true
festlegen. Warnung: Dieses Flag verwendet Einstellungen für Cloudumgebungen und aktiviert keine Features wie die KnownProxies option
, um einzuschränken, von welchen IPs Weiterleitungen akzeptiert werden.
Zertifikatweiterleitung
Azure
Informationen zum Konfigurieren von Azure App Service für die Zertifikatsweiterleitung finden Sie unter Konfigurieren der gegenseitigen TLS-Authentifizierung für Azure App Service. Die folgende Anleitung bezieht sich auf die Konfiguration der ASP.NET Core-App.
- Konfigurieren Sie Middleware für die Zertifikatweiterleitung, um den von Azure verwendeten Headernamen anzugeben. Fügen Sie den folgenden Code hinzu, um den Header zu konfigurieren, anhand dessen die Middleware ein Zertifikat erstellt.
- Rufen Sie UseCertificateForwarding vor UseAuthentication auf.
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();
Andere Webproxys
Wenn ein Proxy verwendet wird, der nicht IIS oder Routing von Anwendungsanforderungen von Azure App Service entspricht, konfigurieren Sie den Proxy so, dass das empfangene Zertifikat in einem HTTP-Header weitergeleitet wird.
- Konfigurieren Sie Middleware für die Zertifikatweiterleitung, um den Headernamen anzugeben. Fügen Sie den folgenden Code hinzu, um den Header zu konfigurieren, anhand dessen die Middleware ein Zertifikat erstellt.
- Rufen Sie UseCertificateForwarding vor UseAuthentication auf.
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();
Wenn der Proxy keine Base64-Codierung für das Zertifikat verwendet (wie bei Nginx), legen Sie die Option HeaderConverter
fest. Betrachten Sie das folgenden Beispiel:
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();
Problembehandlung
Wenn Header nicht wie erwartet weitergeleitet werden, aktivieren Sie die debug
auf debug
-Ebene und die HTTP-Anforderungsprotokollierung. UseHttpLogging muss nach UseForwardedHeaders aufgerufen werden:
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();
Wenn in einem bestimmten Header mehrere Werte vorhanden sind, verarbeitet die Middleware der Weiterleitungsheader die Header in umgekehrter Reihenfolge von rechts nach links. Der Standardwert von ForwardLimit
ist 1
(eins), sodass nur der äußere rechte Wert aus den Headern verarbeitet wird, es sei denn, der Wert von ForwardLimit
wird erhöht.
Die ursprüngliche IP-Remoteadresse der Anforderung muss mit einem Eintrag in den KnownProxies- oder KnownNetworks-Listen übereinstimmen, bevor weitergeleitete Header verarbeitet werden. Auf diese Weise wird das Headerspoofing begrenzt, da keine Weiterleitungen von nicht vertrauenswürdigen Proxys akzeptiert werden. Wenn ein unbekannter Proxy erkannt wird, gibt die Protokollierung die Adresse des Proxys an:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Im vorherigen Beispiel ist 10.0.0.100 ein Proxyserver. Wenn der Server ein vertrauenswürdiger Proxy ist, fügen Sie KnownNetworks
die IP-Adresse des Servers KnownProxies
oder ein vertrauenswürdiges Netzwerk hinzu. Weitere Informationen finden Sie im Abschnitt Middleware für weitergeleitete Header: Optionen.
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();
Um die Protokolle anzuzeigen, fügen Sie "Microsoft.AspNetCore.HttpLogging": "Information"
der Datei appsettings.Development.json
hinzu:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging": "Information"
}
}
}
Wichtig
Erlauben Sie nur vertrauenswürdigen Proxys und Netzwerken die Weiterleitung von Headern. Andernfalls sind Angriffe des Typs IP-Spoofing möglich.
Zusätzliche Ressourcen
- Hosten von ASP.NET Core in einer Webfarm
- Microsoft Security Advisory CVE-2018-0787: ASP.NET Core Elevation Of Privilege Vulnerability (Microsoft-Sicherheitsempfehlung CVE-2018-0787: Sicherheitsrisiko durch Rechteerweiterungen in ASP.NET Core)
- YARP: Yet Another Reverse Proxy (ein weiterer Reverseproxy)
In der für ASP.NET Core empfohlenen Konfiguration wird die App mit dem IIS/ASP.NET Core-Modul, Nginx oder Apache gehostet. Proxyserver, Lastenausgleichsmodule und anderen Netzwerkgeräte verdecken häufig Informationen über die Anforderung, bevor diese die App erreicht:
- Wenn HTTPS-Anforderungen über HTTP-Proxy ausgeführt werden, geht das ursprüngliche Schema (HTTPS) verloren und muss in einem Header weitergeleitet werden.
- Da eine App eine Anforderung über den Proxy empfängt und nicht über ihre echte Quelle im Internet oder Unternehmensnetzwerk, muss die ursprüngliche Client-IP-Adresse ebenfalls in einem Header weitergeleitet werden.
Diese Informationen können im Anforderungsprozess, z.B. in Umleitungen, bei der Authentifizierung, der Linkgenerierung, der Richtlinienauswertung und der Client-Geolocation wichtig sein.
Weitergeleitete Header
Gemäß der Konvention leiten Proxys Informationen in HTTP-Headern weiter.
Header | Beschreibung |
---|---|
X-Forwarded-For | Enthält Informationen zum Client, der die Anforderung und die nachfolgenden Proxys in einer Kette von Proxys initiiert hat. Dieser Parameter kann IP-Adressen (und optional Portnummern) enthalten. Der erste Parameter in einer Kette von Proxyservern gibt den Client an, auf dem die Anforderung zuerst gesendet wurde. Darauf folgen weitere Proxybezeichner. Der letzte Proxy in der Kette ist nicht in der Liste der Parameter. Die IP-Adresse des letzten Proxys und optional eine Portnummer stehen als Remote IP-Adresse auf der Transportschicht zur Verfügung. |
X-Forwarded-Proto | Der Wert des ursprünglichen Schemas (HTTP/HTTPS). Der Wert kann auch eine Liste von Schemas sein, wenn die Anforderung mehrere Proxys durchlaufen hat. |
X-Forwarded-Host | Der ursprüngliche Wert des Felds „Hostheader“. In der Regel ändern Proxys den Hostheader nicht. Informationen zu einem Sicherheitsrisiko, das Rechteerweiterungen ermöglicht und sich auf Systeme auswirkt, in denen der Proxy Hostheader nicht validiert oder auf als unbedenklich bekannte Werte beschränkt, finden Sie in der Microsoft-Sicherheitsempfehlung CVE-2018-0787. |
Die Middleware für weitergeleitete Header (ForwardedHeadersMiddleware) liest die Header und füllt die zugehörigen Felder in HttpContext aus.
Die Middleware aktualisiert:
- HttpContext.Connection.RemoteIpAddress: Wird über den Headerwert
X-Forwarded-For
festgelegt. Zusätzliche Einstellungen beeinflussen, wie die MiddlewareRemoteIpAddress
festlegt. Einzelheiten finden Sie unter Middleware für weitergeleitete Header: Optionen. Die genutzten Werte werden ausX-Forwarded-For
entfernt, und die alten Werte werden inX-Original-For
beibehalten. Das gleiche Muster wird auf die anderen Header (Host
undProto
) angewendet. - HttpContext.Request.Scheme: Wird über den Headerwert
X-Forwarded-Proto
festgelegt. - HttpContext.Request.Host: Wird über den Headerwert
X-Forwarded-Host
festgelegt.
Weitere Informationen hierzu finden Sie in diesem GitHub-Issue.
Die Standardeinstellungen der Middleware für weitergeleitete Header können konfiguriert werden. Für die Standardeinstellungen:
- Zwischen App und Quelle der Anforderungen ist nur ein Proxy vorhanden.
- Loopbackadressen sind für bekannte Proxys und bekannte Netzwerke konfiguriert.
- Die weitergeleiteten Header heißen
X-Forwarded-For
undX-Forwarded-Proto
. - Der Wert
ForwardedHeaders
lautetForwardedHeaders.None
, und die gewünschten Forwarder müssen hier festgelegt werden, um die Middleware zu aktivieren.
Beachten Sie, dass bei manchen Netzwerkgeräten eine zusätzliche Konfiguration erforderlich ist, damit die Header X-Forwarded-For
und X-Forwarded-Proto
hinzugefügt werden. Lesen Sie in der Anleitung des Geräteherstellers nach, wenn über einen Proxy übermittelte Anfragen ohne diese Header in der Anwendung eingehen. Verwendet das Gerät andere Headernamen als X-Forwarded-For
und X-Forwarded-Proto
, passen Sie die Optionen ForwardedForHeaderName und ForwardedProtoHeaderName entsprechend an. Weitere Informationen finden Sie in den Abschnitten Middleware für weitergeleitete Header: Optionen und Konfiguration für einen Proxy, der andere Headernamen nutzt.
IIS-/IIS Express und ASP.NET Core-Modul
Middleware für weitergeleitete Header wird standardmäßig durch Middleware für die Integration von IIS aktiviert, wenn die App hinter IIS und dem ASP.NET Core-Modul von einem Out-of-Process-Host gehostet wird. Middleware für weitergeleitete Header wird aktiviert und zuerst in der Middlewarepipeline mit einer beschränkten Konfiguration ausgeführt, die für das ASP.NET Core-Modul spezifisch ist. Dies ist auf Bedenken in Bezug auf die Vertrauenswürdigkeit von weitergeleiteten Headern zurückzuführen (z.B. IP-Spoofing). Die Middleware wird so konfiguriert, dass sie die Header X-Forwarded-For
und X-Forwarded-Proto
weiterleitet, und ist auf einen einzelnen localhost-Proxy beschränkt. Wenn zusätzliche Konfigurationsschritte erforderlich sind, finden Sie weitere Informationen unter Middleware für weitergeleitete Header: Optionen.
Andere Proxyserver- und Lastenausgleichsszenarios
Außer bei der Verwendung der Integration von IIS wird die Middleware für weitergeleitete Header nicht standardmäßig aktiviert, wenn sie von einem Out-of-Process-Host gehostet wird. Middleware für weitergeleitete Header muss aktiviert sein, damit eine App weitergeleitete Header mit UseForwardedHeaders verarbeitet. Sind nach der Aktivierung der Middleware keine ForwardedHeadersOptions für die Middleware angegeben, sind die standardmäßigen ForwardedHeadersOptions gleich ForwardedHeaders.None.
Konfigurieren Sie die Middleware mit ForwardedHeadersOptions so, dass die Header X-Forwarded-For
und X-Forwarded-Proto
in Startup.ConfigureServices
weitergeleitet werden.
Middleware für weitergeleitete Header: Auftrag
Middleware für weitergeleitete Header muss vor anderen Middlewarekomponenten ausgeführt werden. Mit dieser Reihenfolge wird sichergestellt, dass die auf Informationen von weitergeleiteten Headern basierende Middleware die zu verarbeitenden Headerwerte nutzen kann. Die Middleware für weitergeleitete Header kann nach der Diagnose und Fehlerbehandlung ausgeführt werden. Sie muss jedoch vor dem Aufrufen von UseHsts
ausgeführt werden:
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?}");
});
}
}
Rufen Sie alternativ vor der Diagnose UseForwardedHeaders
auf:
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?}");
});
}
Hinweis
Sind keine ForwardedHeadersOptions in Startup.ConfigureServices
oder direkt für die Erweiterungsmethode mit UseForwardedHeaders angegeben, sind die weiterzuleitenden Standardheader gleich ForwardedHeadersOptions. Die ForwardedHeaders-Eigenschaft muss mit den weiterzuleitenden Headern konfiguriert werden.
Nginx-Konfiguration
Informationen zur Weiterleitung der Header X-Forwarded-For
und X-Forwarded-Proto
finden Sie unter X-Forwarded-For
. Weitere Informationen finden Sie unter NGINX: Using the Forwarded header (NGINX: Verwenden des weitergeleiteten Headers).
Apache-Konfiguration
X-Forwarded-For
wird automatisch hinzugefügt (siehe X-Forwarded-For
).
Middleware für weitergeleitete Header: Optionen
ForwardedHeadersOptions steuern das Verhalten der Middleware für weitergeleitete Header. Im folgenden Beispiel werden die Standardwerte geändert:
- Beschränken Sie die Zahl der Einträge in den weitergeleiteten Headern auf
2
. - Fügen Sie eine bekannte Proxyadresse von
127.0.10.1
hinzu. - Ändern Sie den Namen des weitergeleiteten Headers vom Standardwert
X-Forwarded-For
in den WertX-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";
});
Option | Beschreibung |
---|---|
AllowedHosts | Begrenzt Hosts durch den X-Forwarded-Host -Header auf die angegebenen Werte.
IList<string> . |
ForwardedHeaders | Gibt an, welche Weiterleitungen verarbeitet werden sollen. Weitere Informationen zur Liste der anzuwendenden Felder finden Sie unter ForwardedHeaders Enum. Typische Werte, die dieser Eigenschaft zugewiesen wurden, sind ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto .Der Standardwert ist ForwardedHeaders.None. |
ForwardedForHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedForHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-For sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-For . |
ForwardedHostHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedHostHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-Host sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-Host . |
ForwardedProtoHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XForwardedProtoHeaderName angegebenen. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-Proto sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-Proto . |
ForwardedPrefixHeaderName | Verwenden Sie die von dieser Eigenschaft angegebene Kopfzeile anstelle der durch ForwardedHeadersDefaults.XForwardedPrefixHeaderNameangegebenen Kopfzeile. Diese Option wird verwendet, wenn beim Proxy/Weiterleitenden nicht der Header X-Forwarded-Prefix sondern ein anderer Header für die Weiterleitung der Informationen genutzt wird.Der Standardwert ist X-Forwarded-Prefix . |
ForwardLimit | Schränkt die Anzahl der Einträge in den Headern ein, die verarbeitet werden. Legen Sie den Wert null fest, um die Einschränkung zu deaktivieren. Diese Einstellung sollte jedoch nur vorgenommen werden, wenn KnownProxies oder KnownNetworks konfiguriert sind. Das Festlegen eines Werts ungleich null ist eine Vorsichtsmaßnahme (aber keine Garantie) zum Schutz vor falsch konfigurierten Proxys und schädlichen Anforderungen aus Seitenkanälen im Netzwerk.Die Middleware der Weiterleitungsheader verarbeitet Header in umgekehrter Reihenfolge von rechts nach links. Wenn der Standardwert von ( 1 ) verwendet wird, wird nur der äußere rechte Wert aus den Headern verarbeitet, es sei denn, der Wert von ForwardLimit wird erhöht.Der Standardwert ist 1 . |
KnownNetworks | Adressbereiche bekannter Netzwerke; von dort weitergeleitete Header müssen akzeptiert werden. Geben Sie IP-Adressbereiche mithilfe der CIDR-Notation (Classless Interdomain Routing) an. Wenn der Server Dualmodussockets verwendet, werden IPv4-Adressen in einem IPv6-Format bereitgestellt (z.B. wird 10.0.0.1 in IPv4 in IPv6 als ::ffff:10.0.0.1 dargestellt). Siehe IPAddress.MapToIPv6. Bestimmen Sie mithilfe der HttpContext.Connection.RemoteIpAddress, ob dieses Format erforderlich ist.Der Standardwert lautet IList <IPNetwork> mit einem einzelnen Eintrag für new IPNetwork(IPAddress.Loopback, 8) . |
KnownProxies | Adressen bekannter Proxys, von denen weitergeleitete Header akzeptiert werden müssen. Verwenden Sie KnownProxies , um genaue IP-Adressübereinstimmungen anzugeben.Wenn der Server Dualmodussockets verwendet, werden IPv4-Adressen in einem IPv6-Format bereitgestellt (z.B. wird 10.0.0.1 in IPv4 in IPv6 als ::ffff:10.0.0.1 dargestellt). Siehe IPAddress.MapToIPv6. Bestimmen Sie mithilfe der HttpContext.Connection.RemoteIpAddress, ob dieses Format erforderlich ist.Der Standardwert lautet IList <IPAddress> mit einem einzelnen Eintrag für IPAddress.IPv6Loopback . |
OriginalForHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalForHeaderName angegebenen. Der Standardwert ist X-Original-For . |
OriginalHostHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalHostHeaderName angegebenen. Der Standardwert ist X-Original-Host . |
OriginalProtoHeaderName | Verwenden Sie den Header, der von dieser Eigenschaft angegeben wurde, anstelle des von ForwardedHeadersDefaults.XOriginalProtoHeaderName angegebenen. Der Standardwert ist X-Original-Proto . |
OriginalPrefixHeaderName | Verwenden Sie die von dieser Eigenschaft angegebene Kopfzeile anstelle der durch ForwardedHeadersDefaults.XOriginalPrefixHeaderNameangegebenen Kopfzeile. Der Standardwert ist X-Original-Prefix . |
RequireHeaderSymmetry | Die Anzahl von Headerwerten muss in den ForwardedHeadersOptions.ForwardedHeaders übereinstimmen, die verarbeitet werden. Die Standardeinstellung in ASP.NET Core 1.x ist true . Die Standardeinstellung in ASP.NET Core 2.0 oder höher ist false . |
Szenarios und Anwendungsfälle
Wenn keine weitergeleiteten Header hinzugefügt werden können und alle Anforderungen sicher sind
In einigen Fällen ist es möglicherweise ausgeschlossen, weitergeleitete Header den Anforderungen hinzuzufügen, die über einen Proxy an die App übermittelt werden. Wenn der Proxy erzwingt, dass alle öffentlichen externen Anforderungen HTTPS-Anforderungen sind, kann das Schema manuell in Startup.Configure
festgelegt werden, bevor ein beliebiger Middlewaretyp verwendet wird:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
Dieser Code kann mit einer Umgebungsvariablen oder einer anderen Konfigurationseinstellung in einer Entwicklungs- oder Stagingumgebung deaktiviert werden.
Umgang mit Pfadbasis und Proxys, die den Anforderungspfad ändern
Einige Proxys übergeben den Pfad intakt, aber mit einem App-basierten Pfad, der entfernt werden sollte, damit das Routing ordnungsgemäß funktioniert. UsePathBaseExtensions.UsePathBase-Middleware teilt den Pfad in HttpRequest.Path und den App-Basispfad in HttpRequest.PathBase.
Wenn /foo
der App-Basispfad für einen als /foo/api/1
übergebenen Proxypfad ist, setzt die Middleware mit dem folgenden Befehl Request.PathBase
auf /foo
und Request.Path
auf /api/1
:
app.UsePathBase("/foo");
Der ursprüngliche Pfad und die Pfadbasis werden erneut angewendet, wenn die Middleware in umgekehrter Reihenfolge erneut aufgerufen wird. Weitere Informationen zur Reihenfolge der Middlewareverarbeitung finden Sie unter ASP.NET Core-Middleware.
Wenn der Proxy den Pfad abschneidet (z.B. Weiterleitung von /foo/api/1
zu /api/1
), korrigieren Sie Umleitungen und Links, indem Sie die Eigenschaft /foo/api/1
der Anforderungen setzen:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next();
});
Wenn der Proxy Pfaddaten hinzufügt, verwerfen Sie einen Teil des Pfads, um Umleitungen und Links zu korrigieren, indem Sie StartsWithSegments verwenden und der Path-Eigenschaft zuweisen:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next();
});
Konfiguration für einen Proxy, der andere Headernamen verwendet
Verwendet der Proxy zum Weiterleiten der Proxyadresse/des Ports und zum Erzeugen der Schemainformationen andere Headernamen als X-Forwarded-For
und X-Forwarded-Proto
, passen Sie die Optionen ForwardedForHeaderName und ForwardedProtoHeaderName entsprechend an:
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";
});
Das Schema für Linux- und Nicht-IIS-Reverseproxys weiterleiten
Apps, die UseHttpsRedirection und UseHsts aufrufen, versetzen eine Site in eine Endlosschleife, falls die Bereitstellung in einem Azure Linux App Service, auf einem virtuellen Azure Linux-Computer, oder hinter einem anderen Reverseproxy als IIS erfolgt. TLS wird vom Reverseproxy beendet, und Kestrel wird nicht auf das richtige Anforderungsschema aufmerksam gemacht. OAuth und OIDC schlagen in dieser Konfiguration ebenfalls fehl, weil sie falsche Umleitungen generieren. UseIISIntegration fügt die Middleware für weitergeleitete Header hinzu und konfiguriert sie, wenn es hinter IIS ausgeführt wird, aber es gibt keine entsprechende automatische Konfiguration für Linux (Apache- oder Nginx-Integration).
Um das Schema von dem Proxy in Nicht-IIS-Szenarios weiterzuleiten, fügen Sie die Middleware für weitergeleitete Header hinzu, und konfigurieren Sie sie. In Startup.ConfigureServices
verwenden Sie folgenden Code:
// 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();
});
}
Zertifikatweiterleitung
Azure
Informationen zum Konfigurieren von Azure App Service für die Zertifikatsweiterleitung finden Sie unter Konfigurieren der gegenseitigen TLS-Authentifizierung für Azure App Service. Die folgende Anleitung bezieht sich auf die Konfiguration der ASP.NET Core-App.
Fügen Sie Startup.Configure
direkt vor dem Aufruf von app.UseAuthentication();
den folgenden Code hinzu:
app.UseCertificateForwarding();
Konfigurieren Sie die Middleware für die Zertifikatweiterleitung, um den von Azure verwendeten Headernamen anzugeben. Fügen Sie in Startup.ConfigureServices
den folgenden Code hinzu, um den Header zu konfigurieren, anhand dessen die Middleware ein Zertifikat erstellt:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
Andere Webproxys
Wenn ein Proxy verwendet wird, der nicht IIS oder Routing von Anwendungsanforderungen von Azure App Service entspricht, konfigurieren Sie den Proxy so, dass das empfangene Zertifikat in einem HTTP-Header weitergeleitet wird. Fügen Sie Startup.Configure
direkt vor dem Aufruf von app.UseAuthentication();
den folgenden Code hinzu:
app.UseCertificateForwarding();
Konfigurieren Sie die Middleware für die Zertifikatweiterleitung konfigurieren, um den Headernamen anzugeben. Fügen Sie in Startup.ConfigureServices
den folgenden Code hinzu, um den Header zu konfigurieren, anhand dessen die Middleware ein Zertifikat erstellt:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
Wenn der Proxy das Zertifikat mit nicht mit base64 codiert (wie bei Nginx), legen Sie die Option HeaderConverter
fest. Betrachten Sie das folgende Beispiel 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;
}
});
Problembehandlung
Wenn Header nicht wie erwartet zugewiesen werden, aktivieren Sie die Protokollierung. Wenn die Protokolle nicht genügend Informationen zur Problembehandlung bereitstellen, listen Sie die vom Server empfangenen Anforderungsheader auf. Verwenden Sie Inlinemiddleware, um Anforderungsheader in eine App-Antwort zu schreiben oder die Header zu protokollieren.
Um die Header in die Antwort der App zu schreiben, platzieren Sie die folgende Terminalinlinemiddleware unmittelbar hinter den Aufruf von 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}");
});
Statt in den Antworttext können Sie in Protokolle schreiben. Das Schreiben in Protokolle ermöglicht es der Website, während des Debuggens normal zu funktionieren.
So schreiben Sie in Protokolle und nicht in den Antworttext:
- Fügen Sie
ILogger<Startup>
in dieStartup
-Klasse ein, wie unterILogger<Startup>
beschrieben. - Platzieren Sie die folgende Inlinemiddleware unmittelbar hinter den Aufruf von 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();
});
Bei der Verarbeitung werden X-Forwarded-{For|Proto|Host|Prefix}
-Werte in X-Original-{For|Proto|Host|Prefix}
verschoben. Wenn in einem bestimmten Header mehrere Werte vorhanden sind, verarbeitet die Middleware der Weiterleitungsheader die Header in umgekehrter Reihenfolge von rechts nach links. Der Standardwert von ForwardLimit
ist 1
(eins), sodass nur der äußere rechte Wert aus den Headern verarbeitet wird, es sei denn, der Wert von ForwardLimit
wird erhöht.
Die ursprüngliche IP-Remoteadresse der Anforderung muss mit einem Eintrag in den KnownProxies
- oder KnownNetworks
-Listen übereinstimmen, bevor weitergeleitete Header verarbeitet werden. Auf diese Weise wird das Headerspoofing begrenzt, da keine Weiterleitungen von nicht vertrauenswürdigen Proxys akzeptiert werden. Wenn ein unbekannter Proxy erkannt wird, gibt die Protokollierung die Adresse des Proxys an:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Im vorherigen Beispiel ist 10.0.0.100 ein Proxyserver. Wenn der Server ein vertrauenswürdiger Proxy ist, fügen Sie die IP-Adresse des Servers KnownProxies
(oder ein vertrauenswürdiges Netzwerk KnownNetworks
) in Startup.ConfigureServices
hinzu. Weitere Informationen finden Sie im Abschnitt Middleware für weitergeleitete Header: Optionen.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
Wichtig
Erlauben Sie nur vertrauenswürdigen Proxys und Netzwerken die Weiterleitung von Headern. Andernfalls sind Angriffe des Typs IP-Spoofing möglich.
Zusätzliche Ressourcen
- Hosten von ASP.NET Core in einer Webfarm
- Microsoft Security Advisory CVE-2018-0787: ASP.NET Core Elevation Of Privilege Vulnerability (Microsoft-Sicherheitsempfehlung CVE-2018-0787: Sicherheitsrisiko durch Rechteerweiterungen in ASP.NET Core)
- YARP: Yet Another Reverse Proxy (ein weiterer Reverseproxy)
ASP.NET Core