Реализации веб-сервера Kestrel в ASP.NET CoreKestrel web server implementation in ASP.NET Core

Авторы: Том Дикстра (Tom Dykstra), Крис Росс (Chris Ross) и Стивен Хальтер (Stephen Halter)By Tom Dykstra, Chris Ross, and Stephen Halter

Kestrel — это кроссплатформенный веб-сервер для ASP.NET Core.Kestrel is a cross-platform web server for ASP.NET Core. Веб-сервер Kestrel по умолчанию включается в шаблоны проектов ASP.NET Core.Kestrel is the web server that's included by default in ASP.NET Core project templates.

Kestrel поддерживается в следующих сценариях.Kestrel supports the following scenarios:

  • HTTPSHTTPS
  • Непрозрачное обновление для поддержки WebSocketOpaque upgrade used to enable WebSockets
  • Сокеты UNIX для повышения производительности при работе за NginxUnix sockets for high performance behind Nginx
  • HTTP/2 (за исключением macOS†)HTTP/2 (except on macOS†)

† HTTP/2 будет поддерживаться для macOS в будущих выпусках.†HTTP/2 will be supported on macOS in a future release.

  • HTTPSHTTPS
  • Непрозрачное обновление для поддержки WebSocketOpaque upgrade used to enable WebSockets
  • Сокеты UNIX для повышения производительности при работе за NginxUnix sockets for high performance behind Nginx

Kestrel поддерживается на всех платформах и во всех версиях, поддерживаемых .NET Core.Kestrel is supported on all platforms and versions that .NET Core supports.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Поддержка HTTP/2HTTP/2 support

Протокол HTTP/2 доступен для приложений ASP.NET Core, если выполнены следующие базовые требования:HTTP/2 is available for ASP.NET Core apps if the following base requirements are met:

  • Операционная система†:Operating system†
    • Windows Server 2016 / Windows 10 или более поздних версий‡Windows Server 2016/Windows 10 or later‡
    • Linux с OpenSSL 1.0.2 или более поздней версии (например, Ubuntu 16.04 или более поздней версии).Linux with OpenSSL 1.0.2 or later (for example, Ubuntu 16.04 or later)
  • Требуемая версия .NET Framework: .NET Core версии 2.2 или более позднейTarget framework: .NET Core 2.2 or later
  • Подключение с поддержкой согласования протокола уровня приложений (ALPN).Application-Layer Protocol Negotiation (ALPN) connection
  • Подключение TLS 1.2 или более поздней версии.TLS 1.2 or later connection

† HTTP/2 будет поддерживаться для macOS в будущих выпусках.†HTTP/2 will be supported on macOS in a future release. ‡Для Kestrel предусмотрена ограниченная поддержка HTTP/2 в Windows Server 2012 R2 и Windows 8.1.‡Kestrel has limited support for HTTP/2 on Windows Server 2012 R2 and Windows 8.1. Поддержка ограничена из-за небольшого числа поддерживаемых комплектов шифров TLS, доступных для этих операционных систем.Support is limited because the list of supported TLS cipher suites available on these operating systems is limited. Для обеспечения безопасности TLS-подключений может потребоваться сертификат, созданный с использованием алгоритма ECDSA.A certificate generated using an Elliptic Curve Digital Signature Algorithm (ECDSA) may be required to secure TLS connections.

Если установлено подключение HTTP/2, HttpRequest.Protocol возвращает HTTP/2.If an HTTP/2 connection is established, HttpRequest.Protocol reports HTTP/2.

По умолчанию протокол HTTP/2 отключен.HTTP/2 is disabled by default. Дополнительные сведения о конфигурации см. в разделах о параметрах Kestrel и ListenOptions.Protocols.For more information on configuration, see the Kestrel options and ListenOptions.Protocols sections.

Условия использования Kestrel с обратным прокси-серверомWhen to use Kestrel with a reverse proxy

Kestrel можно использовать отдельно или с обратным прокси-сервером, таким как IIS, Nginx или Apache.Kestrel can be used by itself or with a reverse proxy server, such as Internet Information Services (IIS), Nginx, or Apache. Обратный прокси-сервер получает HTTP-запросы из сети и пересылает их в Kestrel.A reverse proxy server receives HTTP requests from the network and forwards them to Kestrel.

Kestrel используется в качестве веб-сервера перехода (с выходом в Интернет).Kestrel used as an edge (Internet-facing) web server:

Kestrel взаимодействует с Интернетом напрямую, без обратного прокси-сервера

Kestrel используется в конфигурации обратного прокси-сервера.Kestrel used in a reverse proxy configuration:

Kestrel взаимодействует с Интернетом косвенно, через обратный прокси-сервер, такой как IIS, Nginx или Apache.

Любая из этих конфигураций —с обратным прокси-сервером и без него— является поддерживаемой для размещения основных компонентов приложений ASP.NET версии 2.1 и выше, которые получают запросы из Интернета.Either configuration—with or without a reverse proxy server—is a supported hosting configuration for ASP.NET Core 2.1 or later apps that receive requests from the Internet.

Kestrel, используемый в качестве пограничного сервера без обратного прокси-сервера, не поддерживает общий доступ нескольких процессов к одним и тем же IP-адресам и портам.Kestrel used as an edge server without a reverse proxy server doesn't support sharing the same IP and port among multiple processes. Когда Kestrel настроен на ожидание передачи данных от порта, Kestrel обрабатывает весь трафик для этого порта независимо от заголовка Host запросов.When Kestrel is configured to listen on a port, Kestrel handles all of the traffic for that port regardless of requests' Host headers. Поэтому обратный прокси-сервер, который может совместно использовать порты, способен пересылать запросы в Kestrel с уникальным IP-адресом и портом.A reverse proxy that can share ports has the ability to forward requests to Kestrel on a unique IP and port.

Даже если обратный прокси-сервер не требуется, его использование может оказаться удобным.Even if a reverse proxy server isn't required, using a reverse proxy server might be a good choice.

