ASP.NET Core configureren voor gebruik met proxyservers en load balancers

Notitie

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 10-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 10-versie van dit artikel voor de huidige release.

Door Chris Ross

In de aanbevolen configuratie voor ASP.NET Core wordt de app gehost met behulp van ASP.NET Core Module (ANCM) voor IIS-, Nginx of Apache. Proxyservers, load balancers en andere netwerkapparaten verhullen vaak informatie over de aanvraag voordat deze de app bereikt:

  • Wanneer HTTPS-aanvragen via HTTP worden geproxied, gaat het oorspronkelijke schema (HTTPS) verloren en moet het worden doorgestuurd in een header.
  • Omdat een app een aanvraag van de proxy ontvangt en niet de werkelijke bron op internet of het bedrijfsnetwerk, moet het ip-adres van de oorspronkelijke client ook worden doorgestuurd in een header.

Deze informatie kan belangrijk zijn bij het verwerken van aanvragen, bijvoorbeeld bij omleidingen, verificatie, het genereren van koppelingen, beleidsevaluatie en clientgeolocatie.

Apps die zijn bedoeld om uitgevoerd te worden op een webfarm, zouden Host ASP.NET Core in een webfarmmoeten raadplegen.

Doorgestuurde headers

Standaard sturen proxy's informatie door in HTTP-headers.

Koptekst Beschrijving
X-Forwarded-For (XFF) Bevat informatie over de client die de aanvraag en volgende proxy's heeft geïnitieerd in een keten van proxy's. Deze parameter kan IP-adressen en, optioneel, poortnummers bevatten. In een keten van proxyservers geeft de eerste parameter de client aan waar de aanvraag voor het eerst is gedaan. Verdere proxy-id's volgen. De laatste proxy in de keten staat niet in de lijst met parameters. Het IP-adres van de laatste proxy en eventueel een poortnummer zijn beschikbaar als het externe IP-adres op de transportlaag.
X-Forwarded-Proto (XFP) De waarde van het oorspronkelijke schema, HTTP of HTTPS. De waarde kan ook een lijst met schema's zijn als de aanvraag meerdere proxy's heeft doorlopen.
X-Forwarded-Host (XFH) De oorspronkelijke waarde van het veld Hostheader. Meestal wijzigen proxy's de Host-header niet. Zie Microsoft Beveiliging Advisory CVE-2018-0787 voor informatie over een beveiligingsprobleem met uitbreiding van bevoegdheden dat van invloed is op systemen waarop de proxy hostheaders niet valideert of beperkt tot bekende goede waarden.
X-Forwarded-Prefix Het oorspronkelijke basispad dat door de client is aangevraagd. Deze header kan handig zijn voor toepassingen om URL's, omleidingen of koppelingen naar de client correct te genereren.

De middleware voor doorgestuurde headers, ForwardedHeadersMiddleware leest deze headers en vult de bijbehorende velden van HttpContext in.

De middleware wordt bijgewerkt:

Zie dit GitHub-probleemvoor meer informatie over het voorgaande.

De standaardinstellingen van de middleware voor doorgestuurde headers kunnen worden geconfigureerd. Voor de standaardinstellingen:

  • Er is slechts één proxy tussen de app en de bron van de aanvragen.
  • Alleen loopback-adressen zijn geconfigureerd voor bekende proxy's en bekende netwerken.
  • De doorgestuurde headers hebben de naam X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host en X-Forwarded-Prefix.
  • De ForwardedHeaders waarde is ForwardedHeaders.None. De gewenste doorstuurservers moeten hier worden ingesteld om de middleware in te schakelen.

Niet alle netwerkapparaten voegen de X-Forwarded-For en X-Forwarded-Proto headers toe zonder extra configuratie. Raadpleeg de richtlijnen van de fabrikant van uw apparaat als opgegeven aanvragen deze headers niet bevatten wanneer ze de app bereiken. Als het apparaat andere headernamen gebruikt dan X-Forwarded-For en X-Forwarded-Proto, stelt u de ForwardedForHeaderName- en ForwardedProtoHeaderName-opties in zodat deze overeenkomen met de headernamen die door het apparaat worden gebruikt. Zie de opties voor doorgestuurde headers middleware en configuratie voor een proxy die gebruikmaakt van verschillende headernamen voor meer informatie.

IIS/IIS Express en ASP.NET Core-module

De IIS-integratiemiddleware schakelt standaard de middleware voor doorgestuurde headers in wanneer de app buiten het proces wordt gehost achter IIS en de ASP.NET Core Module (ANCM) voor IIS. Middleware voor doorgestuurde headers wordt geactiveerd zodat deze als eerste in de middlewarepijplijn wordt uitgevoerd, met een beperkte configuratie die specifiek is voor de ASP.NET Core-module. De beperkte configuratie is te wijten aan vertrouwensproblemen met doorgestuurde headers, bijvoorbeeld IP-adresvervalsing. De middleware is geconfigureerd om de X-Forwarded-For en X-Forwarded-Proto headers door te sturen en is beperkt tot één localhost-proxy. Als extra configuratie vereist is, zie de middlewareopties voor doorgestuurde headers.

