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

A: Chris Przemysł

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

  • Gdy żądania HTTPS są przekazywane za pośrednictwem protokołu HTTP, oryginalny schemat (HTTPS) jest utracony i musi być przesyłany dalej w nagłówku.
  • Ponieważ aplikacja odbiera żądanie z serwera proxy, a nie jego prawdziwego źródła w Internecie lub sieci firmowej, źródłowy adres IP klienta również musi być przesyłany 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.

Przekazane nagłówki

Zgodnie z konwencją serwer proxy przekazuje informacje w nagłówkach HTTP.

Nagłówek Opis
X-Forwarded-For (XFF) Przechowuje informacje o kliencie, który zainicjował żądanie, oraz kolejnych proxych 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, do którego najpierw zostało wykonane żą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 inicjatora, HTTP lub HTTPS. Wartość może być również listą schematów, jeśli żądanie przechodziło przez wiele serwerów proxy.
X-Forwarded-Host (XFH) Oryginalna wartość pola Nagłówek hosta. Zazwyczaj proxy nie modyfikuje nagłówka Host. 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 lub nie ogranicza nagłówków hosta do znanych dobrych wartości.

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

Oprogramowanie pośredniczące aktualizuje:

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

Można skonfigurować domyślne ustawienia oprogramowania pośredniczącego nagłówków dalej. W przypadku ustawień domyślnych:

  • Między aplikacją a źródłem żądań istnieje tylko jeden serwer proxy.
  • Tylko adresy sprzężenia zwrotnego są konfigurowane dla znanych serwerów proxy i znanych sieci.
  • Przekazane nagłówki mają nazwy X-Forwarded-For i X-Forwarded-Proto .
  • Wartość to . Aby włączyć oprogramowanie pośredniczące, należy w tym miejscu ustawić ForwardedHeadersForwardedHeaders.None żądane usług przesyłania dalej.

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 proxy nie zawierają tych nagłówków, gdy docierają do aplikacji. Jeśli urządzenie używa innych nazw nagłówków niż i , ustaw opcje i w celu dopasowania ich do nazw X-Forwarded-ForX-Forwarded-ProtoForwardedForHeaderNameForwardedProtoHeaderName nagłówków używanych przez urządzenie. Aby uzyskać więcej informacji, zobacz Forwarded Headers Middleware options (Opcje oprogramowania pośredniczącego nagłówków przesyłania dalej) i Configuration for a proxy that uses different header names (Konfiguracja serwera proxy, który używa różnych nazw nagłówków).

IIS/IIS Express i ASP.NET Core Module

Oprogramowanie pośredniczące nagłówków dalej 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 module. Oprogramowanie pośredniczące Nagłówki dalej jest aktywowane do uruchamiania jako pierwsze w potoku oprogramowania pośredniczącego z ograniczoną konfiguracją specyficzną dla ASP.NET Core module. Konfiguracja ograniczona jest spowodowana problemami z zaufaniem w przypadku nagłówków przekazywania, na przykład fałszowania adresów IP. Oprogramowanie pośredniczące jest skonfigurowane do przekazywania dalej nagłówków i i X-Forwarded-For jest ograniczone do pojedynczego serwera proxy hosta X-Forwarded-Proto lokalnego. Jeśli wymagana jest dodatkowa konfiguracja, zobacz opcje oprogramowania pośredniczącego Nagłówki przekazywane.

Inne scenariusze dotyczące serwera proxy i usługi równoważenia obciążenia

Poza używaniem integracji usług IISwprzypadku hostowania poza procesem oprogramowanie pośredniczące nagłówków przekazywania nie jest domyślnie włączone. Oprogramowanie pośredniczące Nagłówki dalej musi być włączone, aby aplikacja przetwarzała przekazywane nagłówki za pomocą funkcji UseForwardedHeaders . Po włączeniu oprogramowania pośredniczącego, jeśli nie określono dla oprogramowania pośredniczącego, domyślnie ForwardedHeadersOptionsForwardedHeadersOptionsForwardedHeaders.None.

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

Kolejność oprogramowania pośredniczącego nagłówków przekazywania

