Konfigurowanie ASP.NET Core do pracy z serwerami proxy i modułami równoważenia obciążenia

Przez Chris Ross

W zalecanej konfiguracji dla ASP.NET Core aplikacja jest hostowana przy użyciu modułu ASP.NET Core (ANCM) dla usług IIS, Nginx lub Apache. Serwery proxy, moduły równoważenia obciążenia i inne urządzenia sieciowe często niejasne informacje o żądaniu przed dotarciem do aplikacji:

  • Gdy żądania HTTPS są proxied za pośrednictwem protokołu HTTP, oryginalny schemat (HTTPS) zostanie utracony i musi zostać przesłany dalej w nagłówku.
  • Ponieważ aplikacja odbiera żądanie od serwera proxy, a nie jego prawdziwe źródło w Internecie lub sieci firmowej, źródłowy adres IP klienta musi być również przekazywany w nagłówku.

Te informacje mogą być ważne w przetwarzaniu żądań, na przykład w przypadku przekierowań, uwierzytelniania, generowania linków, oceny zasad i geolokalizacji klienta.

Nagłówki przekazywane

Zgodnie z konwencją serwery proxy przekazują informacje w nagłówkach HTTP.

Nagłówek Opis
X-Forwarded-For (XFF) Przechowuje informacje o kliencie, który zainicjował żądanie i kolejne serwery proxy w łańcuchu serwerów proxy. Ten parametr może zawierać adresy IP i opcjonalnie numery portów. W łańcuchu serwerów proxy pierwszy parametr wskazuje klienta, w którym zostało wykonane pierwsze żądanie. Kolejne identyfikatory serwera proxy są następujące. Ostatni serwer proxy w łańcuchu nie znajduje się na liście parametrów. Adres IP ostatniego serwera proxy i opcjonalnie numer portu są dostępne jako zdalny adres IP w warstwie transportu.
X-Forwarded-Proto (XFP) Wartość schematu źródłowego, HTTP lub HTTPS. Wartość może być również listą schematów, jeśli żądanie przejechało wiele serwerów proxy.
X-Forwarded-Host (XFH) Oryginalna wartość pola Nagłówek hosta. Zwykle serwery proxy nie modyfikują nagłówka Hosta. Zobacz Biuletyn zabezpieczeń firmy Microsoft CVE-2018-0787, aby uzyskać informacje na temat luki w zabezpieczeniach podniesienia uprawnień, która ma wpływ na systemy, w których serwer proxy nie weryfikuje ani nie ogranicza nagłówków hosta do znanych dobrych wartości.

Oprogramowanie pośredniczące Nagłówki przekazane, ForwardedHeadersMiddleware, odczytuje te nagłówki i wypełnia skojarzone pola w .HttpContext

Oprogramowanie pośredniczące aktualizuje:

Aby uzyskać więcej informacji na temat powyższego, zobacz ten GitHub problem.

Ustawienia domyślne oprogramowania pośredniczącego nagłówków przekazywane można skonfigurować. Dla ustawień domyślnych:

  • Istnieje tylko jeden serwer proxy między aplikacją a źródłem żądań.
  • Tylko adresy sprzężenia zwrotnego są skonfigurowane dla znanych serwerów proxy i znanych sieci.
  • Nagłówki przekazywane są nazwane X-Forwarded-For i X-Forwarded-Proto.
  • Wartość ForwardedHeaders to ForwardedHeaders.None, żądane usługi przesyłania dalej należy ustawić tutaj, aby włączyć oprogramowanie pośredniczące.

Nie wszystkie urządzenia sieciowe dodają X-Forwarded-For nagłówki i X-Forwarded-Proto bez dodatkowej konfiguracji. Zapoznaj się ze wskazówkami producenta urządzenia, jeśli żądania proxied nie zawierają tych nagłówków po dotarciu do aplikacji. Jeśli urządzenie używa różnych nazw nagłówków niż X-Forwarded-For i X-Forwarded-Proto, ustaw ForwardedForHeaderName opcje i ForwardedProtoHeaderName , aby dopasować nazwy nagłówków używane przez urządzenie. Aby uzyskać więcej informacji, zobacz Opcje oprogramowania pośredniczącego przekazywane nagłówki i Konfiguracja serwera proxy, który używa różnych nazw nagłówków.

Iis/IIS Express i moduł ASP.NET Core

Oprogramowanie pośredniczące nagłówków przekazywanych jest domyślnie włączone przez oprogramowanie pośredniczące integracji usług IIS, gdy aplikacja jest hostowana poza procesem za usługami IIS i modułem ASP.NET Core (ANCM) dla usług IIS. Oprogramowanie pośredniczące nagłówków przekazywanych jest aktywowane w celu pierwszego uruchomienia w potoku oprogramowania pośredniczącego z ograniczoną konfiguracją specyficzną dla modułu ASP.NET Core. Konfiguracja ograniczona jest spowodowana obawami dotyczącymi zaufania z przekierowanymi nagłówkami, na przykład fałszowaniem adresów IP. Oprogramowanie pośredniczące jest skonfigurowane do przekazywania X-Forwarded-For nagłówków i X-Forwarded-Proto i jest ograniczone do jednego serwera proxy hosta lokalnego. Jeśli wymagana jest dodatkowa konfiguracja, zobacz Opcje oprogramowania pośredniczącego Nagłówki przekazywane.