Andere scenario's voor proxyservers en load balancer

Buiten het gebruik van IIS-integratie bij het hosten van out-of-process is doorgestuurde headers middleware niet standaard ingeschakeld. Middleware voor doorgestuurde headers moet zijn ingeschakeld voor een app voor het verwerken van doorgestuurde headers met UseForwardedHeaders. Nadat u de middleware hebt ingeschakeld en er geen ForwardedHeadersOptions zijn opgegeven voor de middleware, worden standaard ForwardedHeadersOptions.ForwardedHeaders ingesteld op ForwardedHeaders.None.

Configureer de middleware met ForwardedHeadersOptions om de X-Forwarded-For en X-Forwarded-Proto headers door te sturen.

Volgorde van middleware voor doorgestuurde headers

Middleware voor doorgestuurde headers moet worden uitgevoerd vóór andere middleware. Deze volgorde zorgt ervoor dat de middleware die afhankelijk is van informatie over doorgestuurde headers de headerwaarden kan gebruiken voor verwerking. De middleware voor doorgestuurde headers kan worden uitgevoerd na diagnose en foutafhandeling, maar moet worden uitgevoerd voordat UseHsts wordt aangeroepen:

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();

U kunt ook UseForwardedHeaders aanroepen vóór diagnose.

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();

Notitie

Als er geen ForwardedHeadersOptions worden opgegeven of rechtstreeks op de extensiemethode met UseForwardedHeadersworden toegepast, zijn de standaardheaders die worden doorgestuurd ForwardedHeaders.None. De eigenschap ForwardedHeaders moet worden geconfigureerd met de headers die doorgestuurd moeten worden.

Nginx-configuratie

Zie X-Forwarded-Forom de headers voor X-Forwarded-Proto en door te sturen.

Apache-configuratie

X-Forwarded-For wordt automatisch toegevoegd. Voor meer informatie, zie Apache Module mod_proxy: Headers voor omgekeerde proxyaanvragen.

Opties voor middleware voor doorgestuurde headers

ForwardedHeadersOptions het gedrag van de middleware voor doorgestuurde headers beheren. In het volgende voorbeeld worden de standaardwaarden gewijzigd:

  • Beperkt het aantal vermeldingen in de doorgestuurde headers tot 2.
  • Hiermee wordt een bekend proxyadres van 127.0.10.1toegevoegd.
  • Hiermee wijzigt u de naam van de doorgestuurde koptekst van de standaard-X-Forwarded-For in X-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();