Oprogramowanie pośredniczące Nagłówki dalej powinno być uruchamiane przed innym oprogramowaniem pośredniczącem. To uporządkowanie zapewnia, że oprogramowanie pośredniczące, które korzysta z informacji o nagłówkach przesyłanych dalej, może używać wartości nagłówka do przetwarzania. Oprogramowanie pośredniczące nagłówków dalej może działać po zakończeniu diagnostyki i obsługi błędów, ale musi zostać uruchomione przed wywołaniem funkcji 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();

Alternatywnie wywołaj 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 wartości lub zastosowano bezpośrednio do metody rozszerzenia za pomocą metody , domyślnymi nagłówkami do przekazania są ForwardedHeadersOptionsUseForwardedHeadersForwardedHeadersOptions Właściwość ForwardedHeaders musi być skonfigurowana z nagłówkami do przekazywania.

Konfiguracja serwera Nginx

Aby przesyłać dalej X-Forwarded-For nagłówki i X-Forwarded-Proto , zobacz Host ASP.NET Core on Linux with Nginx (Hostuj pliki w systemie Linux przy użyciu usługi X-Forwarded-For Aby uzyskać więcej informacji, zobacz NGINX: Using the Forwarded header (NGINX: używanie nagłówka Forwarded).

Konfiguracja serwera Apache

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

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

ForwardedHeadersOptionssteruje zachowaniem oprogramowania ForwardedHeadersOptions W poniższym przykładzie wartości domyślne są zmieniane:

  • Ogranicza liczbę wpisów w nagłówkach przekazywania do 2 .
  • Dodaje znany adres serwera proxy 127.0.10.1 .
  • Zmienia nazwę przekazanego nagłówka z domyślnego 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 X-Forwarded-Host nagłówka do podanych wartości.
  • Wartości są porównywane przy użyciu porządkowego-ignoruj-liter.
  • Należy wykluczyć numery portów.
  • 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 dopasowuje *.contoso.com domenę foo.contoso.com podrzędną, ale nie domenę główną contoso.com .
  • Nazwy hostów Unicode są dozwolone, ale są konwertowane na punycode w celu dopasowania.
  • Adresy IPv6 muszą zawierać nawiasy graniczne i być w postaci konwencjonalnej (na przykład ). Adresy IPv6 nie są specjalnie wykonywane w celu sprawdzania równości logicznej między różnymi formatami i nie jest wykonywana kanonizacja.
  • Jeśli nie można ograniczyć dozwolonych hostów, osoba atakująca może podszywać się pod linki wygenerowane przez usługę.
Wartość domyślna to pusta IList<string> wartość .
ForwardedForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast nagłówka określonego przez ForwardedHeadersDefaults.XForwardedForHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka, ale używa innego nagłówka do X-Forwarded-For przekazywania informacji.

Wartość domyślna to X-Forwarded-For.
ForwardedHeaders Określa, które z nich mają być przetwarzane. Listę pól, które mają zastosowanie, można znaleźć w wylicie 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 nagłówka określonego przez ForwardedHeadersDefaults.XForwardedHostHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka, ale używa innego nagłówka do X-Forwarded-Host przekazywania informacji.

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

Wartość domyślna to X-Forwarded-Proto.
ForwardLimit Ogranicza liczbę wpisów w przetwarzanych nagłówkach. Ustaw wartość null , aby wyłączyć limit, ale należy to zrobić tylko wtedy, KnownProxies gdy lub są KnownNetworks skonfigurowane. Ustawienie wartości nie jest zabezpieczeniem (ale nie gwarancją) ochrony przed błędnie skonfigurowanymi proxy i złośliwymi żądaniami, które docierają z kanałów null side-channels w sieci.

Oprogramowanie pośredniczące Przekazane nagłówki przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Jeśli jest używana wartość domyślna ( ), przetwarzana jest tylko najbardziej po prawej stronie wartość z 1 nagłówków, chyba że wartość jest ForwardLimit zwiększana.

Wartość domyślna to 1.
KnownNetworks Zakresy adresów znanych sieci do akceptowania nagłówków przesyłanych dalej z. Podaj zakresy adresów IP przy użyciu notacji CIDR (Classless Interdomain Routing).

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

Wartość domyślna to IList<IPNetwork> element zawierający pojedynczy wpis dla IPAddress.Loopback .
KnownProxies Adresy znanych serwerów proxy, z których mają być akceptowane przekazywane nagłówki. Użyj KnownProxies , aby określić dokładne dopasowania adresów IP.

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

Wartość domyślna to IList<IPAddress> element zawierający pojedynczy wpis dla IPAddress.IPv6Loopback .
OriginalForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast nagłówka 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 nagłówka 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 nagłówka określonego przez ForwardedHeadersDefaults.XOriginalProtoHeaderName.

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

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

Scenariusze i przypadki użycia

Gdy nie jest możliwe dodanie nagłówków przekazywania i wszystkie żądania są bezpieczne

W niektórych przypadkach dodanie nagłówków przekazywania do żądań proxied do aplikacji może nie być możliwe. Jeśli serwer proxy wymusza, że wszystkie publiczne żądania zewnętrzne mają protokół HTTPS, schemat można ręcznie ustawić 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 dewelopera 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 z bazą ścieżek i proxymi, które zmieniają ścieżkę żądania

Niektóre proxy przechodzą ścieżkę bez zmian, ale z podstawową ścieżką aplikacji, którą należy usunąć, aby routing działał prawidłowo. Oprogramowanie pośredniczące UsePathBaseExtensions.UsePathBase dzieli ścieżkę na httpRequest.Path i ścieżkę podstawową aplikacji na wartość HttpRequest.PathBase.

Jeśli ścieżka podstawowa aplikacji dla ścieżki serwera proxy została przekazana jako , oprogramowanie pośredniczące ustawia do i /foo/foo/api/1 do za pomocą Request.PathBase/fooRequest.Path/api/1 następującego polecenia:

app.UsePathBase("/foo");

Oryginalna ścieżka i podstawa ścieżki są ponowniestosowane, 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 Middleware.

Jeśli serwer proxy przycina ścieżkę (na przykład przekazywanie do ), napraw przekierowania i linki, ustawiając /foo/api/1/api/1 właściwość /foo/api/1 żą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 właściwości i przypisując StartsWithSegmentsPath ją:

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 nazwach i do przekazywania adresu/portu serwera proxy i informacji o schemacie pochodzącym, ustaw opcje i , aby dopasować nazwy nagłówków używane przez X-Forwarded-ForX-Forwarded-Proto serwer ForwardedForHeaderNameForwardedProtoHeaderName 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 zwrotnych serwerów proxy dla systemów Linux i innych niż IIS

Aplikacje, które wywołują witrynę i umieszczają ją w pętli nieskończonej, jeśli są wdrażane na platformie Azure z systemem Linux App Service, maszynie wirtualnej platformy Azure z systemem Linux lub za dowolnym innym zwrotny serwer proxy oprócz UseHttpsRedirectionUseHsts usług IIS. Usługa TLS jest przerywana przez zwrotny serwer proxy i nie jest Kestrel świadoma poprawnego schematu żądania. Uwierzytelnianie OAuth i OIDC również nie powiodły się w tej konfiguracji, ponieważ generują nieprawidłowe przekierowania. UseIISIntegration Dodaje i konfiguruje oprogramowanie pośredniczące Forwarded Headers w przypadku uruchamiania za usługami IIS, ale nie ma pasującej konfiguracji automatycznej dla systemu Linux (integracja z serwerem Apache lub Nginx).

Aby przesyłać dalej schemat z serwera proxy w scenariuszach innych niż usługi IIS, dodaj i skonfiguruj oprogramowanie pośredniczące Przekazane nagłówki. W Program.cs programie 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 przekazywania certyfikatów, zobacz Konfigurowanie wzajemnego uwierzytelniania protokołu TLSdla usługi Azure App Service . Poniższe wskazówki dotyczą konfigurowania aplikacji ASP.NET Core aplikacji.

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 internetowe proxy

Jeśli używany jest serwer proxy, który nie jest usługą IIS lub routingiem żądań aplikacji (ARR) usługi Azure App Service, skonfiguruj serwer proxy do przekazywania dalej certyfikatu otrzymanego 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 koduje certyfikatu base64, tak 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

Jeśli nagłówki nie są przekazywane zgodnie z oczekiwaniami, włącz rejestrowanie na poziomie i debug rejestrowanie żądań HTTP. debug UseHttpLogging musi 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, oprogramowanie pośredniczące Forwarded Headers przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Wartość domyślna to (jedna), więc przetwarzana jest tylko najbardziej po prawej stronie wartość z ForwardLimit1 nagłówków, chyba że wartość jest ForwardLimit zwiększana.

Oryginalny zdalny adres IP żądania musi odpowiadać wpisowi na listach lub przed przetworzeniem KnownProxiesKnownNetworks przesyłanych dalej nagłówków. Ogranicza to fałszowanie nagłówka, nie akceptując 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 usługi lub dodaj KnownProxies zaufaną sieć do usługi KnownNetworks . Aby uzyskać więcej informacji, zobacz sekcję Opcje oprogramowania pośredniczącego Nagłówki dalej.

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 "Microsoft.AspNetCore.HttpLogging": "Information"

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

Ważne

Zezwalaj tylko zaufanym serwerów proxy i sieciom na przekazywanie nagłówków. W przeciwnym razie możliwe są ataki podszywające się pod adresy 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, usługi równoważenia obciążenia i inne urządzenia sieciowe często przesłaniają informacje o żądaniu przed dotarciem do aplikacji:

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

Te informacje mogą być ważne w przetwarzaniu żądań, na przykład w przekierowaniach, uwierzytelnianiu, generowaniu linków, ocenie zasad i geolokalizacji klienta.

Przekazane nagłówki

Zgodnie z konwencją serwer proxy przekazuje informacje w nagłówkach HTTP.

Nagłówek Opis
X-Forwarded-for Przechowuje informacje o kliencie, który zainicjował żądanie, oraz kolejnych proxych 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 żądanie zostało wykonane po raz pierwszy. 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 inicjatora (HTTP/HTTPS). Wartość może również być listą schematów, jeśli żądanie przechodziło przez wiele serwerów proxy.
X-Forwarded-Host Oryginalna wartość pola Nagłówek hosta. Zazwyczaj proxy nie modyfikują nagłówka Host. Zobacz Biuletyn zabezpieczeń firmy Microsoft CVE-2018-0787, aby uzyskać informacje na temat luki w zabezpieczeniach dotyczącej podniesienia uprawnień, która ma wpływ na systemy, w których serwer proxy nie weryfikuje lub nie ogranicza nagłówków hosta do znanych dobrych wartości.

Oprogramowanie pośredniczące Forwarded Headers () odczytuje te nagłówki i wypełnia skojarzone ForwardedHeadersMiddleware pola w pliku HttpContext .

Oprogramowanie pośredniczące aktualizuje:

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

Można skonfigurować domyślne ustawienia oprogramowania pośredniczącego do przekazywania nagłówków. W przypadku ustawień domyślnych:

  • Między aplikacją a źródłem żądań istnieje tylko jeden serwer proxy.
  • Tylko adresy sprzężenia zwrotnego są konfigurowane dla znanych serwerów proxy i znanych sieci.
  • Przekazane nagłówki mają nazwy X-Forwarded-For i X-Forwarded-Proto .
  • Wartość to . W tym miejscu należy ustawić żądane usług przesyłania dalej, ForwardedHeadersForwardedHeaders.None 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 proxy nie zawierają tych nagłówków, gdy docierają do aplikacji. Jeśli urządzenie używa innych nazw nagłówków niż i , ustaw opcje i , aby dopasować je do nazw X-Forwarded-ForX-Forwarded-ProtoForwardedForHeaderNameForwardedProtoHeaderName nagłówków używanych przez urządzenie. Aby uzyskać więcej informacji, zobacz Forwarded Headers Middleware options (Opcje oprogramowania pośredniczącego nagłówków przekazywania) i Configuration for a proxy that uses different header names (Konfiguracja serwera proxy, który używa różnych nazw nagłówków).

IIS/IIS Express i ASP.NET Core Module

Oprogramowanie pośredniczące przekazywania nagłówków 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 module. Oprogramowanie pośredniczące do przekazywania nagłówków jest aktywowane w celu uruchomienia najpierw w potoku oprogramowania pośredniczącego z ograniczoną konfiguracją specyficzną dla modułu ASP.NET Core z powodu obaw o zaufanie do przesyłanych nagłówków (na przykład fałszowania adresów IP). Oprogramowanie pośredniczące jest skonfigurowane do przekazywania nagłówków i i jest X-Forwarded-For ograniczone do pojedynczego serwera proxy hosta X-Forwarded-Proto lokalnego. Jeśli wymagana jest dodatkowa konfiguracja, zobacz opcje oprogramowania pośredniczącego Przekazane nagłówki.

Inne scenariusze serwera proxy i usługi równoważenia obciążenia

Poza używaniem integracji usług IISpodczashostowania poza procesem oprogramowanie pośredniczące Przekazywane nagłówki nie jest domyślnie włączone. Oprogramowanie pośredniczące Nagłówki dalej musi być włączone, aby aplikacja przetwarzała przekazywane nagłówki za pomocą funkcji UseForwardedHeaders . Po włączeniu oprogramowania pośredniczącego, jeśli nie określono dla oprogramowania pośredniczącego, domyślnie ForwardedHeadersOptionsForwardedHeadersOptionsForwardedHeaders.None.

Skonfiguruj oprogramowanie pośredniczące za ForwardedHeadersOptions pomocą narzędzia , aby X-Forwarded-ForX-Forwarded-Proto przesyłać dalej nagłówki i w pliku Startup.ConfigureServices .

Kolejność oprogramowania pośredniczącego Przekazane nagłówki

Oprogramowanie pośredniczące Nagłówki dalej powinno być uruchamiane przed innym oprogramowaniem pośredniczącem. Dzięki temu można zagwarantować, że oprogramowanie pośredniczące, które korzysta z informacji o przesyłanych nagłówkach, może używać wartości nagłówka do przetwarzania. Oprogramowanie pośredniczące nagłówków dalej może działać po zakończeniu diagnostyki i obsługi błędów, ale musi zostać uruchomione przed wywołaniem UseHsts funkcji :

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

Alternatywnie wywołaj 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 nie określono wartości w metodzie rozszerzenia lub bezpośrednio do metody rozszerzenia za pomocą metody , domyślnymi nagłówkami do przekazania są ForwardedHeadersOptionsStartup.ConfigureServicesUseForwardedHeadersForwardedHeadersOptions Właściwość ForwardedHeaders musi być skonfigurowana z nagłówkami do przekazywania dalej.

Konfiguracja serwera Nginx

Aby przesyłać dalej X-Forwarded-For nagłówki i X-Forwarded-Proto , zobacz Host ASP.NET Core on Linux with Nginx (Serwery X-Forwarded-For Aby uzyskać więcej informacji, zobacz NGINX: Using the Forwarded header (NGINX: używanie nagłówka Forwarded).

Konfiguracja serwera Apache

X-Forwarded-For jest dodawany automatycznie (zobacz X-Forwarded-For(Moduł Apache: nagłówki żądań zwrotnego serwera proxy). Aby uzyskać informacje na temat przekazywania X-Forwarded-Proto nagłówka, zobacz Host ASP.NET Core on Linux with Apache (Host X-Forwarded-Proto

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

ForwardedHeadersOptions kontroluj zachowanie oprogramowania pośredniczącego Forwarded Headers. Poniższy przykład zmienia wartości domyślne:

  • Ogranicz liczbę wpisów w nagłówkach przekazywania do 2 .
  • Dodaj znany adres serwera proxy 127.0.10.1 .
  • Zmień nazwę przekazanego nagłówka z domyślnego 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 X-Forwarded-Host nagłówka do podanych wartości.
  • Wartości są porównywane przy użyciu porządkowych-ignorowanych-liter.
  • Należy wykluczyć numery portów.
  • 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 dopasowuje *.contoso.com domenę foo.contoso.com podrzędną, ale nie domenę główną contoso.com .
  • Nazwy hostów Unicode są dozwolone, ale są konwertowane na punycode w celu dopasowania.
  • Adresy IPv6 muszą zawierać nawiasy graniczne i być w postaci konwencjonalnej (na przykład ). Adresy IPv6 nie są specjalnie wykonywane w celu sprawdzania równości logicznej między różnymi formatami i nie jest wykonywana kanoniczacja.
  • Jeśli nie można ograniczyć dozwolonych hostów, osoba atakująca może podszywać się pod linki wygenerowane przez usługę.
Wartość domyślna to pusta IList<string> wartość .
ForwardedForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast nagłówka określonego przez ForwardedHeadersDefaults.XForwardedForHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka, ale używa innego nagłówka X-Forwarded-For do przekazywania informacji.

Wartość domyślna to X-Forwarded-For.
ForwardedHeaders Określa, które z nich mają być przetwarzane. Listę pól, które mają zastosowanie, można znaleźć w wylicie 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 nagłówka określonego przez ForwardedHeadersDefaults.XForwardedHostHeaderName. Ta opcja jest używana, gdy serwer proxy/usługa przesyłania dalej nie używa nagłówka, ale używa innego nagłówka X-Forwarded-Host do przekazywania informacji.

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

Wartość domyślna to X-Forwarded-Proto.
ForwardLimit Ogranicza liczbę wpisów w przetwarzanych nagłówkach. Ustaw wartość null , aby wyłączyć limit, ale należy to zrobić tylko wtedy, KnownProxies gdy lub są KnownNetworks skonfigurowane. Ustawienie wartości nie jest zabezpieczeniem (ale nie gwarancją) ochrony przed błędnie skonfigurowanymi proxy i złośliwymi żądaniami, które docierają z kanałów null side-channels w sieci.

Oprogramowanie pośredniczące Przekazane nagłówki przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Jeśli jest używana wartość domyślna ( ), przetwarzana jest tylko najbardziej po prawej stronie wartość z 1 nagłówków, chyba że wartość jest ForwardLimit zwiększana.

Wartość domyślna to 1.
KnownNetworks Zakresy adresów znanych sieci do akceptowania nagłówków przesyłanych dalej z. Podaj zakresy adresów IP przy użyciu notacji CIDR (Classless Interdomain Routing).

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

Wartość domyślna to IList<IPNetwork> element zawierający pojedynczy wpis dla IPAddress.Loopback .
KnownProxies Adresy znanych serwerów proxy, z których mają być akceptowane przekazywane nagłówki. Użyj KnownProxies , aby określić dokładne dopasowania adresów IP.

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

Wartość domyślna to IList<IPAddress> element zawierający pojedynczy wpis dla IPAddress.IPv6Loopback .
OriginalForHeaderName Użyj nagłówka określonego przez tę właściwość zamiast nagłówka 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 nagłówka 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 nagłówka określonego przez ForwardedHeadersDefaults.XOriginalProtoHeaderName.

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

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

Scenariusze i przypadki użycia

Jeśli nie jest możliwe dodanie nagłówków, które zostały przekazane dalej, a wszystkie żądania są bezpieczne

W niektórych przypadkach może nie być możliwe dodanie do żądań przesyłanych dalej nagłówków do aplikacji. Jeśli serwer proxy wymusza, że wszystkie publiczne żądania zewnętrzne mają protokół HTTPS, schemat można ustawić ręcznie przed użyciem Startup.Configure 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 dewelopera lub przejściowym.

Deal with path base and proxies that change the request path (Zajmowanie się bazą ścieżki i serwerów proxy, które zmieniają ścieżkę żądania)

Niektóre proxy przekażą ś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ę podstawową aplikacji na ścieżkę HttpRequest.PathBase.

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

app.UsePathBase("/foo");

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

Jeśli serwer proxy przycina ścieżkę (na przykład przekazywanie do ), napraw przekierowania i linki, ustawiając /foo/api/1/api/1 właściwość /foo/api/1 żą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, używając właściwości i przypisując StartsWithSegmentsPath ją:

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

    return next();
});

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

Jeśli serwer proxy nie używa nagłówków o nazwach i do przekazywania adresu/portu serwera proxy i informacji o schemacie, ustaw opcje i , aby dopasować nazwy nagłówków używane przez X-Forwarded-ForX-Forwarded-Proto serwer ForwardedForHeaderNameForwardedProtoHeaderName 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, które wywołują witrynę i umieszczają ją w pętli nieskończonej, jeśli są wdrażane w usłudze Azure Linux App Service, maszynie wirtualnej platformy Azure z systemem Linux lub za dowolnym innym zwrotny serwer proxy oprócz UseHttpsRedirectionUseHsts usług IIS. Usługa TLS jest przerywana przez zwrotny serwer proxy i nie jest Kestrel świadoma poprawnego schematu żądania. W tej konfiguracji również nie można użyć uwierzytelniania OAuth i OIDC, ponieważ generują nieprawidłowe przekierowania. UseIISIntegration Dodaje i konfiguruje oprogramowanie pośredniczące Forwarded Headers w przypadku uruchamiania za usługami IIS, ale nie ma pasującej konfiguracji automatycznej dla systemu Linux (integracja z serwerem Apache lub Nginx).

Aby przesyłać schemat z serwera proxy w scenariuszach innych niż usługi IIS, dodaj i skonfiguruj oprogramowanie pośredniczące Przekazane nagłówki. W Startup.ConfigureServices programie 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 przekazywania certyfikatów, zobacz Konfigurowanie wzajemnego uwierzytelniania protokołu TLSdla usługi Azure App Service . Poniższe wskazówki dotyczą konfigurowania aplikacji ASP.NET Core aplikacji.

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

app.UseCertificateForwarding();

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

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

Inne internetowe serwer proxy

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

app.UseCertificateForwarding();

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

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

Jeśli serwer proxy nie koduje certyfikatu przy użyciu kodowania base64 (tak jak w przypadku serwera Nginx), ustaw HeaderConverter opcję . Rozważmy następujący przykład w 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

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

Aby zapisać nagłówki w odpowiedzi aplikacji, umieść następujące wbudowane oprogramowanie pośredniczące terminalu bezpośrednio po wywołaniu w UseForwardedHeaders pliku 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}");
});