Inne scenariusze serwera proxy i modułu równoważenia obciążenia

Poza używaniem integracji z usługami IIS podczas hostowania poza procesem oprogramowanie pośredniczące nagłówków przekazywanych nie jest domyślnie włączone. Oprogramowanie pośredniczące nagłówków przekazywanych musi być włączone, aby aplikacja przetwarzała nagłówki przekazywane za pomocą polecenia UseForwardedHeaders. Po włączeniu oprogramowania pośredniczącego, jeśli nie ForwardedHeadersOptions określono żadnego oprogramowania pośredniczącego, domyślna wartość ForwardedHeadersOptions.ForwardedHeaders to ForwardedHeaders.None.

Skonfiguruj oprogramowanie pośredniczące za pomocą ForwardedHeadersOptions polecenia , aby przekazać X-Forwarded-For dalej nagłówki i X-Forwarded-Proto .

Kolejność oprogramowania pośredniczącego nagłówków przesłanych dalej

Oprogramowanie pośredniczące nagłówków przekazywane powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Ta kolejność gwarantuje, że oprogramowanie pośredniczące uzależnione od przekazanych informacji nagłówków może używać wartości nagłówków do przetwarzania. Oprogramowanie pośredniczące nagłówków przekazywanych może być uruchamiane po diagnostyce i obsłudze błędów, ale należy je uruchomić przed wywołaniem polecenia UseHsts:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseForwardedHeaders();
    app.UseHsts();
}
else
{
    app.UseDeveloperExceptionPage();
    app.UseForwardedHeaders();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Możesz też wywołać wywołanie UseForwardedHeaders przed diagnostyką:

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

Uwaga

Jeśli nie określono ani nie ForwardedHeadersOptions zastosowano bezpośrednio do metody rozszerzenia za pomocą UseForwardedHeaderspolecenia , domyślne nagłówki do przodu to ForwardedHeaders.None. Właściwość ForwardedHeaders musi być skonfigurowana przy użyciu nagłówków do przodu.

Konfiguracja serwera Nginx

Aby przekazać X-Forwarded-For dalej nagłówki iX-Forwarded-Proto, zobacz Host ASP.NET Core w systemie Linux przy użyciu serwera Nginx. Aby uzyskać więcej informacji, zobacz NGINX: Using the Forwarded header (Używanie nagłówka Przekazane).

Konfiguracja platformy Apache

X-Forwarded-For jest dodawany automatycznie. Aby uzyskać więcej informacji, zobacz Apache Module mod_proxy: Reverse Proxy Request Headers (Odwrotne nagłówki żądań serwera proxy). Aby uzyskać informacje na temat przekazywania nagłówkaX-Forwarded-Proto, zobacz Host ASP.NET Core w systemie Linux przy użyciu platformy Apache.

Opcje oprogramowania pośredniczącego nagłówków przekazanych

ForwardedHeadersOptions kontrolować zachowanie oprogramowania pośredniczącego Nagłówki przekazywane. Poniższy przykład zmienia wartości domyślne:

  • Ogranicza liczbę wpisów w przekazanych nagłówkach do 2.
  • Dodaje znany adres serwera proxy .127.0.10.1
  • Zmienia nazwę nagłówka przekazanego z domyślnej X-Forwarded-For na 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();
Opcja Opis
AllowedHosts Ogranicza hosty według nagłówka X-Forwarded-Host do podanych wartości.
  • Wartości są porównywane przy użyciu porządkowego przypadku ignoruj wielkość liter.
  • Numery portów muszą być wykluczone.
  • Jeśli lista jest pusta, wszystkie hosty są dozwolone.
  • Symbol wieloznaczny * najwyższego poziomu zezwala na wszystkie niepuste hosty.
  • Symbole wieloznaczne poddomeny są dozwolone, ale nie są zgodne z domeną główną. Na przykład pasuje do poddomenyfoo.contoso.com, *.contoso.com ale nie domeny contoso.comgłównej .
  • Nazwy hostów Unicode są dozwolone, ale są konwertowane na Punycode w celu dopasowania.
  • Adresy IPv6 muszą zawierać nawiasy ograniczenia i być w formie konwencjonalnej (na przykład [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). Adresy IPv6 nie są specjalne, aby sprawdzić równość logiczną między różnymi formatami, a nie jest wykonywana kanonizacja.
  • Nie można ograniczyć dozwolonych hostów, aby umożliwić osobie atakującej fałszowanie linków generowanych przez usługę.
Wartość domyślna to pusta IList<string>wartość .
ForwardedForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedForHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-For , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-For.
ForwardedHeaders Określa, które usługi przesyłania dalej powinny być przetwarzane. Aby uzyskać listę pól, które mają zastosowanie, zobacz wyliczenie ForwardedHeaders . Typowe wartości przypisane do tej właściwości to ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

Wartość domyślna to ForwardedHeaders.None.
ForwardedHostHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedHostHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-Host , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-Host.
ForwardedProtoHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedProtoHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-Proto , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-Proto.
ForwardLimit Ogranicza liczbę wpisów w przetworzonych nagłówkach. Ustaw wartość na wartość , aby null wyłączyć limit, ale należy to zrobić tylko w przypadku KnownProxies skonfigurowania lub KnownNetworks skonfigurowania. Ustawienie wartości innejnull niż jest środkiem ostrożności (ale nie gwarancją) w celu ochrony przed błędnie skonfigurowanymi serwerami proxy i złośliwymi żądaniami przychodzącymi z kanałów bocznych w sieci.

Nagłówki oprogramowania pośredniczącego przekazywane przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Jeśli jest używana wartość domyślna (1), tylko najbardziej właściwa wartość z nagłówków jest przetwarzana, chyba że wartość ForwardLimit jest zwiększona.

Wartość domyślna to 1.
KnownNetworks Zakresy adresów znanych sieci do akceptowania przekierowanych nagłówków. Podaj zakresy adresów IP przy użyciu notacji Routing międzydomenowy (CIDR) bez klas.

Jeśli serwer korzysta z gniazd w trybie podwójnym, adresy IPv4 są dostarczane w formacie IPv6 (na przykład 10.0.0.1 w przypadku protokołu IPv4 reprezentowanego w formacie IPv6 jako ::ffff:10.0.0.1). Zobacz IPAddress.MapToIPv6. Ustal, czy ten format jest wymagany, patrząc na httpContext.Connection.RemoteIpAddress.

Wartość domyślna IList><IPNetworkto pojedynczy wpis dla IPAddress.Loopbackelementu .
KnownProxies Adresy znanych serwerów proxy do akceptowania przekierowanych nagłówków. Służy KnownProxies do określania dokładnych dopasowań adresów IP.

Jeśli serwer korzysta z gniazd w trybie podwójnym, adresy IPv4 są dostarczane w formacie IPv6 (na przykład 10.0.0.1 w przypadku protokołu IPv4 reprezentowanego w formacie IPv6 jako ::ffff:10.0.0.1). Zobacz IPAddress.MapToIPv6. Ustal, czy ten format jest wymagany, patrząc na httpContext.Connection.RemoteIpAddress.

Wartość domyślna IList><IPAddressto pojedynczy wpis dla IPAddress.IPv6Loopbackelementu .
OriginalForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalForHeaderName.

Wartość domyślna to X-Original-For.
OriginalHostHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalHostHeaderName.

Wartość domyślna to X-Original-Host.
OriginalProtoHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalProtoHeaderName.

Wartość domyślna to X-Original-Proto.
RequireHeaderSymmetry Wymagaj synchronizacji wartości nagłówka między przetwarzanymi usługami ForwardedHeadersOptions.ForwardedHeaders .

Wartość domyślna w ASP.NET Core 1.x to true. Wartość domyślna w ASP.NET Core 2.0 lub nowsza to false.

Scenariusze i przypadki użycia

Gdy nie można dodać nagłówków przekazanych dalej, a wszystkie żądania są bezpieczne

W niektórych przypadkach dodanie nagłówków przesłanych dalej do aplikacji może nie być możliwe. Jeśli serwer proxy wymusza, że wszystkie publiczne żądania zewnętrzne to HTTPS, schemat można ustawić ręcznie przed użyciem dowolnego typu oprogramowania pośredniczącego:

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

Ten kod można wyłączyć za pomocą zmiennej środowiskowej lub innego ustawienia konfiguracji w środowisku programistycznym lub przejściowym:

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

Praca ze ścieżką bazową i serwerami proxy, które zmieniają ścieżkę żądania

Niektóre serwery proxy przechodzą ścieżkę nienaruszoną, ale ze ścieżką bazową aplikacji, która powinna zostać usunięta, aby routing działał prawidłowo. Oprogramowanie pośredniczące UsePathBaseExtensions.UsePathBase dzieli ścieżkę na httpRequest.Path i ścieżkę podstawową aplikacji na httpRequest.PathBase.

Jeśli /foo jest ścieżką podstawową aplikacji dla ścieżki serwera proxy przekazanej jako /foo/api/1, oprogramowanie pośredniczące ustawia Request.PathBase wartość /foo i Request.Path na /api/1 za pomocą następującego polecenia:

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

Uwaga

W przypadku korzystania WebApplication z programu (zobacz Migrowanie z ASP.NET Core 5.0 do 6.0), app.UseRouting należy wywołać metodę poUsePathBase, aby oprogramowanie pośredniczące routingu może obserwować zmodyfikowaną ścieżkę przed pasującymi trasami. W przeciwnym razie trasy są dopasowywane przed ponownym napisaniem UsePathBase ścieżki zgodnie z opisem w artykułach Ordering and Routingoprogramowania pośredniczącego.

Oryginalna ścieżka i podstawa ścieżki są ponownie stosować, gdy oprogramowanie pośredniczące jest wywoływane ponownie w odwrotnej kolejności. Aby uzyskać więcej informacji na temat przetwarzania zamówień oprogramowania pośredniczącego, zobacz ASP.NET Core Oprogramowanie pośredniczące.

Jeśli serwer proxy przycina ścieżkę (na przykład przekazywanie /foo/api/1 dalej do /api/1), napraw przekierowania i łącza, ustawiając właściwość PathBase żądania:

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

Jeśli serwer proxy dodaje dane ścieżki, odrzuć część ścieżki, aby naprawić przekierowania i linki, używając StartsWithSegments i przypisując do Path właściwości:

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

    return next(context);
});