Optie Beschrijving
AllowedHosts Hiermee beperkt u hosts door de X-Forwarded-Host header tot de opgegeven waarden.
  • Waarden worden vergeleken met ordinaal-ignore-case.
  • Poortnummers moeten worden uitgesloten.
  • Als de lijst leeg is, zijn alle hosts toegestaan.
  • Een jokerteken op het hoogste niveau * staat alle niet-lege hosts toe.
  • Jokertekens voor subdomeinen zijn toegestaan, maar komen niet overeen met het hoofddomein. *.contoso.com komt bijvoorbeeld overeen met het subdomein foo.contoso.com maar niet het hoofddomein contoso.com.
  • Unicode-hostnamen zijn toegestaan, maar worden geconverteerd naar Punycode- voor het vergelijken.
  • IPv6-adressen moeten begrenzingshaken bevatten en zich in conventionele vorm bevinden (bijvoorbeeld [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). IPv6-adressen zijn niet speciaal bedoeld om te controleren op logische gelijkheid tussen verschillende indelingen en er wordt geen canonicalisatie uitgevoerd.
  • Het niet beperken van de toegestane hosts kan een cyberaanvaller in staat stellen om koppelingen te spoofen die door de service worden gegenereerd.
De standaardwaarde is een lege IList<string>.
ForwardedForHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de koptekst die is opgegeven door ForwardedHeadersDefaults.XForwardedForHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-For header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-For.
ForwardedHeaders Hiermee wordt bepaald welke doorstuurders moeten worden verwerkt. Zie de ForwardedHeaders Enum- voor de lijst met velden die van toepassing zijn. Typische waarden die aan deze eigenschap zijn toegewezen, worden ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

De standaardwaarde is ForwardedHeaders.None.
ForwardedHostHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XForwardedHostHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-Host header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-Host.
ForwardedProtoHeaderName Gebruik de header die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XForwardedProtoHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-Proto header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-Proto.
ForwardLimit Hiermee beperkt u het aantal vermeldingen in de kopteksten die worden verwerkt. Ingesteld op null om de limiet uit te schakelen, maar dit moet alleen worden gedaan als KnownProxies of KnownNetworks zijn geconfigureerd. Het instellen van een niet-null waarde is een voorzorgsmaatregel (maar geen garantie) om te beschermen tegen onjuist geconfigureerde proxy's en schadelijke aanvragen die afkomstig zijn van side-channels in het netwerk.

Middleware voor doorgestuurde headers verwerkt de headers in omgekeerde volgorde van rechts naar links. Als de standaardwaarde (1) wordt gebruikt, wordt alleen de meest rechtse waarde van de headers verwerkt, tenzij de waarde van ForwardLimit wordt verhoogd.

De standaardwaarde is 1.
KnownNetworks Adresbereiken van bekende netwerken waaruit doorgestuurde headers moeten worden geaccepteerd. Ip-bereiken opgeven met cidr-notatie (Classless Interdomain Routing).

Als de server sockets met dubbele modus gebruikt, worden IPv4-adressen opgegeven in een IPv6-indeling (bijvoorbeeld 10.0.0.1 in IPv4 die als ::ffff:10.0.0.1in IPv6 worden weergegeven). Zie IPAddress.MapToIPv6-. Bepaal of deze indeling is vereist door de HttpContext.Connection.RemoteIpAddresste bekijken.

De standaardwaarde is een IList<IPNetwork> met één vermelding voor new IPNetwork(IPAddress.Loopback, 8).
KnownProxies Adressen van bekende proxy's waaruit doorgestuurde headers moeten worden geaccepteerd. Gebruik KnownProxies om exacte IP-adresovereenkomsten op te geven.

Als de server sockets met dubbele modus gebruikt, worden IPv4-adressen opgegeven in een IPv6-indeling (bijvoorbeeld 10.0.0.1 in IPv4 die als ::ffff:10.0.0.1in IPv6 worden weergegeven). Zie IPAddress.MapToIPv6-. Bepaal of deze indeling is vereist door de HttpContext.Connection.RemoteIpAddresste bekijken.

De standaardwaarde is een IList<IPAddress> met één vermelding voor IPAddress.IPv6Loopback.
OriginalForHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalForHeaderName.

De standaardwaarde is X-Original-For.
OriginalHostHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalHostHeaderName.

De standaardwaarde is X-Original-Host.
OriginalProtoHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalProtoHeaderName.

De standaardwaarde is X-Original-Proto.
RequireHeaderSymmetry Zorg ervoor dat het aantal headerwaarden in overeenstemming is tussen de ForwardedHeadersOptions.ForwardedHeaders die worden verwerkt.

De standaardwaarde in ASP.NET Core 1.x is true. De standaardwaarde in ASP.NET Core 2.0 of hoger is false.

Scenarios en use cases

Wanneer het niet mogelijk is om doorgestuurde headers toe te voegen en alle aanvragen veilig zijn

In sommige gevallen is het misschien niet mogelijk om doorgestuurde headers toe te voegen aan de aanvragen die via proxy naar de app worden gestuurd. Als de proxy afdwingt dat alle openbare externe aanvragen HTTPS zijn, kan het schema handmatig worden ingesteld voordat u een willekeurig type middleware gebruikt:

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();

Deze code kan worden uitgeschakeld met een omgevingsvariabele of andere configuratie-instelling in een ontwikkel- of faseringsomgeving:

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();

Werken met padbasis en proxy's die het aanvraagpad wijzigen

Sommige proxy's geven het pad intact door, maar met een app-basispad dat moet worden verwijderd, zodat routering goed werkt. UsePathBaseExtensions.UsePathBase middleware splitst het pad in HttpRequest.Path en het basispad van de app in HttpRequest.PathBase.

Als /foo het basispad van de app is voor een proxypad dat als /foo/api/1wordt doorgegeven, stelt de middleware Request.PathBase in op /foo en Request.Path op /api/1 met de volgende opdracht:

app.UsePathBase("/foo");
// ...
app.UseRouting();

Notitie

Wanneer u WebApplication gebruikt (zie Migreren van ASP.NET Core in .NET 5 naar .NET 6), moet app.UseRouting worden aangeroepen na UsePathBase, zodat de middleware voor routering het gewijzigde pad kan observeren voordat overeenkomende routes worden gezocht. Anders worden routes vergeleken voordat UsePathBase het pad opnieuw wordt geschreven, zoals beschreven in ASP.NET Core middleware en routering in ASP.NET Core.

Het oorspronkelijke pad en de padbasis worden opnieuw toegepast wanneer de middleware opnieuw wordt aangeroepen in omgekeerde richting. Zie ASP.NET Core middleware voor meer informatie over de verwerkingsvolgorde van middleware.

Als de proxy het pad trimt (bijvoorbeeld het doorsturen van /foo/api/1 naar /api/1), herstelt u omleidingen en koppelingen door de eigenschap PathBase van de aanvraag in te stellen:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/foo");
    return next(context);
});