Обратный прокси-сервер:A reverse proxy:

  • Может ограничить общедоступную контактную зону размещенных на нем приложений.Can limit the exposed public surface area of the apps that it hosts.
  • Предоставляет дополнительный уровень конфигурации и защиты.Provide an additional layer of configuration and defense.
  • Может лучше интегрироваться с существующей инфраструктурой.Might integrate better with existing infrastructure.
  • Упрощает настройку балансировки нагрузки и безопасных подключений (HTTPS).Simplify load balancing and secure communication (HTTPS) configuration. Сертификат X.509 требуется только обратному прокси-серверу, а сам этот сервер может обмениваться данными с серверами приложений во внутренней сети по обычному протоколу HTTP.Only the reverse proxy server requires an X.509 certificate, and that server can communicate with your app servers on the internal network using plain HTTP.

Предупреждение

Для размещения в конфигурации обратного прокси-сервера требуется фильтрация узлов.Hosting in a reverse proxy configuration requires host filtering.

Условия использования Kestrel в приложениях ASP.NET CoreHow to use Kestrel in ASP.NET Core apps

Пакет Microsoft.AspNetCore.Server.Kestrel входит в состав метапакета Microsoft.AspNetCore.App (ASP.NET Core 2.1 или более поздней версии).The Microsoft.AspNetCore.Server.Kestrel package is included in the Microsoft.AspNetCore.App metapackage (ASP.NET Core 2.1 or later).

Шаблоны проектов ASP.NET Core используют Kestrel по умолчанию.ASP.NET Core project templates use Kestrel by default. В файле Program.cs код шаблона вызывает метод CreateDefaultBuilder, который в фоновом режиме вызывает UseKestrel.In Program.cs, the template code calls CreateDefaultBuilder, which calls UseKestrel behind the scenes.

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

Чтобы задать дополнительную конфигурацию после вызова CreateDefaultBuilder, используйте ConfigureKestrel:To provide additional configuration after calling CreateDefaultBuilder, use ConfigureKestrel:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            // Set properties and call methods on options
        });

Если приложение не вызывает CreateDefaultBuilder, чтобы настроить узел, вызовите UseKestrel перед вызовом ConfigureKestrel:If the app doesn't call CreateDefaultBuilder to set up the host, call UseKestrel before calling ConfigureKestrel:

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseKestrel()
        .UseIISIntegration()
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            // Set properties and call methods on options
        })
        .Build();

    host.Run();
}

Чтобы задать дополнительную конфигурацию после вызова CreateDefaultBuilder, вызовите UseKestrel:To provide additional configuration after calling CreateDefaultBuilder, call UseKestrel:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            // Set properties and call methods on options
        });

Параметры KestrelKestrel options

Веб-сервер Kestrel имеет ограничительные параметры конфигурации, которые удобно использовать в развертываниях с выходом в Интернет.The Kestrel web server has constraint configuration options that are especially useful in Internet-facing deployments.

Задать ограничения для свойства Limits в классе KestrelServerOptions.Set constraints on the Limits property of the KestrelServerOptions class. Свойство Limits содержит экземпляр класса KestrelServerLimits.The Limits property holds an instance of the KestrelServerLimits class.

В следующих примерах используется пространство имен Microsoft.AspNetCore.Server.Kestrel.Core.The following examples use the Microsoft.AspNetCore.Server.Kestrel.Core namespace:

using Microsoft.AspNetCore.Server.Kestrel.Core;

Время ожидания проверки на активностьKeep-alive timeout

KeepAliveTimeout

Получает или задает время ожидания проверки на активность.Gets or sets the keep-alive timeout. Значение по умолчанию — 2 минуты.Defaults to 2 minutes.

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
        });

максимальное число клиентских подключений;Maximum client connections

MaxConcurrentConnections MaxConcurrentUpgradedConnections

Максимальное число одновременно открытых подключений TCP для всего приложения можно задать с помощью следующего кода:The maximum number of concurrent open TCP connections can be set for the entire app with the following code:

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.MaxConcurrentConnections = 100;
        });

Существует отдельный предел по подключениям, измененным с HTTP или HTTPS на другой протокол (например, по запросу WebSocket).There's a separate limit for connections that have been upgraded from HTTP or HTTPS to another protocol (for example, on a WebSockets request). После изменения подключение не учитывается в пределе MaxConcurrentConnections.After a connection is upgraded, it isn't counted against the MaxConcurrentConnections limit.

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.MaxConcurrentUpgradedConnections = 100;
        });

По умолчанию максимальное число подключений не ограничено (null).The maximum number of connections is unlimited (null) by default.

максимальный размер текста запроса;Maximum request body size

MaxRequestBodySize

По умолчанию максимальный размер текста запроса составляет 30 000 000 байт, что примерно соответствует 28,6 МБ.The default maximum request body size is 30,000,000 bytes, which is approximately 28.6 MB.

Чтобы переопределить это ограничение в приложении MVC ASP.NET Core, мы рекомендуем использовать атрибут RequestSizeLimitAttribute в методе действия:The recommended approach to override the limit in an ASP.NET Core MVC app is to use the RequestSizeLimitAttribute attribute on an action method:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Приведенный ниже пример показывает, как настроить ограничение для приложения и каждого запроса:Here's an example that shows how to configure the constraint for the app on every request:

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.MaxRequestBodySize = 10 * 1024;
        });

Можно переопределить параметр для конкретного запроса в ПО промежуточного слоя:You can override the setting on a specific request in middleware:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

При попытке настроить ограничение для запроса после того, как приложение начало считывать запрос, возникает исключение.An exception is thrown if you attempt to configure the limit on a request after the app has started to read the request. Доступно свойство IsReadOnly, указывающее, что свойство MaxRequestBodySize находится в состоянии только для чтения и настраивать ограничение слишком поздно.There's an IsReadOnly property that indicates if the MaxRequestBodySize property is in read-only state, meaning it's too late to configure the limit.

При запуске приложения вне процесса, который обслуживает модуль ASP.NET Core, ограничение на размер текста запроса Kestrel будет отключено, так как оно уже задается IIS.When an app is run out-of-process behind the ASP.NET Core Module, Kestrel's request body size limit is disabled because IIS already sets the limit.

минимальная скорость передачи данных в тексте запроса.Minimum request body data rate

MinRequestBodyDataRate MinResponseDataRate