Konfiguracja serwera proxy, który używa różnych nazw nagłówków

Jeśli serwer proxy nie używa nagłówków o nazwie X-Forwarded-For i X-Forwarded-Proto do przekazywania informacji o adresie/porcie serwera proxy i schematu źródłowego, ustaw ForwardedForHeaderName opcje i ForwardedProtoHeaderName zgodne z nazwami nagłówków używanymi przez serwer proxy:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedForHeaderName = "HeaderNamUsedByProxy_X-Forwarded-For_Header";
    options.ForwardedProtoHeaderName = "HeaderNamUsedByProxy_X-Forwarded-Proto_Header";
});

var app = builder.Build();

app.UseForwardedHeaders();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Przekazywanie schematu dla odwrotnych serwerów proxy systemu Linux i innych niż IIS

Aplikacje wywołujące UseHttpsRedirection i UseHsts umieszczające witrynę w nieskończonej pętli, jeśli zostały wdrożone w usłudze Azure Linux App Service, maszynie wirtualnej platformy Azure z systemem Linux lub za innym zwrotnym serwerem proxy oprócz usług IIS. Protokół TLS jest przerywany przez odwrotny serwer proxy i Kestrel nie jest świadomy prawidłowego schematu żądań. Uwierzytelnianie OAuth i OIDC również kończą się niepowodzeniem w tej konfiguracji, ponieważ generują nieprawidłowe przekierowania. UseIISIntegration dodaje i konfiguruje oprogramowanie pośredniczące Przekazywane nagłówki podczas uruchamiania za usługami IIS, ale nie ma zgodnej konfiguracji automatycznej dla systemu Linux (integracja apache lub Nginx).