Als de proxy padgegevens toevoegt, verwijdert u een deel van het pad om omleidingen en koppelingen op te lossen met behulp van StartsWithSegments en wijst u deze toe aan de eigenschap Path:

app.Use((context, next) =>
{
    if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
    {
        context.Request.Path = remainder;
    }

    return next(context);
});

Configuratie voor een proxy die gebruikmaakt van verschillende headernamen

Als de proxy geen headers gebruikt met de naam X-Forwarded-For en X-Forwarded-Proto om het proxyadres/de poort en de oorspronkelijke schemagegevens door te sturen, stelt u de opties voor ForwardedForHeaderName en ForwardedProtoHeaderName in zodat deze overeenkomen met de headernamen die door de proxy worden gebruikt:

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();

Het schema doorsturen voor Linux- en niet-IIS-reverse proxy's

Apps die UseHttpsRedirection aanroepen en UseHsts een site in een oneindige lus plaatsen als deze worden geïmplementeerd op een Azure Linux App Service, virtuele Azure Linux-machine (VM) of achter een andere omgekeerde proxy dan IIS. De omgekeerde proxy beëindigt TLS en Kestrel wordt niet op de hoogte gesteld van het juiste aanvraagschema. OAuth en OIDC mislukken ook in deze configuratie omdat ze onjuiste omleidingen genereren. UseIISIntegration voegt middleware voor doorgestuurde headers toe en configureert deze wanneer deze achter IIS wordt uitgevoerd, maar er is geen vergelijkbare automatische configuratie voor Linux (Apache- of Nginx-integratie).

Als u in niet-IIS-scenario's het protocol via de proxy wilt doorsturen, schakelt u de Forwarded Headers-middleware in door ASPNETCORE_FORWARDEDHEADERS_ENABLED in te stellen op true. Waarschuwing: deze vlag maakt gebruik van instellingen die zijn ontworpen voor cloudomgevingen en schakelt functies zoals de KnownProxies option niet in om te beperken vanaf welke IP-doorstuurservers worden geaccepteerd.

Certificaat doorsturen

Azuur

Zie Wederzijdse TLS-verificatie configureren voor Azure App Serviceom Azure App Service te configureren voor het doorsturen van certificaten. De volgende richtlijnen hebben betrekking op het configureren van de ASP.NET Core-app.

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 webproxy's

Als een proxy wordt gebruikt die niet IIS of ARR (Application Request Routing) van Azure App Service is, configureert u de proxy om het certificaat dat is ontvangen in een HTTP-header door te sturen.

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();

Als de proxy het certificaat niet base64-codeert, zoals bij Nginx het geval is, zet de optie HeaderConverter aan. Bekijk het volgende voorbeeld:

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();

Problemen oplossen

Wanneer headers niet worden doorgestuurd zoals verwacht, schakelt u debug niveau in logboekregistratie en logboekregistratie van HTTP-aanvragen. UseHttpLogging moet na UseForwardedHeadersworden aangeroepen:

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();

Als er meerdere waarden in een bepaalde header staan, verwerkt de Forwarded Headers-middleware headers in omgekeerde volgorde van rechts naar links. De standaard ForwardLimit is 1 (één), dus alleen de meest rechtse waarde uit de headers wordt verwerkt, tenzij de waarde van ForwardLimit wordt verhoogd.

Het oorspronkelijke externe IP-adres van de aanvraag moet overeenkomen met een vermelding in de KnownProxies of KnownNetworks lijsten voordat doorgestuurde headers worden verwerkt. Hierdoor wordt adresvervalsing van headers beperkt door doorstuurservers van niet-vertrouwde proxy's niet te accepteren. Wanneer een onbekende proxy wordt gedetecteerd, geeft logboekregistratie het adres van de proxy aan:

September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321

In het voorgaande voorbeeld is 10.0.0.100 een proxyserver. Als de server een vertrouwde proxy is, voegt u het IP-adres van de server toe aan KnownProxiesof voegt u een vertrouwd netwerk toe aan KnownNetworks. Zie de sectie middlewareopties voor doorgestuurde headers voor meer informatie.

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();

Als u de logboeken wilt weergeven, voegt u "Microsoft.AspNetCore.HttpLogging": "Information" toe aan het appsettings.Development.json-bestand:

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.HttpLogging": "Information"
    }
  }
}

Belangrijk

Alleen vertrouwde proxy's en netwerken toestaan headers door te sturen. Anders zijn IP-spoofing-aanvallen mogelijk.

Aanvullende informatiebronnen

In de aanbevolen configuratie voor ASP.NET Core wordt de app gehost met behulp van IIS/ASP.NET Core Module, Nginx of Apache. Proxyservers, load balancers en andere netwerkapparaten verhullen vaak informatie over de aanvraag voordat deze de app bereikt:

  • Wanneer HTTPS-aanvragen via HTTP worden geproxied, gaat het oorspronkelijke schema (HTTPS) verloren en moet het worden doorgestuurd in een header.
  • Omdat een app een aanvraag van de proxy ontvangt en niet de werkelijke bron op internet of het bedrijfsnetwerk, moet het ip-adres van de oorspronkelijke client ook worden doorgestuurd in een header.