Kestrel каждую секунду проверяет, поступают ли данные с указанной скоростью в байтах в секунду.Kestrel checks every second if data is arriving at the specified rate in bytes/second. Если скорость падает ниже минимума, для соединения истекает время ожидания. Льготный период — это количество времени, которое Kestrel дает клиенту на увеличение его скорости отправки до минимального уровня; в течение этого периода скорость не проверяется.If the rate drops below the minimum, the connection is timed out. The grace period is the amount of time that Kestrel gives the client to increase its send rate up to the minimum; the rate isn't checked during that time. Льготный период помогает избежать разрыва соединений, которые первоначально отправляют данные с небольшой скоростью из-за медленного запуска TCP.The grace period helps avoid dropping connections that are initially sending data at a slow rate due to TCP slow-start.

Минимальная скорость по умолчанию составляет 240 байт/с, льготный период равен 5 секундам.The default minimum rate is 240 bytes/second with a 5 second grace period.

Минимальная скорость также применяется к отклику.A minimum rate also applies to the response. Код для задания лимита запросов и лимита откликов различается только наличием RequestBody или Response в именах свойств и интерфейсов.The code to set the request limit and the response limit is the same except for having RequestBody or Response in the property and interface names.

Ниже приведен пример, показывающий, как настроить минимальную скорость передачи данных в Program.cs:Here's an example that shows how to configure the minimum data rates in Program.cs:

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.MinRequestBodyDataRate =
                new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
            options.Limits.MinResponseDataRate =
                new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
        });

Можно переопределить ограничения минимальной скорости для каждого запроса в ПО промежуточного слоя:You can override the minimum rate limits per request in middleware:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

Возможности IHttpMinResponseDataRateFeature, указанные в предыдущем примере, отсутствуют в HttpContext.Features для запросов HTTP/2, так как изменение ограничений скорости для каждого запроса не поддерживается для HTTP/2 из-за поддержки протокола мультиплексирования запроса.The IHttpMinResponseDataRateFeature referenced in the prior sample is not present in HttpContext.Features for HTTP/2 requests because modifying rate limits on a per-request basis is generally not supported for HTTP/2 due to the protocol's support for request multiplexing. Но возможности IHttpMinRequestBodyDataRateFeature все еще присутствуют в HttpContext.Features для запросов HTTP/2, так как ограничение скорости чтения может быть полностью отключено для отдельных запросов. Чтобы сделать это, задайте для параметра IHttpMinRequestBodyDataRateFeature.MinDataRate значение null (даже для запроса HTTP/2).However, the IHttpMinRequestBodyDataRateFeature is still present HttpContext.Features for HTTP/2 requests, because the read rate limit can still be disabled entirely on a per-request basis by setting IHttpMinRequestBodyDataRateFeature.MinDataRate to null even for an HTTP/2 request. При попытке чтения свойства IHttpMinRequestBodyDataRateFeature.MinDataRate или при попытке задать для него значение, отличное от null, возникнет исключение NotSupportedException для запроса HTTP/2.Attempting to read IHttpMinRequestBodyDataRateFeature.MinDataRate or attempting to set it to a value other than null will result in a NotSupportedException being thrown given an HTTP/2 request.

Ограничения скорости на уровне сервера, которые настроены с помощью KestrelServerOptions.Limits, по-прежнему применяются к подключениям HTTP/1.x и HTTP/2.Server-wide rate limits configured via KestrelServerOptions.Limits still apply to both HTTP/1.x and HTTP/2 connections.

В HttpContext.Features для запросов HTTP/2 отсутствуют возможности настройки скорости, указанные в предыдущем примере, так как изменение ограничений скорости для каждого запроса не поддерживается для HTTP/2 из-за поддержки протокола мультиплексирования запроса.Neither rate feature referenced in the prior sample are present in HttpContext.Features for HTTP/2 requests because modifying rate limits on a per-request basis isn't supported for HTTP/2 due to the protocol's support for request multiplexing. Ограничения скорости на уровне сервера, которые настроены с помощью KestrelServerOptions.Limits, по-прежнему применяются к подключениям HTTP/1.x и HTTP/2.Server-wide rate limits configured via KestrelServerOptions.Limits still apply to both HTTP/1.x and HTTP/2 connections.

Время ожидания для заголовков запросовRequest headers timeout

RequestHeadersTimeout

Получает или задает максимальное время, которое сервер уделяет получению заголовков запросов.Gets or sets the maximum amount of time the server spends receiving request headers. Значение по умолчанию — 30 секунд.Defaults to 30 seconds.

.ConfigureKestrel((context, options) =>
{
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024;
    options.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    options.Listen(IPAddress.Loopback, 5000);
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
        });

Максимальное число потоков на подключениеMaximum streams per connection

Http2.MaxStreamsPerConnection ограничивает количество параллельных потоков запросов для одного соединения HTTP/2.Http2.MaxStreamsPerConnection limits the number of concurrent request streams per HTTP/2 connection. Потоки сверх этого числа будут отклонены.Excess streams are refused.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.MaxStreamsPerConnection = 100;
        });

Значение по умолчанию — 100.The default value is 100.

Размер таблицы заголовкаHeader table size

Декодер HPACK распаковывает заголовки HTTP для подключений HTTP/2.The HPACK decoder decompresses HTTP headers for HTTP/2 connections. Http2.HeaderTableSize ограничивает размер таблицы сжатия заголовка, которую использует декодер HPACK.Http2.HeaderTableSize limits the size of the header compression table that the HPACK decoder uses. Это значение указывается в октетах и должно быть больше нуля (0).The value is provided in octets and must be greater than zero (0).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.HeaderTableSize = 4096;
        });

Значение по умолчанию — 4096.The default value is 4096.

Максимальный размер кадраMaximum frame size

Http2.MaxFrameSize указывает максимальный размер полезных данных в получаемом кадре подключения HTTP/2.Http2.MaxFrameSize indicates the maximum size of the HTTP/2 connection frame payload to receive. Это значение указывается в октетах и должно находиться в пределах от 2^14 (16 384) до 2^24-1 (16 777 215).The value is provided in octets and must be between 2^14 (16,384) and 2^24-1 (16,777,215).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.MaxFrameSize = 16384;
        });

Значение по умолчанию — 2^14 (16 384).The default value is 2^14 (16,384).

Максимальный размер запроса заголовкаMaximum request header size