Aby przekazać schemat z serwera proxy w scenariuszach innych niż USŁUGI IIS, dodaj i skonfiguruj oprogramowanie pośredniczące Nagłówki przekazywane. W Program.csprogramie użyj następującego kodu:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

if (string.Equals(
    Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"),
    "true", StringComparison.OrdinalIgnoreCase))
{
    builder.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();
    });
}

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

Przekazywanie certyfikatów

Azure

Aby skonfigurować Azure App Service na potrzeby przekazywania certyfikatów, zobacz Konfigurowanie wzajemnego uwierzytelniania PROTOKOŁU TLS dla Azure App Service. Poniższe wskazówki dotyczą konfigurowania aplikacji ASP.NET Core.

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

Inne serwery proxy sieci Web

Jeśli używany jest serwer proxy, który nie jest usługami IIS lub routingiem żądań aplikacji Azure App Service (ARR), skonfiguruj serwer proxy do przekazywania certyfikatu odebranego w nagłówku HTTP.

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

Jeśli serwer proxy nie jest zakodowany w formacie base64 certyfikatu, podobnie jak w przypadku serwera Nginx, ustaw HeaderConverter opcję. Rozpatrzmy następujący przykład:

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

Rozwiązywanie problemów

Gdy nagłówki nie są przekazywane zgodnie z oczekiwaniami, włącz debug rejestrowanie na poziomie i rejestrowanie żądań HTTP. UseHttpLoggingmusi być wywoływana po :UseForwardedHeaders

using Microsoft.AspNetCore.HttpLogging;
using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHttpLogging(options =>
{
    options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders;
});

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

var app = builder.Build();

app.UseForwardedHeaders();
app.UseHttpLogging();

app.Use(async (context, next) =>
{
    // Connection: RemoteIp
    app.Logger.LogInformation("Request RemoteIp: {RemoteIpAddress}",
        context.Connection.RemoteIpAddress);

    await next(context);
});

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Po przetworzeniu X-Forwarded-{For|Proto|Host} wartości są przenoszone do X-Original-{For|Proto|Host}. Jeśli w danym nagłówku znajduje się wiele wartości, nagłówki oprogramowania pośredniczącego przekazywane przetwarza w odwrotnej kolejności od prawej do lewej. Wartość domyślna ForwardLimit to 1 (jeden), więc tylko najbardziej właściwa wartość z nagłówków jest przetwarzana, chyba że wartość ForwardLimit jest zwiększona.

Oryginalny zdalny adres IP żądania musi być zgodny z wpisem na KnownProxies listach lub KnownNetworks przed przetworzeniem nagłówków przekazanych dalej. Ogranicza to fałszowanie nagłówków, nie akceptując usług przesyłania dalej z niezaufanych serwerów proxy. Po wykryciu nieznanego serwera proxy rejestrowanie wskazuje adres serwera proxy:

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

W poprzednim przykładzie 10.0.0.100 jest serwerem proxy. Jeśli serwer jest zaufanym serwerem proxy, dodaj adres IP serwera do KnownProxies, lub dodaj zaufaną sieć do KnownNetworks. Aby uzyskać więcej informacji, zobacz sekcję Opcje oprogramowania pośredniczącego Nagłówki przekazywane .

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

Aby wyświetlić dzienniki, dodaj "Microsoft.AspNetCore.HttpLogging": "Information" do appsettings.Development.json pliku:

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

Ważne

Zezwalaj tylko zaufanym serwerom proxy i sieciom na przekazywanie nagłówków. W przeciwnym razie możliwe są ataki fałszowania adresów IP .

Dodatkowe zasoby