Deze informatie kan belangrijk zijn bij het verwerken van aanvragen, bijvoorbeeld bij omleidingen, verificatie, het genereren van koppelingen, beleidsevaluatie en clientgeolocatie.

Doorgestuurde headers

Standaard sturen proxy's informatie door in HTTP-headers.

Koptekst Beschrijving
X-Forwarded-For Bevat informatie over de client die de aanvraag en volgende proxy's heeft geïnitieerd in een keten van proxy's. Deze parameter kan IP-adressen bevatten (en, optioneel, poortnummers). In een keten van proxyservers geeft de eerste parameter de client aan waar de aanvraag voor het eerst is gedaan. Verdere proxy-id's volgen. De laatste proxy in de keten staat niet in de lijst met parameters. Het IP-adres van de laatste proxy en eventueel een poortnummer zijn beschikbaar als het externe IP-adres op de transportlaag.
X-Forwarded-Proto De waarde van het oorspronkelijke schema (HTTP/HTTPS). De waarde kan ook een lijst met schema's zijn als de aanvraag meerdere proxy's heeft doorlopen.
X-Forwarded-Host De oorspronkelijke waarde van het veld Hostheader. Meestal wijzigen proxy's de Host-header niet. Zie Microsoft Beveiliging Advisory CVE-2018-0787 voor informatie over een beveiligingsprobleem met uitbreiding van bevoegdheden dat van invloed is op systemen waarop de proxy hostheaders niet valideert of beperkt tot bekende goede waarden.

De middleware voor doorgestuurde headers (ForwardedHeadersMiddleware) leest deze headers en vult de bijbehorende velden op HttpContext in.

De middleware wordt bijgewerkt:

Zie dit GitHub-probleemvoor meer informatie over het voorgaande.

De standaardinstellingen van de middleware voor doorgestuurde headers kunnen worden geconfigureerd. Voor de standaardinstellingen:

  • Er is slechts één proxy tussen de app en de bron van de aanvragen.
  • Alleen loopback-adressen zijn geconfigureerd voor bekende proxy's en bekende netwerken.
  • De doorgestuurde headers hebben de naam X-Forwarded-For en X-Forwarded-Proto.
  • De ForwardedHeaders waarde is ForwardedHeaders.None, de gewenste doorstuurservers moeten hier worden ingesteld om de middleware in te schakelen.

Niet alle netwerkapparaten voegen de X-Forwarded-For en X-Forwarded-Proto headers toe zonder extra configuratie. Raadpleeg de richtlijnen van de fabrikant van uw apparaat als opgegeven aanvragen deze headers niet bevatten wanneer ze de app bereiken. Als het apparaat andere headernamen gebruikt dan X-Forwarded-For en X-Forwarded-Proto, stelt u de ForwardedForHeaderName- en ForwardedProtoHeaderName-opties in zodat deze overeenkomen met de headernamen die door het apparaat worden gebruikt. Zie de middlewareopties voor doorgestuurde headers en configuratie voor een proxy die gebruikmaakt van verschillende headernamen voor meer informatie.

IIS/IIS Express en ASP.NET Core-module

IIS-integratiemiddleware schakelt standaard middleware voor doorgestuurde headers in wanneer de app out-of-process wordt gehost achter IIS en de ASP.NET Core Module. Middleware voor doorgestuurde headers wordt geactiveerd zodat deze als eerste wordt uitgevoerd in de middlewarepijplijn, met een beperkte configuratie die specifiek is voor de ASP.NET Core-module vanwege zorgen over het vertrouwen in doorgestuurde headers (bijvoorbeeld IP-spoofing). De middleware is geconfigureerd om de X-Forwarded-For en X-Forwarded-Proto headers door te sturen en is beperkt tot één localhost-proxy. Als aanvullende configuratie nodig is, raadpleeg dan de opties voor de middleware voor doorgestuurde headers.

Andere scenario's voor proxyservers en load balancer

Buiten het gebruik van IIS-integratie bij het hosten van out-of-process is doorgestuurde headers middleware niet standaard ingeschakeld. Middleware voor doorgestuurde headers moet zijn ingeschakeld voor een app voor het verwerken van doorgestuurde headers met UseForwardedHeaders. Nadat u de middleware hebt ingeschakeld en er geen ForwardedHeadersOptions zijn opgegeven voor de middleware, worden standaard ForwardedHeadersOptions.ForwardedHeaders ingesteld op ForwardedHeaders.None.

Configureer de middleware met ForwardedHeadersOptions om de X-Forwarded-For en X-Forwarded-Proto headers in Startup.ConfigureServicesdoor te sturen.