Http2.MaxRequestHeaderFieldSize указывает максимально допустимый размер значений заголовка запроса (в октетах).Http2.MaxRequestHeaderFieldSize indicates the maximum allowed size in octets of request header values. Это ограничение применяется к имени и значению в их сжатых и несжатых представлениях.This limit applies to both name and value together in their compressed and uncompressed representations. Значение должно быть больше нуля.The value must be greater than zero (0).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
        });

Значение по умолчанию — 8 192.The default value is 8,192.

Размер окна начального подключенияInitial connection window size

Http2.InitialConnectionWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для всех запросов (потоков) на каждое соединение.Http2.InitialConnectionWindowSize indicates the maximum request body data in bytes the server buffers at one time aggregated across all requests (streams) per connection. Размеры запросов также ограничиваются параметром Http2.InitialStreamWindowSize.Requests are also limited by Http2.InitialStreamWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.InitialConnectionWindowSize = 131072;
        });

Значение по умолчанию — 128 КБ (131 072).The default value is 128 KB (131,072).

Размер окна начального потокаInitial stream window size

Http2.InitialStreamWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для каждого запроса (потока).Http2.InitialStreamWindowSize indicates the maximum request body data in bytes the server buffers at one time per request (stream). Размеры запросов также ограничиваются параметром Http2.InitialStreamWindowSize.Requests are also limited by Http2.InitialStreamWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.Http2.InitialStreamWindowSize = 98304;
        });

Значение по умолчанию — 96 КБ (98 304).The default value is 96 KB (98,304).

Синхронные операции ввода-выводаSynchronous IO

AllowSynchronousIO определяет, разрешены ли синхронные операции ввода-вывода для запроса и ответа.AllowSynchronousIO controls whether synchronous IO is allowed for the request and response. Значение по умолчанию — false.The default value is false.

AllowSynchronousIO определяет, разрешены ли синхронные операции ввода-вывода для запроса и ответа.AllowSynchronousIO controls whether synchronous IO is allowed for the request and response. Значение по умолчанию — true.The default value is true.

Предупреждение

Выполнение большого числа заблокированных операций синхронного ввода-вывода может привести к перегрузке пула потоков и зависанию приложения.A large number of blocking synchronous IO operations can lead to thread pool starvation, which makes the app unresponsive. Включайте AllowSynchronousIO, только если вы используете библиотеку, которая не поддерживает асинхронные операции ввода-вывода.Only enable AllowSynchronousIO when using a library that doesn't support asynchronous IO.

В примере ниже включаются синхронные операции ввода-вывода:The following example enables synchronous IO:

.ConfigureKestrel((context, options) =>
{
    options.AllowSynchronousIO = true;
});

В примере ниже отключаются синхронные операции ввода-вывода:The following example disables synchronous IO:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.AllowSynchronousIO = false;
        });

Сведения о других параметрах и ограничениях Kestrel см. в следующих разделах:For information about other Kestrel options and limits, see:

Конфигурация конечной точкиEndpoint configuration

По умолчанию платформа ASP.NET Core привязана к:By default, ASP.NET Core binds to:

  • http://localhost:5000
  • https://localhost:5001 (если присутствует локальный сертификат разработки)https://localhost:5001 (when a local development certificate is present)

Укажите URL-адреса с помощью следующих параметров:Specify URLs using the:

  • Переменная среды ASPNETCORE_URLS.ASPNETCORE_URLS environment variable.
  • Аргументы командной строки --urls.--urls command-line argument.
  • Ключ конфигурации узла urls.urls host configuration key.
  • Метод расширения UseUrls.UseUrls extension method.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию).The value provided using these approaches can be one or more HTTP and HTTPS endpoints (HTTPS if a default cert is available). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000; http://localhost:8001").Configure the value as a semicolon-separated list (for example, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.For more information on these approaches, see Server URLs and Override configuration.

Сертификат разработки создается, когда:A development certificate is created:

В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.Some browsers require that you grant explicit permission to the browser to trust the local development certificate.

Шаблоны проектов на ASP.NET Core 2.1 и более поздних версий настраивают приложения так, чтобы они запускались на HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.ASP.NET Core 2.1 and later project templates configure apps to run on HTTPS by default and include HTTPS redirection and HSTS support.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.Call Listen or ListenUnixSocket methods on KestrelServerOptions to configure URL prefixes and ports for Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).UseUrls, the --urls command-line argument, urls host configuration key, and the ASPNETCORE_URLS environment variable also work but have the limitations noted later in this section (a default certificate must be available for HTTPS endpoint configuration).

Конфигурация KestrelServerOptions в ASP.NET Core 2.1 или более поздней версии:ASP.NET Core 2.1 or later KestrelServerOptions configuration:

ConfigureEndpointDefaults(Action<ListenOptions>)ConfigureEndpointDefaults(Action<ListenOptions>)

Указывает конфигурацию Action для выполнения каждой заданной конечной точки.Specifies a configuration Action to run for each specified endpoint. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.Calling ConfigureEndpointDefaults multiple times replaces prior Actions with the last Action specified.

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.ConfigureKestrel(serverOptions =>
        {
            serverOptions.ConfigureEndpointDefaults(configureOptions =>
            {
                configureOptions.NoDelay = true;
            });
        });
        webBuilder.UseStartup<Startup>();
    });
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.ConfigureEndpointDefaults(configureOptions =>
            {
                configureOptions.NoDelay = true;
            });
        });

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

Указывает конфигурацию Action для выполнения каждой конечной точки HTTPS.Specifies a configuration Action to run for each HTTPS endpoint. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.Calling ConfigureHttpsDefaults multiple times replaces prior Actions with the last Action specified.

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.ConfigureKestrel(serverOptions =>
        {
            serverOptions.ConfigureHttpsDefaults(options =>
            {
                // certificate is an X509Certificate2
                options.ServerCertificate = certificate;
            });
        });
        webBuilder.UseStartup<Startup>();
    });
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.ConfigureHttpsDefaults(httpsOptions =>
            {
                // certificate is an X509Certificate2
                httpsOptions.ServerCertificate = certificate;
            });
        });

Configure(IConfiguration)Configure(IConfiguration)

Создает загрузчик конфигурации для настройки Kestrel, который принимает IConfiguration в качестве входных данных.Creates a configuration loader for setting up Kestrel that takes an IConfiguration as input. Для Kestrel конфигурация должна быть ограничена разделом конфигурации.The configuration must be scoped to the configuration section for Kestrel.