W zalecanej konfiguracji dla ASP.NET Core aplikacja jest hostowana przy użyciu usług IIS/ASP.NET Core Module, Nginx lub Apache. Serwery proxy, moduły równoważenia obciążenia i inne urządzenia sieciowe często niejasne informacje o żądaniu przed dotarciem do aplikacji:

  • Gdy żądania HTTPS są proxied za pośrednictwem protokołu HTTP, oryginalny schemat (HTTPS) zostanie utracony i musi zostać przesłany dalej w nagłówku.
  • Ponieważ aplikacja odbiera żądanie od serwera proxy, a nie jego prawdziwe źródło w Internecie lub sieci firmowej, źródłowy adres IP klienta musi być również przekazywany w nagłówku.

Te informacje mogą być ważne w przetwarzaniu żądań, na przykład w przypadku przekierowań, uwierzytelniania, generowania linków, oceny zasad i geolokalizacji klienta.

Nagłówki przekazywane

Zgodnie z konwencją serwery proxy przekazują informacje w nagłówkach HTTP.

Nagłówek Opis
X-Forwarded-for Przechowuje informacje o kliencie, który zainicjował żądanie i kolejne serwery proxy w łańcuchu serwerów proxy. Ten parametr może zawierać adresy IP (i, opcjonalnie, numery portów). W łańcuchu serwerów proxy pierwszy parametr wskazuje klienta, w którym zostało wykonane pierwsze żądanie. Kolejne identyfikatory serwera proxy są następujące. Ostatni serwer proxy w łańcuchu nie znajduje się na liście parametrów. Adres IP ostatniego serwera proxy i opcjonalnie numer portu są dostępne jako zdalny adres IP w warstwie transportu.
X-Forwarded-Proto Wartość schematu źródłowego (HTTP/HTTPS). Wartość może być również listą schematów, jeśli żądanie przejechało wiele serwerów proxy.
X-Forwarded-Host Oryginalna wartość pola Nagłówek hosta. Zwykle serwery proxy nie modyfikują nagłówka Hosta. Zobacz Biuletyn zabezpieczeń firmy Microsoft CVE-2018-0787, aby uzyskać informacje na temat luki w zabezpieczeniach podniesienia uprawnień, która ma wpływ na systemy, w których serwer proxy nie weryfikuje ani nie ogranicza nagłówków hosta do znanych dobrych wartości.

Oprogramowanie pośredniczące przesyłania dalej nagłówków (ForwardedHeadersMiddleware), odczytuje te nagłówki i wypełnia skojarzone pola w obiekcie HttpContext.

Oprogramowanie pośredniczące aktualizuje:

Aby uzyskać więcej informacji na temat powyższego, zobacz ten GitHub problem.

Ustawienia domyślne oprogramowania pośredniczącego nagłówków przekazywane można skonfigurować. Dla ustawień domyślnych:

  • Istnieje tylko jeden serwer proxy między aplikacją a źródłem żądań.
  • Tylko adresy sprzężenia zwrotnego są skonfigurowane dla znanych serwerów proxy i znanych sieci.
  • Nagłówki przekazywane są nazwane X-Forwarded-For i X-Forwarded-Proto.
  • Wartość ForwardedHeaders to ForwardedHeaders.None, żądane usługi przesyłania dalej należy ustawić tutaj, aby włączyć oprogramowanie pośredniczące.

Nie wszystkie urządzenia sieciowe dodają X-Forwarded-For nagłówki i X-Forwarded-Proto bez dodatkowej konfiguracji. Zapoznaj się ze wskazówkami producenta urządzenia, jeśli żądania proxied nie zawierają tych nagłówków po dotarciu do aplikacji. Jeśli urządzenie używa różnych nazw nagłówków niż X-Forwarded-For i X-Forwarded-Proto, ustaw ForwardedForHeaderName opcje i ForwardedProtoHeaderName , aby dopasować nazwy nagłówków używane przez urządzenie. Aby uzyskać więcej informacji, zobacz Opcje oprogramowania pośredniczącego przekazywane nagłówki i Konfiguracja serwera proxy, który używa różnych nazw nagłówków.

Iis/IIS Express i moduł ASP.NET Core

Oprogramowanie pośredniczące nagłówków przekazywanych jest domyślnie włączone przez oprogramowanie pośredniczące integracji usług IIS, gdy aplikacja jest hostowana poza procesem za usługami IIS i modułem ASP.NET Core. Oprogramowanie pośredniczące nagłówków przekazywanych jest aktywowane w celu uruchomienia najpierw w potoku oprogramowania pośredniczącego z ograniczoną konfiguracją specyficzną dla modułu ASP.NET Core ze względu na obawy dotyczące zaufania z przekierowanymi nagłówkami (na przykład fałszowanie adresów IP). Oprogramowanie pośredniczące jest skonfigurowane do przekazywania X-Forwarded-For nagłówków i X-Forwarded-Proto i jest ograniczone do jednego serwera proxy hosta lokalnego. Jeśli wymagana jest dodatkowa konfiguracja, zobacz Opcje oprogramowania pośredniczącego Nagłówki przekazywane.

Inne scenariusze serwera proxy i modułu równoważenia obciążenia