Volgorde van de middleware voor doorgestuurde headers

Middleware voor doorgestuurde headers moet worden uitgevoerd voordat andere middleware wordt uitgevoerd. Deze volgorde zorgt ervoor dat de middleware die afhankelijk is van informatie over doorgestuurde headers de headerwaarden kan gebruiken voor verwerking. De middleware voor doorgestuurde headers kan na diagnostiek en foutafhandeling worden uitgevoerd, maar moet worden uitgevoerd voordat UseHsts wordt aangeroepen:

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?}");
        });
    }
}

U kunt ook UseForwardedHeaders aanroepen vóór diagnose.

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?}");
    });
}

Notitie

Als er geen ForwardedHeadersOptions zijn opgegeven in Startup.ConfigureServices of rechtstreeks bij de extensiemethode met UseForwardedHeaders, worden de standaardheaders die moeten worden doorgestuurd ForwardedHeaders.None. De eigenschap ForwardedHeaders moet worden geconfigureerd met de headers die doorgestuurd moeten worden.

Nginx-configuratie

Zie X-Forwarded-Forom de headers voor X-Forwarded-Proto en door te sturen.

Apache-configuratie

X-Forwarded-For wordt automatisch toegevoegd (zie Apache Module mod_proxy: Headers voor omgekeerde proxyaanvragen).

Opties voor doorgestuurde headers-middleware

ForwardedHeadersOptions het gedrag van de middleware voor doorgestuurde headers bepalen. In het volgende voorbeeld worden de standaardwaarden gewijzigd:

  • Beperk het aantal vermeldingen in de doorgestuurde headers tot 2.
  • Voeg een bekend proxyadres van 127.0.10.1toe.
  • Wijzig de naam van de doorgestuurde header van de standaard-X-Forwarded-For in X-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";
});
Optie Beschrijving
AllowedHosts Hiermee beperkt u hosts door de X-Forwarded-Host header tot de opgegeven waarden.
  • Waarden worden vergeleken met ordinaal-ignore-case.
  • Poortnummers moeten worden uitgesloten.
  • Als de lijst leeg is, zijn alle hosts toegestaan.
  • Een jokerteken op het hoogste niveau * staat alle niet-lege hosts toe.
  • Jokertekens voor subdomeinen zijn toegestaan, maar komen niet overeen met het hoofddomein. *.contoso.com komt bijvoorbeeld overeen met het subdomein foo.contoso.com maar niet het hoofddomein contoso.com.
  • Unicode-hostnamen zijn toegestaan, maar worden geconverteerd naar Punycode- voor het vergelijken.
  • IPv6-adressen moeten begrenzingshaken bevatten en zich in conventionele vorm bevinden (bijvoorbeeld [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). IPv6-adressen zijn niet speciaal bedoeld om te controleren op logische gelijkheid tussen verschillende indelingen en er wordt geen canonicalisatie uitgevoerd.
  • Het niet beperken van de toegestane hosts kan een cyberaanvaller in staat stellen om koppelingen te spoofen die door de service worden gegenereerd.
De standaardwaarde is een lege IList<string>.
ForwardedHeaders Hiermee wordt bepaald welke doorstuurders moeten worden verwerkt. Zie de ForwardedHeaders Enum- voor de lijst met velden die van toepassing zijn. Typische waarden die aan deze eigenschap zijn toegewezen, worden ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

De standaardwaarde is ForwardedHeaders.None.
ForwardedForHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de koptekst die is opgegeven door ForwardedHeadersDefaults.XForwardedForHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-For header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-For.
ForwardedHostHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XForwardedHostHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-Host header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-Host.
ForwardedProtoHeaderName Gebruik de header die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XForwardedProtoHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-Proto header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-Proto.
ForwardedPrefixHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XForwardedPrefixHeaderName. Deze optie wordt gebruikt wanneer de proxy/doorstuurserver de X-Forwarded-Prefix header niet gebruikt, maar een andere header gebruikt om de informatie door te sturen.

De standaardwaarde is X-Forwarded-Prefix.
ForwardLimit Hiermee beperkt u het aantal vermeldingen in de kopteksten die worden verwerkt. Ingesteld op null om de limiet uit te schakelen, maar dit moet alleen worden gedaan als KnownProxies of KnownNetworks zijn geconfigureerd. Het instellen van een niet-null waarde is een voorzorgsmaatregel (maar geen garantie) om te beschermen tegen onjuist geconfigureerde proxy's en schadelijke aanvragen die afkomstig zijn van side-channels in het netwerk.

De middleware Forwarded Headers verwerkt de headers in omgekeerde volgorde, van rechts naar links. Als de standaardwaarde (1) wordt gebruikt, wordt alleen de meest rechtse waarde van de headers verwerkt, tenzij de waarde van ForwardLimit wordt verhoogd.

De standaardwaarde is 1.
KnownNetworks Adresbereiken van bekende netwerken waaruit doorgestuurde headers moeten worden geaccepteerd. Ip-bereiken opgeven met cidr-notatie (Classless Interdomain Routing).

Als de server sockets met dubbele modus gebruikt, worden IPv4-adressen opgegeven in een IPv6-indeling (bijvoorbeeld 10.0.0.1 in IPv4 die als ::ffff:10.0.0.1in IPv6 worden weergegeven). Zie IPAddress.MapToIPv6-. Bepaal of deze indeling is vereist door de HttpContext.Connection.RemoteIpAddresste bekijken.

De standaardwaarde is een IList<IPNetwork> met één vermelding voor new IPNetwork(IPAddress.Loopback, 8).
KnownProxies Adressen van bekende proxy's waaruit doorgestuurde headers moeten worden geaccepteerd. Gebruik KnownProxies om exacte IP-adresovereenkomsten op te geven.

Als de server sockets met dubbele modus gebruikt, worden IPv4-adressen opgegeven in een IPv6-indeling (bijvoorbeeld 10.0.0.1 in IPv4 die als ::ffff:10.0.0.1in IPv6 worden weergegeven). Zie IPAddress.MapToIPv6-. Bepaal of deze indeling is vereist door de HttpContext.Connection.RemoteIpAddresste bekijken.

De standaardwaarde is een IList<IPAddress> met één vermelding voor IPAddress.IPv6Loopback.
OriginalForHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalForHeaderName.

De standaardwaarde is X-Original-For.
OriginalHostHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalHostHeaderName.

De standaardwaarde is X-Original-Host.
OriginalProtoHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalProtoHeaderName.

De standaardwaarde is X-Original-Proto.
OriginalPrefixHeaderName Gebruik de koptekst die is opgegeven door deze eigenschap in plaats van de header die is opgegeven door ForwardedHeadersDefaults.XOriginalPrefixHeaderName.

De standaardwaarde is X-Original-Prefix.
RequireHeaderSymmetry Zorg ervoor dat het aantal headerwaarden in overeenstemming is tussen de ForwardedHeadersOptions.ForwardedHeaders die worden verwerkt.

De standaardwaarde in ASP.NET Core 1.x is true. De standaardwaarde in ASP.NET Core 2.0 of hoger is false.

Scenarios en use cases

Wanneer het niet mogelijk is om doorgestuurde headers toe te voegen en alle aanvragen veilig zijn

In sommige gevallen is het misschien niet mogelijk om doorgestuurde headers toe te voegen aan de aanvragen die via proxy naar de app worden gestuurd. Als de proxy afdwingt dat alle openbare externe aanvragen HTTPS zijn, kan het schema handmatig worden ingesteld in Startup.Configure voordat u een willekeurig type middleware gebruikt:

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next();
});