ListenOptions.UseHttpsListenOptions.UseHttps

Настройте Kestrel для использования протокола HTTPS.Configure Kestrel to use HTTPS.

Расширения ListenOptions.UseHttps:ListenOptions.UseHttps extensions:

  • UseHttps – Настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию.UseHttps – Configure Kestrel to use HTTPS with the default certificate. Создает исключение, если сертификат по умолчанию не настроен.Throws an exception if no default certificate is configured.
  • UseHttps(string fileName)
  • UseHttps(string fileName, string password)
  • UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(StoreName storeName, string subject)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(X509Certificate2 serverCertificate)
  • UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)

Параметры ListenOptions.UseHttps:ListenOptions.UseHttps parameters:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.filename is the path and file name of a certificate file, relative to the directory that contains the app's content files.
  • password — это пароль для доступа к данным сертификата X.509.password is the password required to access the X.509 certificate data.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions.configureOptions is an Action to configure the HttpsConnectionAdapterOptions. Возвращает ListenOptions.Returns the ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.storeName is the certificate store from which to load the certificate.
  • subject — это имя субъекта для сертификата.subject is the subject name for the certificate.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.allowInvalid indicates if invalid certificates should be considered, such as self-signed certificates.
  • location — это расположение хранилища, из которого загружается сертификат.location is the store location to load the certificate from.
  • serverCertificate — это сертификат X.509.serverCertificate is the X.509 certificate.

В рабочей среде необходимо явно настроить HTTPS.In production, HTTPS must be explicitly configured. Как минимум необходимо указать сертификат по умолчанию.At a minimum, a default certificate must be provided.

Поддерживаемые конфигурации, описанные далее:Supported configurations described next:

  • Отсутствие конфигурацииNo configuration
  • Замена сертификата по умолчанию из конфигурацииReplace the default certificate from configuration
  • Изменение значений по умолчанию в кодеChange the defaults in code

Отсутствие конфигурацииNo configuration

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).Kestrel listens on http://localhost:5000 and https://localhost:5001 (if a default cert is available).

Замена сертификата по умолчанию из конфигурацииReplace the default certificate from configuration

CreateDefaultBuilder по умолчанию вызывает serverOptions.Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel.CreateDefaultBuilder calls serverOptions.Configure(context.Configuration.GetSection("Kestrel")) by default to load Kestrel configuration. Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию.A default HTTPS app settings configuration schema is available for Kestrel. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.Configure multiple endpoints, including the URLs and the certificates to use, either from a file on disk or from a certificate store.

В следующем примере appsettings.json:In the following appsettings.json example:

  • Установите для AllowInvalid значение true, чтобы разрешить использование недопустимых сертификатов (например, самозаверяющих сертификатов).Set AllowInvalid to true to permit the use of invalid certificates (for example, self-signed certificates).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Сертификаты > По умолчанию , или сертификат разработки.Any HTTPS endpoint that doesn't specify a certificate (HttpsDefaultCert in the example that follows) falls back to the cert defined under Certificates > Default or the development certificate.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },

      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      },

      "HttpsInlineCertStore": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },

      "HttpsDefaultCert": {
        "Url": "https://localhost:5003"
      },

      "Https": {
        "Url": "https://*:5004",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "<certificate password>"
      }
    }
  }
}

Вместо использования параметров Path и Password для узла сертификата можно указать сертификат с помощью полей хранилища сертификатов.An alternative to using Path and Password for any certificate node is to specify the certificate using certificate store fields. Например, сертификат из раздела Сертификаты > По умолчанию можно указать следующим образом:For example, the Certificates > Default certificate can be specified as:

"Default": {
  "Subject": "<subject; required>",
  "Store": "<cert store; required>",
  "Location": "<location; defaults to CurrentUser>",
  "AllowInvalid": "<true or false; defaults to false>"
}

Примечания к схеме.Schema notes:

  • Регистр букв в именах конечных точек не учитывается.Endpoints names are case-insensitive. Например, HTTPS и Https являются допустимыми.For example, HTTPS and Https are valid.

  • Параметр Url является обязательным для каждой конечной точки.The Url parameter is required for each endpoint. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.The format for this parameter is the same as the top-level Urls configuration parameter except that it's limited to a single value.

  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их.These endpoints replace those defined in the top-level Urls configuration rather than adding to them. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.Endpoints defined in code via Listen are cumulative with the endpoints defined in the configuration section.

  • Раздел Certificate является необязательным.The Certificate section is optional. Если раздел Certificate не указан, используются значения по умолчанию, определенные в предыдущих сценариях.If the Certificate section isn't specified, the defaults defined in earlier scenarios are used. Если значений по умолчанию нет, сервер выдает исключение и не запускается.If no defaults are available, the server throws an exception and fails to start.

  • Раздел Certificate поддерживает сертификаты PathPassword и SubjectStore.The Certificate section supports both PathPassword and SubjectStore certificates.

  • Таким образом, можно определить любое количество конечных точек, если это не приводит к конфликту портов.Any number of endpoints may be defined in this way so long as they don't cause port conflicts.

  • options.Configure(context.Configuration.GetSection("Kestrel")) возвращает KestrelConfigurationLoader с методом .Endpoint(string name, options => { }), который может использоваться в качестве дополнения для параметров настроенной конечной точки:options.Configure(context.Configuration.GetSection("Kestrel")) returns a KestrelConfigurationLoader with an .Endpoint(string name, options => { }) method that can be used to supplement a configured endpoint's settings:

    options.Configure(context.Configuration.GetSection("Kestrel"))
        .Endpoint("HTTPS", opt =>
        {
            opt.HttpsOptions.SslProtocols = SslProtocols.Tls12;
        });
    

    Можно также напрямую использовать KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным CreateDefaultBuilder.You can also directly access KestrelServerOptions.ConfigurationLoader to keep iterating on the existing loader, such as the one provided by CreateDefaultBuilder.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.The configuration section for each endpoint is a available on the options in the Endpoint method so that custom settings may be read.

  • Можно загрузить несколько конфигураций, снова вызвав options.Configure(context.Configuration.GetSection("Kestrel")) с другим разделом.Multiple configurations may be loaded by calling options.Configure(context.Configuration.GetSection("Kestrel")) again with another section. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах.Only the last configuration is used, unless Load is explicitly called on prior instances. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.The metapackage doesn't call Load so that its default configuration section may be replaced.

  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте.KestrelConfigurationLoader mirrors the Listen family of APIs from KestrelServerOptions as Endpoint overloads, so code and config endpoints may be configured in the same place. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.These overloads don't use names and only consume default settings from configuration.