Możesz zapisywać w dziennikach zamiast w treści odpowiedzi. Zapisywanie w dziennikach umożliwia normalnie działanie witryny podczas debugowania.

Aby zapisywać dzienniki, a nie w treści odpowiedzi:

  • ILogger<Startup>Wstrzyknąć Startup do klasy zgodnie z opisem w ILogger<Startup>
  • Umieść następujące wbudowane oprogramowanie pośredniczące bezpośrednio po wywołaniu do w UseForwardedHeaders . Startup.Configure
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();
});

Po przetworzeniu X-Forwarded-{For|Proto|Host} wartości są przenoszone do X-Original-{For|Proto|Host} . Jeśli w danym nagłówku istnieje wiele wartości, oprogramowanie pośredniczące Nagłówki dalej przetwarza nagłówki w odwrotnej kolejności od prawej do lewej. Wartość domyślna to (jeden), więc przetwarzana jest tylko najbardziej po prawej stronie wartość ForwardLimit1 nagłówków, chyba że wartość zostanie ForwardLimit zwiększona.

Oryginalny zdalny adres IP żądania musi być zgodne z wpisem na listach lub przed przetworzeniem KnownProxiesKnownNetworks nagłówków dalej. Ogranicza to fałszowanie nagłówka, nie akceptując 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 adresu (lub dodaj zaufaną sieć KnownProxies do usługi ) w KnownNetworks programie Startup.ConfigureServices . Aby uzyskać więcej informacji, zobacz sekcję Opcje oprogramowania pośredniczącego nagłówków dalej.

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

Ważne

Zezwalaj na przekazywanie nagłówków tylko zaufanym serwerów proxy i sieciom. W przeciwnym razie możliwe są ataki podszywające się pod adresy IP.

Dodatkowe zasoby