Deze code kan worden uitgeschakeld met een omgevingsvariabele of andere configuratie-instelling in een ontwikkel- of faseringsomgeving.

Omgaan met padbasis en proxy's die het aanvraagpad wijzigen

Sommige proxy's geven het pad intact door, maar met een app-basispad dat moet worden verwijderd, zodat routering goed werkt. UsePathBaseExtensions.UsePathBase middleware splitst het pad in HttpRequest.Path en het basispad van de app in HttpRequest.PathBase.

Als /foo het basispad van de app is voor een proxypad dat als /foo/api/1wordt doorgegeven, stelt de middleware Request.PathBase in op /foo en Request.Path op /api/1 met de volgende opdracht:

app.UsePathBase("/foo");

Het oorspronkelijke pad en de padbasis worden opnieuw toegepast wanneer de middleware opnieuw wordt aangeroepen in omgekeerde richting. Zie ASP.NET Core middleware voor meer informatie over de verwerkingsvolgorde van middleware.

Als de proxy het pad trimt (bijvoorbeeld het doorsturen van /foo/api/1 naar /api/1), herstelt u omleidingen en koppelingen door de eigenschap PathBase van de aanvraag in te stellen:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/foo");
    return next();
});

Als de proxy padgegevens toevoegt, verwijdert u een deel van het pad om omleidingen en koppelingen op te lossen met behulp van StartsWithSegments en wijst u deze toe aan de eigenschap Path:

app.Use((context, next) =>
{
    if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
    {
        context.Request.Path = remainder;
    }

    return next();
});

Configuratie voor een proxy die gebruikmaakt van verschillende headernamen

Als de proxy geen headers gebruikt met de naam X-Forwarded-For en X-Forwarded-Proto om het proxyadres/de poort en de oorspronkelijke schemagegevens door te sturen, stelt u de opties voor ForwardedForHeaderName en ForwardedProtoHeaderName in zodat deze overeenkomen met de headernamen die door de proxy worden gebruikt:

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";
});

Het schema doorsturen voor Linux- en niet-IIS-reverse proxy's