Poza używaniem integracji z usługami IIS podczas hostowania poza procesem oprogramowanie pośredniczące nagłówków przekazywanych nie jest domyślnie włączone. Oprogramowanie pośredniczące nagłówków przekazywanych musi być włączone, aby aplikacja przetwarzała nagłówki przekazywane za pomocą polecenia UseForwardedHeaders. Po włączeniu oprogramowania pośredniczącego, jeśli nie ForwardedHeadersOptions określono żadnego oprogramowania pośredniczącego, domyślna wartość ForwardedHeadersOptions.ForwardedHeaders to ForwardedHeaders.None.

Skonfiguruj oprogramowanie pośredniczące za pomocą ForwardedHeadersOptions polecenia , aby przekazać X-Forwarded-For dalej nagłówki i X-Forwarded-Proto w pliku Startup.ConfigureServices.

Kolejność oprogramowania pośredniczącego nagłówków przesłanych dalej

Oprogramowanie pośredniczące nagłówków przekazywane powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Ta kolejność gwarantuje, że oprogramowanie pośredniczące uzależnione od przekazanych informacji nagłówków może używać wartości nagłówków do przetwarzania. Oprogramowanie pośredniczące nagłówków przekazywanych może być uruchamiane po diagnostyce i obsłudze błędów, ale należy je uruchomić przed wywołaniem polecenia UseHsts:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders =
                ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseForwardedHeaders();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseForwardedHeaders();
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

Możesz też wywołać wywołanie UseForwardedHeaders przed diagnostyką:

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

Uwaga

Jeśli w metodzie rozszerzenia nie ForwardedHeadersOptions określono Startup.ConfigureServices wartości lub bezpośrednio do metody rozszerzenia , UseForwardedHeadersdomyślne nagłówki do przodu to ForwardedHeaders.None. Właściwość ForwardedHeaders musi być skonfigurowana przy użyciu nagłówków do przodu.

Konfiguracja serwera Nginx

Aby przekazać X-Forwarded-For dalej nagłówki iX-Forwarded-Proto, zobacz Host ASP.NET Core w systemie Linux przy użyciu serwera Nginx. Aby uzyskać więcej informacji, zobacz NGINX: Using the Forwarded header (Używanie nagłówka Przekazane).

Konfiguracja platformy Apache