Изменение значений по умолчанию в кодеChange the defaults in code

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии.ConfigureEndpointDefaults and ConfigureHttpsDefaults can be used to change default settings for ListenOptions and HttpsConnectionAdapterOptions, including overriding the default certificate specified in the prior scenario. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.ConfigureEndpointDefaults and ConfigureHttpsDefaults should be called before any endpoints are configured.

options.ConfigureEndpointDefaults(opt =>
{
    opt.NoDelay = true;
});

options.ConfigureHttpsDefaults(httpsOptions =>
{
    httpsOptions.SslProtocols = SslProtocols.Tls12;
});

Поддержка Kestrel для SNIKestrel support for SNI

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте.Server Name Indication (SNI) can be used to host multiple domains on the same IP address and port. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат.For SNI to function, the client sends the host name for the secure session to the server during the TLS handshake so that the server can provide the correct certificate. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.The client uses the furnished certificate for encrypted communication with the server during the secure session that follows the TLS handshake.

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector.Kestrel supports SNI via the ServerCertificateSelector callback. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат.The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate.

Поддержка SNI требует:SNI support requires:

  • Запуск на целевой платформе netcoreapp2.1.Running on target framework netcoreapp2.1. В netcoreapp2.0 и net461 обратный вызов выполняется, но name всегда имеет значение null.On netcoreapp2.0 and net461, the callback is invoked but the name is always null. name также имеет значение null, если клиент не предоставляет параметр имени узла при подтверждении TLS.The name is also null if the client doesn't provide the host name parameter in the TLS handshake.
  • Все веб-сайты выполняются на одном и том же экземпляре Kestrel.All websites run on the same Kestrel instance. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.Kestrel doesn't support sharing an IP address and port across multiple instances without a reverse proxy.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.ListenAnyIP(5005, listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    var localhostCert = CertificateLoader.LoadFromStoreCert(
                        "localhost", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var exampleCert = CertificateLoader.LoadFromStoreCert(
                        "example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var subExampleCert = CertificateLoader.LoadFromStoreCert(
                        "sub.example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var certs = new Dictionary<string, X509Certificate2>(
                        StringComparer.OrdinalIgnoreCase);
                    certs["localhost"] = localhostCert;
                    certs["example.com"] = exampleCert;
                    certs["sub.example.com"] = subExampleCert;

                    httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
                    {
                        if (name != null && certs.TryGetValue(name, out var cert))
                        {
                            return cert;
                        }

                        return exampleCert;
                    };
                });
            });
        });
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, options) =>
        {
            options.ListenAnyIP(5005, listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    var localhostCert = CertificateLoader.LoadFromStoreCert(
                        "localhost", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var exampleCert = CertificateLoader.LoadFromStoreCert(
                        "example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var subExampleCert = CertificateLoader.LoadFromStoreCert(
                        "sub.example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var certs = new Dictionary<string, X509Certificate2>(
                        StringComparer.OrdinalIgnoreCase);
                    certs["localhost"] = localhostCert;
                    certs["example.com"] = exampleCert;
                    certs["sub.example.com"] = subExampleCert;

                    httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
                    {
                        if (name != null && certs.TryGetValue(name, out var cert))
                        {
                            return cert;
                        }

                        return exampleCert;
                    };
                });
            });
        })
        .Build();

Привязка к TCP-сокетуBind to a TCP socket

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:The Listen method binds to a TCP socket, and an options lambda permits X.509 certificate configuration:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Listen(IPAddress.Loopback, 5000);
            options.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Listen(IPAddress.Loopback, 5000);
            options.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Listen(IPAddress.Loopback, 5000);
            options.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions.The example configures HTTPS for an endpoint with ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.Use the same API to configure other Kestrel settings for specific endpoints.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate.On Windows, self-signed certificates can be created using the New-SelfSignedCertificate PowerShell cmdlet. Примеры, которые не поддерживаются, см. в разделе UpdateIISExpressSSLForChrome.ps1.For an unsupported example, see UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.On macOS, Linux, and Windows, certificates can be created using OpenSSL.

Привязка к сокету UNIXBind to a Unix socket

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:Listen on a Unix socket with ListenUnixSocket for improved performance with Nginx, as shown in this example:

.ConfigureKestrel((context, options) =>
{
    options.ListenUnixSocket("/tmp/kestrel-test.sock");
    options.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testpassword");
    });
});
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.ListenUnixSocket("/tmp/kestrel-test.sock");
            options.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testpassword");
            });
        });

Порт 0Port 0

Если указать номер порта 0, Kestrel динамически привязывается к доступному порту.When the port number 0 is specified, Kestrel dynamically binds to an available port. Следующий пример показывает, как определить, к какому порту фактически привязан Kestrel во время выполнения:The following example shows how to determine which port Kestrel actually bound at runtime:

public void Configure(IApplicationBuilder app)
{
    var serverAddressesFeature = 
        app.ServerFeatures.Get<IServerAddressesFeature>();

    app.UseStaticFiles();

    app.Run(async (context) =>
    {
        context.Response.ContentType = "text/html";
        await context.Response
            .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                "<title></title></head><body><p>Hosted by Kestrel</p>");

        if (serverAddressesFeature != null)
        {
            await context.Response
                .WriteAsync("<p>Listening on the following addresses: " +
                    string.Join(", ", serverAddressesFeature.Addresses) +
                    "</p>");
        }

        await context.Response.WriteAsync("<p>Request URL: " +
            $"{context.Request.GetDisplayUrl()}<p>");
    });
}

Когда приложение выполняется, в выходных данных в окне консоли указывается динамический порт, по которому можно связаться с приложением:When the app is run, the console window output indicates the dynamic port where the app can be reached:

Listening on the following addresses: http://127.0.0.1:48508

ОграниченияLimitations