Apps die UseHttpsRedirection aanroepen en UseHsts een site in een oneindige lus plaatsen als deze worden geïmplementeerd op een Azure Linux App Service, virtuele Azure Linux-machine (VM) of achter een andere omgekeerde proxy dan IIS. De omgekeerde proxy beëindigt TLS en Kestrel wordt niet op de hoogte gesteld van het juiste aanvraagschema. OAuth en OIDC mislukken ook in deze configuratie omdat ze onjuiste omleidingen genereren. UseIISIntegration voegt middleware voor doorgestuurde headers toe en configureert deze wanneer deze achter IIS wordt uitgevoerd, maar er is geen vergelijkbare automatische configuratie voor Linux (integratie met Apache of Nginx).

Als u het schema vanuit de proxy wilt doorsturen in niet-IIS-scenario's, voegt u doorgestuurde headers-middleware toe en configureert u deze. Gebruik in Startup.ConfigureServicesde volgende 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();
    });
}

Certificaat doorsturen

Azuur

Zie Wederzijdse TLS-verificatie configureren voor Azure App Serviceom Azure App Service te configureren voor het doorsturen van certificaten. De volgende richtlijnen hebben betrekking op het configureren van de ASP.NET Core-app.

Voeg in Startup.Configurede volgende code toe voordat de aanroep naar app.UseAuthentication();:

app.UseCertificateForwarding();

Configureer middleware voor het doorsturen van certificaten om de headernaam op te geven die Azure gebruikt. Voeg in Startup.ConfigureServicesde volgende code toe om de header te configureren waaruit de middleware een certificaat bouwt:

services.AddCertificateForwarding(options =>
    options.CertificateHeader = "X-ARR-ClientCert");

Andere webproxy's

Als een proxy wordt gebruikt die niet IIS of ARR (Application Request Routing) van Azure App Service is, configureert u de proxy om het certificaat dat is ontvangen in een HTTP-header door te sturen. Voeg in Startup.Configurede volgende code toe voordat de aanroep naar app.UseAuthentication();:

app.UseCertificateForwarding();

Configureer de middleware voor het doorsturen van certificaten om de headernaam op te geven. Voeg in Startup.ConfigureServicesde volgende code toe om de header te configureren waaruit de middleware een certificaat bouwt:

services.AddCertificateForwarding(options =>
    options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");

Als de proxy het certificaat niet base64-codeert (zoals het geval is met Nginx), stelt u de optie HeaderConverter in. Bekijk het volgende voorbeeld 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;
    }
});

Problemen oplossen

Wanneer headers niet worden doorgestuurd zoals verwacht, schakelt u logboekregistratie in. Als de logboeken onvoldoende informatie bevatten om het probleem op te lossen, inventariseert u de aanvraagheaders die door de server zijn ontvangen. Gebruik inline-middleware om aanvraagheaders naar een app-antwoord te schrijven of de headers te registreren.

Als u de headers naar het antwoord van de app wilt schrijven, plaatst u de volgende terminal inline-middleware direct na de aanroep naar 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}");
});

U kunt naar logboeken schrijven in plaats van de hoofdtekst van het antwoord. Door naar logboeken te schrijven, kan de site normaal functioneren tijdens het debuggen.

Logboeken schrijven in plaats van naar de hoofdtekst van het antwoord:

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();
});

Wanneer deze worden verwerkt, worden X-Forwarded-{For|Proto|Host|Prefix} waarden verplaatst naar X-Original-{For|Proto|Host|Prefix}. Als er meerdere waarden in een bepaalde header staan, verwerkt de middleware voor doorgestuurde headers de headers in omgekeerde volgorde, van rechts naar links. De standaard ForwardLimit is 1 (één), dus alleen de meest rechtse waarde uit de headers wordt verwerkt, tenzij de waarde van ForwardLimit wordt verhoogd.

Het oorspronkelijke externe IP-adres van de aanvraag moet overeenkomen met een vermelding in de KnownProxies of KnownNetworks lijsten voordat doorgestuurde headers worden verwerkt. Hierdoor wordt adresvervalsing van headers beperkt door doorstuurservers van niet-vertrouwde proxy's niet te accepteren. Wanneer een onbekende proxy wordt gedetecteerd, geeft logboekregistratie het adres van de proxy aan:

September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321

In het voorgaande voorbeeld is 10.0.0.100 een proxyserver. Als de server een vertrouwde proxy is, voegt u het IP-adres van de server toe aan KnownProxies (of voegt u een vertrouwd netwerk toe aan KnownNetworks) in Startup.ConfigureServices. Zie de sectie middlewareopties voor doorgestuurde headers voor meer informatie.

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

Belangrijk

Alleen vertrouwde proxy's en netwerken toestaan headers door te sturen. Anders zijn IP-spoofing-aanvallen mogelijk.

Aanvullende informatiebronnen