X-Forwarded-For program jest dodawany automatycznie (zobacz Apache Module mod_proxy: Reverse Proxy Request Headers (Zobacz temat Apache Module mod_proxy: Reverse Proxy Request Headers (Nagłówki zwrotnego żądania serwera proxy). Aby uzyskać informacje na temat przekazywania nagłówkaX-Forwarded-Proto, zobacz Host ASP.NET Core w systemie Linux przy użyciu platformy Apache.

Opcje oprogramowania pośredniczącego nagłówków przekazanych

ForwardedHeadersOptions kontrolować zachowanie oprogramowania pośredniczącego Nagłówki przekazywane. Poniższy przykład zmienia wartości domyślne:

  • Ogranicz liczbę wpisów w przekazanych nagłówkach do 2.
  • Dodaj znany adres serwera proxy .127.0.10.1
  • Zmień nazwę przekazanego nagłówka z domyślnej X-Forwarded-For na 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";
});
Opcja Opis
AllowedHosts Ogranicza hosty według nagłówka X-Forwarded-Host do podanych wartości.
  • Wartości są porównywane przy użyciu porządkowego przypadku ignoruj wielkość liter.
  • Numery portów muszą być wykluczone.
  • Jeśli lista jest pusta, wszystkie hosty są dozwolone.
  • Symbol wieloznaczny * najwyższego poziomu zezwala na wszystkie niepuste hosty.
  • Symbole wieloznaczne poddomeny są dozwolone, ale nie są zgodne z domeną główną. Na przykład pasuje do poddomenyfoo.contoso.com, *.contoso.com ale nie domeny contoso.comgłównej .
  • Nazwy hostów Unicode są dozwolone, ale są konwertowane na Punycode w celu dopasowania.
  • Adresy IPv6 muszą zawierać nawiasy ograniczenia i być w formie konwencjonalnej (na przykład [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). Adresy IPv6 nie są specjalne, aby sprawdzić równość logiczną między różnymi formatami, a nie jest wykonywana kanonizacja.
  • Nie można ograniczyć dozwolonych hostów, aby umożliwić osobie atakującej fałszowanie linków generowanych przez usługę.
Wartość domyślna to pusta IList<string>wartość .
ForwardedForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedForHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-For , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-For.
ForwardedHeaders Określa, które usługi przesyłania dalej powinny być przetwarzane. Aby uzyskać listę pól, które mają zastosowanie, zobacz wyliczenie ForwardedHeaders . Typowe wartości przypisane do tej właściwości to ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

Wartość domyślna to ForwardedHeaders.None.
ForwardedHostHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedHostHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-Host , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-Host.
ForwardedProtoHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XForwardedProtoHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka X-Forwarded-Proto , ale używa innego nagłówka do przekazywania informacji.

Wartość domyślna to X-Forwarded-Proto.
ForwardLimit Ogranicza liczbę wpisów w przetworzonych nagłówkach. Ustaw wartość na wartość , aby null wyłączyć limit, ale należy to zrobić tylko w przypadku KnownProxies skonfigurowania lub KnownNetworks skonfigurowania. Ustawienie wartości innejnull niż jest środkiem ostrożności (ale nie gwarancją) w celu ochrony przed błędnie skonfigurowanymi serwerami proxy i złośliwymi żądaniami przychodzącymi z kanałów bocznych w sieci.

Nagłówki oprogramowania pośredniczącego przekazywane przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Jeśli jest używana wartość domyślna (1), tylko najbardziej właściwa wartość z nagłówków jest przetwarzana, chyba że wartość ForwardLimit jest zwiększona.

Wartość domyślna to 1.
KnownNetworks Zakresy adresów znanych sieci do akceptowania przekierowanych nagłówków. Podaj zakresy adresów IP przy użyciu notacji Routing międzydomenowy (CIDR) bez klas.

Jeśli serwer korzysta z gniazd w trybie podwójnym, adresy IPv4 są dostarczane w formacie IPv6 (na przykład 10.0.0.1 w przypadku protokołu IPv4 reprezentowanego w formacie IPv6 jako ::ffff:10.0.0.1). Zobacz IPAddress.MapToIPv6. Ustal, czy ten format jest wymagany, patrząc na httpContext.Connection.RemoteIpAddress.

Wartość domyślna IList><IPNetworkto pojedynczy wpis dla IPAddress.Loopbackelementu .
KnownProxies Adresy znanych serwerów proxy do akceptowania przekierowanych nagłówków. Służy KnownProxies do określania dokładnych dopasowań adresów IP.

Jeśli serwer używa gniazd w trybie podwójnym, adresy IPv4 są dostarczane w formacie IPv6 (na przykład 10.0.0.1 w IPv4 reprezentowane w IPv6 jako ::ffff:10.0.0.1). Zobacz IPAddress.MapToIPv6. Ustal, czy ten format jest wymagany, patrząc na httpContext.Connection.RemoteIpAddress.

Wartość domyślna to pojedynczy IList><IPAddresswpis dla elementu .IPAddress.IPv6Loopback
OriginalForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalForHeaderName.

Wartość domyślna to X-Original-For.
OriginalHostHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalHostHeaderName.

Wartość domyślna to X-Original-Host.
OriginalProtoHeaderName Użyj nagłówka określonego przez tę właściwość zamiast określonego przez ForwardedHeadersDefaults.XOriginalProtoHeaderName.

Wartość domyślna to X-Original-Proto.
RequireHeaderSymmetry Wymagaj synchronizacji wartości nagłówka między przetwarzanymi elementami ForwardedHeadersOptions.ForwardedHeaders .

Wartość domyślna w ASP.NET Core 1.x to true. Wartość domyślna w wersji ASP.NET Core 2.0 lub nowszej to false.

Scenariusze i przypadki użycia

Gdy nie można dodać nagłówków przesłanych dalej, a wszystkie żądania są bezpieczne

W niektórych przypadkach dodanie nagłówków przesłanych dalej do aplikacji może nie być możliwe. Jeśli serwer proxy wymusza, że wszystkie publiczne żądania zewnętrzne są https, schemat można ustawić Startup.Configure ręcznie przed użyciem dowolnego typu oprogramowania pośredniczącego:

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

Ten kod można wyłączyć za pomocą zmiennej środowiskowej lub innego ustawienia konfiguracji w środowisku programistycznym lub przejściowym.

Obsługa bazowych ścieżek i serwerów proxy, które zmieniają ścieżkę żądania

Niektóre serwery proxy przechodzą ścieżkę bez zmian, ale z podstawową ścieżką aplikacji, która powinna zostać usunięta, aby routing działał prawidłowo. Oprogramowanie pośredniczące UsePathBaseExtensions.UsePathBase dzieli ścieżkę na httpRequest.Path, a ścieżkę bazową aplikacji na HttpRequest.PathBase.

Jeśli /foo jest ścieżką podstawową aplikacji dla ścieżki serwera proxy przekazanej jako /foo/api/1, oprogramowanie pośredniczące ustawia wartość Request.PathBase/foo i Request.Path na /api/1 za pomocą następującego polecenia:

app.UsePathBase("/foo");

Oryginalna ścieżka i podstawa ścieżki są ponownie stosować, gdy oprogramowanie pośredniczące jest wywoływane ponownie w odwrotnym momencie. Aby uzyskać więcej informacji na temat przetwarzania zamówień oprogramowania pośredniczącego, zobacz ASP.NET Core Oprogramowania pośredniczącego.

Jeśli serwer proxy przycina ścieżkę (na przykład przekazywanie /foo/api/1 do /api/1elementu ), napraw przekierowania i łącza, ustawiając właściwość PathBase żądania:

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

Jeśli serwer proxy dodaje dane ścieżki, odrzuć część ścieżki, aby naprawić przekierowania i linki przy użyciu polecenia StartsWithSegments i przypisz do Path właściwości :

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

    return next();
});

Konfiguracja serwera proxy używającego różnych nazw nagłówków

Jeśli serwer proxy nie używa nagłówków o nazwie X-Forwarded-For i X-Forwarded-Proto do przekazywania informacji o adresie/porcie serwera proxy i schemacie źródłowym, ustaw ForwardedForHeaderName opcje i ForwardedProtoHeaderName , aby były zgodne z nazwami nagłówków używanymi przez serwer proxy:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
    options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});

Przekazywanie schematu dla zwrotnych serwerów proxy systemu Linux i innych niż IIS