Настройте конечные точки с помощью следующих подходов:Configure endpoints with the following approaches:

  • UseUrls
  • Аргументы командной строки --urls.--urls command-line argument
  • Ключ конфигурации узла urls.urls host configuration key
  • Переменная среды ASPNETCORE_URLS.ASPNETCORE_URLS environment variable

Эти методы удобны, если нужно, чтобы код работал с серверами, отличными от Kestrel.These methods are useful for making code work with servers other than Kestrel. Не забывайте о следующих ограничениях.However, be aware of the following limitations:

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этом разделе).HTTPS can't be used with these approaches unless a default certificate is provided in the HTTPS endpoint configuration (for example, using KestrelServerOptions configuration or a configuration file as shown earlier in this topic).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.When both the Listen and UseUrls approaches are used simultaneously, the Listen endpoints override the UseUrls endpoints.

Конфигурация конечной точки IISIIS endpoint configuration

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls.When using IIS, the URL bindings for IIS override bindings are set by either Listen or UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.For more information, see the ASP.NET Core Module topic.

ListenOptions.ProtocolsListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера.The Protocols property establishes the HTTP protocols (HttpProtocols) enabled on a connection endpoint or for the server. Значение свойства Protocols должно входить в перечисление HttpProtocols.Assign a value to the Protocols property from the HttpProtocols enum.

Значение перечисления HttpProtocolsHttpProtocols enum value Допустимый протокол подключенияConnection protocol permitted
Http1 Только HTTP/1.1.HTTP/1.1 only. Можно использовать с протоколом TLS или без него.Can be used with or without TLS.
Http2 Только HTTP/2.HTTP/2 only. В основном используется с протоколом TLS.Primarily used with TLS. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.May be used without TLS only if the client supports a Prior Knowledge mode.
Http1AndHttp2 HTTP/1.1 и HTTP/2.HTTP/1.1 and HTTP/2. Для согласования HTTP/2 требуется протокол TLS и подключение с согласованием протокола уровня приложений (ALPN); при их отсутствии используется подключение по умолчанию HTTP/1.1.Requires a TLS and Application-Layer Protocol Negotiation (ALPN) connection to negotiate HTTP/2; otherwise, the connection defaults to HTTP/1.1.

По умолчанию используется протокол HTTP/1.1.The default protocol is HTTP/1.1.

Ограничения TLS для HTTP/2:TLS restrictions for HTTP/2:

  • TSL 1.2 или более поздней версии.TLS version 1.2 or later
  • Повторное согласование отключено.Renegotiation disabled
  • Сжатие отключено.Compression disabled
  • Минимальные размеры обмена временными ключами:Minimum ephemeral key exchange sizes:
    • эллиптическая кривая Диффи-Хелмана (ECDHE) [RFC4492] – не менее 224 бит;Elliptic curve Diffie-Hellman (ECDHE) [RFC4492] – 224 bits minimum
    • конечное поле Диффи-Хелмана (DHE) [TLS12] – не менее 2048 бит;Finite field Diffie-Hellman (DHE) [TLS12] – 2048 bits minimum
  • Набор шифров не внесен в список блокировок.Cipher suite not blacklisted

По умолчанию поддерживается TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] с эллиптической кривой P-256 [FIPS186].TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] with the P-256 elliptic curve [FIPS186] is supported by default.

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000.The following example permits HTTP/1.1 and HTTP/2 connections on port 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:Connections are secured by TLS with a supplied certificate:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Listen(IPAddress.Any, 8000, listenOptions =>
            {
                listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });

Также вы можете создать реализацию IConnectionAdapter для фильтрации подтверждений TLS для каждого соединения по конкретным шифрам:Optionally create an IConnectionAdapter implementation to filter TLS handshakes on a per-connection basis for specific ciphers:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, options) =>
        {
            options.Listen(IPAddress.Any, 8000, listenOptions =>
            {
                listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
                listenOptions.UseHttps("testCert.pfx", "testPassword");
                listenOptions.ConnectionAdapters.Add(new TlsFilterAdapter());
            });
        });
private class TlsFilterAdapter : IConnectionAdapter
{
    public bool IsHttps => false;

    public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
    {
        var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();

        // Throw NotSupportedException for any cipher algorithm that you don't
        // wish to support. Alternatively, define and compare
        // ITlsHandshakeFeature.CipherAlgorithm to a list of acceptable cipher
        // suites.
        //
        // A ITlsHandshakeFeature.CipherAlgorithm of CipherAlgorithmType.Null
        // indicates that no cipher algorithm supported by Kestrel matches the
        // requested algorithm(s).
        if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
        {
            throw new NotSupportedException("Prohibited cipher: " + tlsFeature.CipherAlgorithm);
        }

        return Task.FromResult<IAdaptedConnection>(new AdaptedConnection(context.ConnectionStream));
    }

    private class AdaptedConnection : IAdaptedConnection
    {
        public AdaptedConnection(Stream adaptedStream)
        {
            ConnectionStream = adaptedStream;
        }

        public Stream ConnectionStream { get; }

        public void Dispose()
        {
        }
    }
}

Выбор протокола из конфигурацииSet the protocol from configuration

CreateDefaultBuilder по умолчанию вызывает serverOptions.Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel.CreateDefaultBuilder calls serverOptions.Configure(context.Configuration.GetSection("Kestrel")) by default to load Kestrel configuration.

В следующем примере appsettings.json для всех конечных точек Kestrel устанавливается протокол подключения по умолчанию (HTTP/1.1 и HTTP/2):In the following appsettings.json example, a default connection protocol (HTTP/1.1 and HTTP/2) is established for all of Kestrel's endpoints:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

В следующем примере файла конфигурации задается протокол соединения для конкретной конечной точки:The following configuration file example establishes a connection protocol for a specific endpoint:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsDefaultCert": {
        "Url": "https://localhost:5001",
        "Protocols": "Http1AndHttp2"
      }
    }
  }
}

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.Protocols specified in code override values set by configuration.

Конфигурация транспортаTransport configuration

После выпуска ASP.NET Core 2.1 транспорт Kestrel по умолчанию основан не на Libuv, а на управляемых сокетах.With the release of ASP.NET Core 2.1, Kestrel's default transport is no longer based on Libuv but instead based on managed sockets. Это критическое изменение для приложений ASP.NET Core 2.0, которые обновляются до версии 2.1, если они вызывают UseLibuv и зависят от одного из следующих пакетов:This is a breaking change for ASP.NET Core 2.0 apps upgrading to 2.1 that call UseLibuv and depend on either of the following packages:

Для ASP.NET Core 2.1 или более поздней версии проекты, которые используют метапакет Microsoft.AspNetCore.App и требуют использования Libuv:For ASP.NET Core 2.1 or later projects that use the Microsoft.AspNetCore.App metapackage and require the use of Libuv:

  • Добавляют зависимость для пакета Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv к файлу проекта приложения:Add a dependency for the Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv package to the app's project file:

    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv"
                      Version="<LATEST_VERSION>" />
    
  • Вызов UseLibuv:Call UseLibuv:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseLibuv()
                .UseStartup<Startup>();
    }
    

Префиксы URL-адресовURL prefixes

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.When using UseUrls, --urls command-line argument, urls host configuration key, or ASPNETCORE_URLS environment variable, the URL prefixes can be in any of the following formats.

Допустимы только префиксы URL-адресов HTTP.Only HTTP URL prefixes are valid. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.Kestrel doesn't support HTTPS when configuring URL bindings using UseUrls.

  • IPv4-адрес с номером портаIPv4 address with port number

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.0.0.0.0 is a special case that binds to all IPv4 addresses.

  • IPv6-адрес с номером портаIPv6 address with port number

    http://[0:0:0:0:0:ffff:4137:270a]:80/
    

    [::] является IPv6-аналогом IPv4-адреса 0.0.0.0.[::] is the IPv6 equivalent of IPv4 0.0.0.0.

  • Имя узла с номером портаHost name with port number

    http://contoso.com:80/
    http://*:80/
    

    Имена узлов, * и +, не являются особыми.Host names, *, and +, aren't special. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6.Anything not recognized as a valid IP address or localhost binds to all IPv4 and IPv6 IPs. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер, такой как IIS, Nginx или Apache.To bind different host names to different ASP.NET Core apps on the same port, use HTTP.sys or a reverse proxy server, such as IIS, Nginx, or Apache.

    Предупреждение

    Для размещения в конфигурации обратного прокси-сервера требуется фильтрация узлов.Hosting in a reverse proxy configuration requires host filtering.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером портаHost localhost name with port number or loopback IP with port number

    http://localhost:5000/
    http://127.0.0.1:5000/
    http://[::1]:5000/
    

    Когда указан localhost, Kestrel пытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6.When localhost is specified, Kestrel attempts to bind to both IPv4 and IPv6 loopback interfaces. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не запускается.If the requested port is in use by another service on either loopback interface, Kestrel fails to start. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего, это отсутствие поддержки IPv6), Kestrel заносит в журнал предупреждение.If either loopback interface is unavailable for any other reason (most commonly because IPv6 isn't supported), Kestrel logs a warning.

Фильтрация узловHost filtering

Хотя Kestrel поддерживает конфигурации с использованием префиксов, такие как http://example.com:5000, Kestrel не учитывает имя узла.While Kestrel supports configuration based on prefixes such as http://example.com:5000, Kestrel largely ignores the host name. Узел localhost является особым случаем, используемым для привязки к адресам замыкания на себя.Host localhost is a special case used for binding to loopback addresses. Любой узел, отличный от явного IP-адреса, привязывается ко всем общедоступным IP-адресам.Any host other than an explicit IP address binds to all public IP addresses. Заголовки Host не проверяются.Host headers aren't validated.

В качестве обходного решения используйте ПО промежуточного слоя фильтрации узлов.As a workaround, use Host Filtering Middleware. ПО промежуточного слоя фильтрации узла предоставляется пакетом Microsoft.AspNetCore.HostFiltering, который входит в метапакет Microsoft.AspNetCore.App (ASP.NET Core 2.1 или более поздней версии).Host Filtering Middleware is provided by the Microsoft.AspNetCore.HostFiltering package, which is included in the Microsoft.AspNetCore.App metapackage (ASP.NET Core 2.1 or later). ПО промежуточного слоя добавляется в CreateDefaultBuilder, который вызывает AddHostFiltering:The middleware is added by CreateDefaultBuilder, which calls AddHostFiltering:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

ПО промежуточного слоя фильтрации узлов отключено по умолчанию.Host Filtering Middleware is disabled by default. Чтобы включить ПО промежуточного слоя, определите ключ AllowedHosts в appsettings.json/appsettings.<EnvironmentName>.json.To enable the middleware, define an AllowedHosts key in appsettings.json/appsettings.<EnvironmentName>.json. Значение представляет собой разделенный точками с запятой список имен узлов без номеров портов:The value is a semicolon-delimited list of host names without port numbers:

appsettings.json:appsettings.json:

{
  "AllowedHosts": "example.com;localhost"
}

Примечание

ПО промежуточного слоя перенаправления заголовков имеет также параметр AllowedHosts.Forwarded Headers Middleware also has an AllowedHosts option. ПО промежуточного слоя перенаправления заголовков и ПО промежуточного слоя фильтрации узлов обладают сходными возможностями для различных сценариев.Forwarded Headers Middleware and Host Filtering Middleware have similar functionality for different scenarios. Параметр AllowedHosts с ПО промежуточного слоя перенаправления заголовков подходит для случаев, когда заголовок Host не сохраняется при переадресации запросов с помощью обратного прокси-сервера или подсистемы балансировки нагрузки.Setting AllowedHosts with Forwarded Headers Middleware is appropriate when the Host header isn't preserved while forwarding requests with a reverse proxy server or load balancer. Параметр AllowedHosts с ПО промежуточного слоя фильтрации узлов подходит для случаев, когда Kestrel используется в качестве общедоступного пограничного сервера или если заголовок Host пересылается напрямую.Setting AllowedHosts with Host Filtering Middleware is appropriate when Kestrel is used as a public-facing edge server or when the Host header is directly forwarded.

Дополнительные сведения о ПО промежуточного слоя перенаправления заголовков см. в статье Настройка ASP.NET Core для работы с прокси-серверами и подсистемами балансировки нагрузки.For more information on Forwarded Headers Middleware, see Настройка ASP.NET Core для работы с прокси-серверами и подсистемами балансировки нагрузки.

Дополнительные ресурсыAdditional resources