Aplikacje wywołujące UseHttpsRedirection i UseHsts umieszczające lokację w nieskończoną pętlę, jeśli zostały wdrożone w usłudze Azure Linux App Service, maszynie wirtualnej z systemem Linux platformy Azure lub za innym zwrotnym serwerem proxy oprócz usług IIS. Protokół TLS jest przerywany przez zwrotny serwer proxy i Kestrel nie jest świadomy poprawnego schematu żądań. Uwierzytelnianie OAuth i OIDC również kończą się niepowodzeniem w tej konfiguracji, ponieważ generują nieprawidłowe przekierowania. UseIISIntegration Dodaje i konfiguruje oprogramowanie pośredniczące przekierowanych nagłówków podczas uruchamiania za usługami IIS, ale nie ma zgodnej automatycznej konfiguracji dla systemu Linux (integracja z serwerem Apache lub Nginx).

Aby przekazać schemat z serwera proxy w scenariuszach innych niż IIS, dodaj i skonfiguruj oprogramowanie pośredniczące nagłówków przekazywanych. W Startup.ConfigureServicespliku użyj następującego kodu:

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

Przekazywanie certyfikatów

Azure

Aby skonfigurować Azure App Service na potrzeby przekazywania certyfikatów, zobacz Konfigurowanie wzajemnego uwierzytelniania TLS dla Azure App Service. Poniższe wskazówki dotyczą konfigurowania aplikacji ASP.NET Core.

W Startup.Configurepliku dodaj następujący kod przed wywołaniem metody app.UseAuthentication();:

app.UseCertificateForwarding();

Skonfiguruj oprogramowanie pośredniczące przekazywania certyfikatów, aby określić nazwę nagłówka używaną przez platformę Azure. W Startup.ConfigureServicespliku dodaj następujący kod, aby skonfigurować nagłówek, z którego oprogramowanie pośredniczące tworzy certyfikat:

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

Inne internetowe serwery proxy

Jeśli używany jest serwer proxy, który nie jest usługami IIS lub routingiem żądań aplikacji Azure App Service (ARR), skonfiguruj serwer proxy do przekazywania certyfikatu otrzymanego w nagłówku HTTP. W Startup.Configurepliku dodaj następujący kod przed wywołaniem metody app.UseAuthentication();:

app.UseCertificateForwarding();

Skonfiguruj oprogramowanie pośredniczące przekazywania certyfikatów, aby określić nazwę nagłówka. W Startup.ConfigureServicespliku dodaj następujący kod, aby skonfigurować nagłówek, z którego oprogramowanie pośredniczące tworzy certyfikat:

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

Jeśli serwer proxy nie jest zakodowany w formacie base64 certyfikatu (tak jak w przypadku serwera Nginx), ustaw HeaderConverter opcję . Rozważmy następujący przykład w pliku 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;
    }
});

Rozwiązywanie problemów

Gdy nagłówki nie są przekazywane zgodnie z oczekiwaniami, włącz rejestrowanie. Jeśli dzienniki nie dostarczają wystarczających informacji do rozwiązania problemu, wyliczenie nagłówków żądań odebranych przez serwer. Użyj wbudowanego oprogramowania pośredniczącego, aby zapisywać nagłówki żądań w odpowiedzi aplikacji lub rejestrować nagłówki.

Aby zapisać nagłówki w odpowiedzi aplikacji, umieść następujące śródliniowe oprogramowanie pośredniczące terminalu bezpośrednio po wywołaniu metody UseForwardedHeaders w Startup.Configurepliku :

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

Można zapisywać w dziennikach zamiast treści odpowiedzi. Zapisywanie w dziennikach umożliwia lokacji normalne działanie podczas debugowania.

Aby zapisać dzienniki zamiast do treści odpowiedzi:

app.Use(async (context, next) =>
{
    // Request method, scheme, and 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);

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

Podczas przetwarzania X-Forwarded-{For|Proto|Host} wartości są przenoszone do elementu X-Original-{For|Proto|Host}. Jeśli w danym nagłówku znajduje się wiele wartości, oprogramowanie pośredniczące nagłówków przekazujących przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Wartość domyślna ForwardLimit to 1 (jeden), więc tylko najbardziej właściwa wartość z nagłówków jest przetwarzana, chyba że wartość parametru ForwardLimit zostanie zwiększona.

Oryginalny zdalny adres IP żądania musi być zgodny z wpisem na KnownProxies listach lub KnownNetworks przed przetworzeniem przekazanych nagłówków. Ogranicza to fałszowanie nagłówków, nie akceptując usług przesyłania dalej z niezaufanych serwerów proxy. Po wykryciu nieznanego serwera proxy rejestrowanie wskazuje adres serwera proxy:

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

W poprzednim przykładzie 10.0.0.100 jest serwerem proxy. Jeśli serwer jest zaufanym serwerem proxy, dodaj adres IP serwera do KnownProxies (lub dodaj zaufaną sieć do KnownNetworksprogramu ) w pliku Startup.ConfigureServices. Aby uzyskać więcej informacji, zobacz sekcję Opcje oprogramowania pośredniczącego dla nagłówków przekazywanych .

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

Ważne

Zezwalaj tylko zaufanym serwerom proxy i sieciom na przekazywanie nagłówków. W przeciwnym razie możliwe są ataki fałszowania adresów IP .

Dodatkowe zasoby