Поделиться через


Настройка конечных точек для веб-сервера Kestrel для ASP.NET Core

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

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

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 9 этой статьи.

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

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

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 9 этой статьи.

Kestrel конечные точки предоставляют инфраструктуру для прослушивания входящих запросов и маршрутизации их в соответствующее ПО промежуточного слоя. Сочетание адреса и протокола определяет конечную точку.

  • Адрес указывает сетевой интерфейс, который сервер прослушивает для входящих запросов, таких как TCP-порт.
  • Протокол задает связь между клиентом и сервером, например HTTP/1.1, HTTP/2 или HTTP/3.
  • Конечную точку можно защитить с помощью https схемы URL-адреса или UseHttps метода.

Конечные точки можно настроить с помощью URL-адресов, JSON и appsettings.jsonкода. В этой статье описывается, как использовать каждый параметр для настройки конечной точки:

Конечная точка по умолчанию

Новые проекты ASP.NET Core настроены для привязки к случайному порту HTTP от 5000 до 5300 и случайному порту HTTPS от 7000 до 7300. Выбранные порты хранятся в созданном Properties/launchSettings.json файле и могут быть изменены разработчиком. Файл launchSetting.json используется только в локальной разработке.

Если конфигурации конечной точки нет, Kestrel привязывается к http://localhost:5000.

Настройка конечных точек

Kestrel конечные точки прослушивают входящие подключения. При создании конечной точки необходимо настроить адрес, который он будет прослушивать. Обычно это TCP-адрес и номер порта.

Существует несколько вариантов настройки конечных точек:

Настройка конечных точек с URL-адресами

В следующих разделах объясняется, как настроить конечные точки с помощью следующих разделов:

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.
  • Свойство WebApplication.Urls.

Форматы URL-адресов

URL-адреса указывают IP-адреса или адреса узлов с портами и протоколами, на которых должен прослушивать сервер. Порт может быть опущен, если это протокол по умолчанию (обычно 80 и 443). URL-адреса могут находиться в любом из следующих форматов.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

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

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

  • Узел подстановочного знака с номером порта

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

    Что-либо не распознано как допустимый IP-адрес или localhost рассматривается как подстановочный знак, который привязывается ко всем адресам IPv4 и IPv6. Некоторые люди любят использовать * или + быть более явными. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер.

    Примеры обратного прокси-сервера включают IIS, YARP, Nginx и Apache.

  • Имя localhost узла с номером порта или IP-адресом обратного цикла с номером порта

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

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

Несколько префиксов URL-адресов можно указать с помощью разделителя с запятой (;):

http://*:5000;http://localhost:5001;https://hostname:5002

Дополнительные сведения см. в разделе "Переопределение конфигурации".

Префиксы URL-адреса HTTPS

Префиксы URL-адреса HTTPS можно использовать для определения конечных точек только в том случае, если сертификат по умолчанию указан в конфигурации конечной точки HTTPS. Например, используйте KestrelServerOptions конфигурацию или файл конфигурации, как показано далее в этой статье.

Дополнительные сведения см. в разделе "Настройка HTTPS".

Укажите только порты

Приложения и контейнеры часто получают только порт для прослушивания, например порта 80, без дополнительных ограничений, таких как узел или путь. HTTP_PORTS и HTTPS_PORTS — это ключи конфигурации, указывающие порты прослушивания для Kestrel серверов и HTTP.sys. Эти ключи могут быть указаны в виде переменных среды, определенных с DOTNET_ префиксами или ASPNETCORE_ напрямую через любые другие входные данные конфигурации, например appsettings.json. Каждый из них представляет собой список значений портов с запятой, как показано в следующем примере:

ASPNETCORE_HTTP_PORTS=80;8080
ASPNETCORE_HTTPS_PORTS=443;8081

Приведенный выше пример сокращен для следующей конфигурации, которая указывает схему (HTTP или HTTPS) и любой узел или IP-адрес.

ASPNETCORE_URLS=http://*:80/;http://*:8080/;https://*:443/;https://*:8081/

Ключи конфигурации HTTP_PORTS и HTTPS_PORTS имеют более низкий приоритет и переопределяются URL-адресами или значениями, предоставленными непосредственно в коде. Сертификаты по-прежнему необходимо настроить отдельно с помощью механики для HTTPS для конкретного сервера.

Настройка конечных точек в appsettings.json

Kestrel может загружать конечные точки из экземпляра IConfiguration . По умолчанию Kestrel конфигурация загружается из Kestrel раздела и конечных точек настраивается в Kestrel:Endpoints:

{
  "Kestrel": {
    "Endpoints": {
      "MyHttpEndpoint": {
        "Url": "http://localhost:8080"
      }
    }
  }
}

Предшествующий пример:

  • Используется appsettings.json в качестве источника конфигурации. Однако можно использовать любой IConfiguration источник.
  • Добавляет конечную точку с именем MyHttpEndpoint порта 8080.

Дополнительные сведения о настройке конечных точек с помощью JSON см. в последующих разделах этой статьи, посвященных настройке HTTPS и настройке протоколов HTTP в appsettings.json.

Перезагрузка конечных точек из конфигурации

Перезагрузите конфигурацию конечной точки при включении изменения источника конфигурации по умолчанию. Его можно отключить с помощью KestrelServerOptions.Configure(IConfiguration, Boolean).

При сигнале об изменении выполняются следующие действия:

  • Новая конфигурация сравнивается со старой, и любая конечная точка без изменений конфигурации не изменяется.
  • Для удаленных или измененных конечных точек выделяется 5 секунд для завершения обработки запросов и завершения работы.
  • Запускаются новые или измененные конечные точки.

Клиенты, подключающиеся к измененной конечной точке, могут быть отключены или получить отказ в подключении при перезапуске конечной точки.

ConfigurationLoader

KestrelServerOptions.Configure возвращает значение типа KestrelConfigurationLoader. Метод загрузчика Endpoint(String, Action<EndpointConfiguration>) , который можно использовать для дополнения параметров настроенной конечной точки:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    var kestrelSection = context.Configuration.GetSection("Kestrel");

    serverOptions.Configure(kestrelSection)
        .Endpoint("HTTPS", listenOptions =>
        {
            // ...
        });
});

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным WebApplicationBuilder.WebHost.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • KestrelServerOptions.Configure(IConfiguration) можно вызывать несколько раз, но используется только последняя конфигурация, если Load не вызывается явным образом в предыдущих экземплярах. Узел по умолчанию не вызывается Load таким образом, чтобы его раздел конфигурации по умолчанию мог быть заменен.
  • KestrelConfigurationLoader зеркально Listen отражает семейство API из KestrelServerOptions перегрузки Endpoint , поэтому конечные точки кода и конфигурации можно настроить в том же месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Настройка конечных точек в коде

KestrelServerOptions предоставляет методы настройки конечных точек в коде:

Listen Когда api UseUrls используются одновременно, Listen конечные точки переопределяют UseUrls конечные точки.

Привязка к TCP-сокету

ListenLocalhostМетоды Listenи ListenAnyIP методы привязываются к сокету TCP:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

Предшествующий пример:

  • Настраивает конечные точки, прослушивающие порт 5000 и 5001.
  • Настраивает HTTPS для конечной точки с UseHttps помощью метода ListenOptionsрасширения. Дополнительные сведения см. в разделе "Настройка HTTPS" в коде.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Неподдерживаемый пример: UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
});
  • В файле конфигурации Nginx установите для записи server>location>proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Настройка значений по умолчанию конечной точки

ConfigureEndpointDefaults(Action<ListenOptions>) указывает конфигурацию, которая выполняется для каждой указанной конечной точки. Вызов ConfigureEndpointDefaults несколько раз заменяет предыдущую конфигурацию.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

Динамическая привязка портов

При указании Kestrel номера 0 порта динамически привязывается к доступному порту. В следующем примере показано, как определить, к какому порту привязан Kestrel во время выполнения:

app.Run(async (context) =>
{
    var serverAddressFeature = context.Features.Get<IServerAddressesFeature>();

    if (serverAddressFeature is not null)
    {
        var listenAddresses = string.Join(", ", serverAddressFeature.Addresses);

        // ...
    }
});

В некоторых ситуациях динамическая привязка порта недоступна:

Настройка HTTPS

Kestrel поддерживает защиту конечных точек с помощью HTTPS. Данные, отправляемые по протоколу HTTPS, шифруются с помощью протокола TLS для повышения безопасности данных, передаваемых между клиентом и сервером.

Для HTTPS требуется сертификат TLS. Сертификат TLS хранится на сервере и Kestrel настроен для его использования. Приложение может использовать сертификат разработки ASP.NET Core HTTPS в локальной среде разработки. Сертификат разработки не установлен в неразвитых средах. В рабочей среде сертификат TLS должен быть явно настроен. Как минимум необходимо указать сертификат по умолчанию.

Способ настройки HTTPS и сертификата TLS зависит от того, как настроены конечные точки:

Настройка HTTPS в appsettings.json

Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере) возвращается к сертификату, определенному в Certificates:Default разделе или сертификате разработки.

В следующем примере используется appsettings.jsonлюбой источник конфигурации:

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Заметки о схеме

  • Имена конечных точек не учитывает регистр. Например, выражение HTTPS and Https являются эквивалентными.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением. См . форматы URL-адресов, приведенные ранее в этой статье.
  • Эти конечные точки заменяют те, которые определены в конфигурации верхнего уровня Urls , а не добавляются в них. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в Certificates:Default. Если значения по умолчанию недоступны, используется сертификат разработки. Если значений по умолчанию нет и сертификат разработки отсутствует, сервер выдаст исключение и не сможет запуститься.
  • В Certificate этом разделе поддерживается несколько источников сертификатов.
  • Любое количество конечных точек может быть определено в Configuration, если они не вызывают конфликтов портов.

Источники сертификатов

Узлы сертификатов можно настроить для загрузки сертификатов из нескольких источников:

  • Path и Password для загрузки файлов .pfx;
  • Path, KeyPath и Password для загрузки файлов .pem/.crt и .key;
  • Subject и Store для загрузки из хранилища сертификатов.

Например, Certificates:Default сертификат можно указать следующим образом:

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

Настройка сертификатов клиента в appsettings.json

ClientCertificateMode используется для настройки поведения сертификата клиента.

{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "ClientCertificateMode": "AllowCertificate",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Значением по умолчанию является, где Kestrel не запрашивается или требуется ClientCertificateMode.NoCertificateсертификат от клиента.

Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.

Настройка протоколов SSL/TLS в appsettings.json

Протоколы SSL — это протоколы, используемые для шифрования и расшифровки трафика между двумя одноранговыми узлами, обычно клиентом и сервером.

{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "SslProtocols": ["Tls12", "Tls13"],
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Значение по умолчанию SslProtocols.None указывает Kestrel использовать параметры операционной системы по умолчанию для выбора оптимального протокола. Если вам не требуется по какой-либо причине выбрать определенный протокол, используйте значение по умолчанию.

Настройка HTTPS в коде

При использовании Listen API UseHttps метод ListenOptions расширения доступен для настройки HTTPS.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

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

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

Полный UseHttps список перегрузок см. в разделе UseHttps.

Настройка сертификатов клиента в коде

ClientCertificateMode настраивает требования к сертификату клиента.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
    });
});

Значением по умолчанию является, где Kestrel не запрашивается или требуется NoCertificateсертификат от клиента.

Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.

Настройка по умолчанию HTTPS в коде

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>) указывает конфигурацию Action для каждой конечной точки HTTPS. Вызов ConfigureHttpsDefaults несколько раз заменяет предыдущие Action экземпляры последним Action заданным.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

Настройка протоколов SSL/TLS в коде

Протоколы SSL — это протоколы, используемые для шифрования и расшифровки трафика между двумя одноранговыми узлами, традиционно клиентом и сервером.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls13;
    });
});

Настройка фильтра наборов шифров TLS в коде

В Linux для фильтрации подтверждений TLS по каждому соединению можно использовать CipherSuitesPolicy:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.OnAuthenticate = (context, sslOptions) =>
        {
            sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
                new[]
                {
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    // ...
                });
        };
    });
});

Настройка указания имени сервера

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. SNI можно использовать для экономии ресурсов, обслуживая несколько сайтов с одного сервера.

Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

Все веб-сайты нужно выполнять на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.

SNI можно настроить двумя способами:

  • Настроив сопоставление имен узлов и параметров HTTPS в конфигурации. Например, JSON в файле appsettings.json.
  • Создав конечную точку в коде и выбрав сертификат, используя имя узла с обратным вызовом ServerCertificateSelector.

Настройка SNI в appsettings.json

Kestrel поддерживает SNI, как определено в конфигурации. Конечную точку можно настроить с помощью объекта Sni, который содержит сопоставление имен узлов и параметров HTTPS. Имя узла подключения соответствует параметрам, и они используются для этого подключения.

Следующая конфигурация добавляет конечную точку с именем MySniEndpoint, которая использует SNI для выбора параметров HTTPS на основе имени узла:

{
  "Kestrel": {
    "Endpoints": {
      "MySniEndpoint": {
        "Url": "https://*",
        "SslProtocols": ["Tls11", "Tls12"],
        "Sni": {
          "a.example.org": {
            "Protocols": "Http1AndHttp2",
            "SslProtocols": ["Tls11", "Tls12", "Tls13"],
            "Certificate": {
              "Subject": "<subject; required>",
              "Store": "<certificate store; required>",
            },
            "ClientCertificateMode" : "NoCertificate"
          },
          "*.example.org": {
            "Certificate": {
              "Path": "<path to .pfx file>",
              "Password": "$CREDENTIAL_PLACEHOLDER$"
            }
          },
          "*": {
            // At least one subproperty needs to exist per SNI section or it
            // cannot be discovered via IConfiguration
            "Protocols": "Http1",
          }
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Параметры HTTPS, которые можно переопределить с помощью SNI:

Имя узла поддерживает сопоставление с подстановочными знаками:

  • Точное соответствие. Например, a.example.org соответствует a.example.org.
  • Префикс подстановочного знака. Если имеется несколько совпадений с подстановочными знаками, выбирается самый длинный шаблон. Например, *.example.org соответствует b.example.org и c.example.org.
  • Подстановочный знак полностью. * соответствует всем остальным элементам, в том числе клиентам, которые не используют SNI и не отправляют имя узла.

Соответствующая конфигурация SNI применяется к конечной точке подключения, переопределяя значения в этой конечной точке. Если подключение не совпадает с настроенным именем узла SNI, подключение отказано.

Настройка SNI с помощью кода

Kestrel поддерживает SNI с несколькими API обратного вызова:

  • ServerCertificateSelector
  • ServerOptionsSelectionCallback
  • TlsHandshakeCallbackOptions

SNI с обратным вызовом ServerCertificateSelector

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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)
            {
                ["localhost"] = localhostCert,
                ["example.com"] = exampleCert,
                ["sub.example.com"] = subExampleCert
            };

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

                return exampleCert;
            };
        });
    });
});

SNI с обратным вызовом ServerOptionsSelectionCallback

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов ServerOptionsSelectionCallback. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат и конфигурацию TLS. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этим обратным вызовом.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
            {
                if (string.Equals(clientHelloInfo.ServerName, "localhost",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = localhostCert,
                            // Different TLS requirements for this host
                            ClientCertificateRequired = true
                        });
                }

                return new ValueTask<SslServerAuthenticationOptions>(
                    new SslServerAuthenticationOptions
                    {
                        ServerCertificate = exampleCert
                    });
            }, state: null!);
        });
    });
});

SNI с обратным вызовом TlsHandshakeCallbackOptions

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов TlsHandshakeCallbackOptions.OnConnection. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат, конфигурацию TLS и другие параметры сервера. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этим обратным вызовом.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps(new TlsHandshakeCallbackOptions
            {
                OnConnection = context =>
                {
                    if (string.Equals(context.ClientHelloInfo.ServerName, "localhost",
                        StringComparison.OrdinalIgnoreCase))
                    {
                        // Different TLS requirements for this host
                        context.AllowDelayedClientCertificateNegotation = true;

                        return new ValueTask<SslServerAuthenticationOptions>(
                            new SslServerAuthenticationOptions
                            {
                                ServerCertificate = localhostCert
                            });
                    }

                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = exampleCert
                        });
                }
            });
        });
    });
});

Настройка протоколов HTTP

Kestrel поддерживает все часто используемые версии HTTP. Конечные точки можно настроить для поддержки разных версий HTTP с помощью HttpProtocols перечисления, указывающего доступные параметры версии HTTP.

Протокол TLS требуется для поддержки нескольких версий HTTP. Подтверждение установки связи TLS Application-Layer Protocol Negotiation (ALPN) используется для согласования протокола подключения между клиентом и сервером, если конечная точка поддерживает несколько протоколов.

Значение HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http3 Только HTTP/3. Требуется TLS. Клиент может потребоваться настроить только для использования ПРОТОКОЛА HTTP/3.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется, чтобы клиент выбрал HTTP/2 при подтверждении согласования протокола уровня приложений (ALPN); в противном случае используется подключение по умолчанию HTTP/1.1.
Http1AndHttp2AndHttp3 HTTP/1.1, HTTP/2 и HTTP/3. Первый клиентский запрос обычно использует HTTP/1.1 или HTTP/2, а alt-svc заголовок ответа запрашивает обновление клиента до HTTP/3. Для HTTP/2 и HTTP/3 требуется TLS; в противном случае подключение по умолчанию используется по протоколу HTTP/1.1.

Значение протокола по умолчанию для конечной точки HttpProtocols.Http1AndHttp2.

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

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные временные размеры обмена ключами:
    • эллиптическая кривая Диффи — Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи — Хелмана (DHE) [TLS12]: не менее 2048 бит;
  • Набор шифров не запрещен.

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

Настройка протоколов HTTP в appsettings.json

В следующем примере appsettings.json для отдельной конечной точки устанавливается протокол подключения HTTP/1.1:

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

Протокол по умолчанию можно настроить в Kestrel:EndpointDefaults разделе. В следующем примере appsettings.json для всех конечных точек устанавливается протокол подключения по умолчанию HTTP/1.1:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1"
    }
  }
}

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

Настройка протоколов HTTP в коде

ListenOptions.Protocols используется для указания протоколов с HttpProtocols перечислением.

В следующем примере настраивается конечная точка для подключений HTTP/1.1, HTTP/2 и HTTP/3 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
    });
});

См. также

Проекты ASP.NET Core настраиваются для привязки случайного порта HTTP в диапазоне 5000–5300 и случайного порта HTTPS в диапазоне 7000–7300. Эта конфигурация по умолчанию указана в созданном Properties/launchSettings.json файле и может быть переопределена. Если порты не указаны, Kestrel выполняет привязку к http://localhost:5000:

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

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

Сертификат разработки доступен только для пользователя, который создает сертификат. В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

НастройкаEndpointDefaults

ConfigureEndpointDefaults(Action<ListenOptions>) указывает конфигурацию Action для каждой указанной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Позволяет Kestrel загружать конечные точки из IConfiguration. Для Kestrel конфигурация должна быть ограничена разделом конфигурации. Перегрузку Configure(IConfiguration, bool) можно использовать для включения перезагрузки конечных точек при изменении источника конфигурации.

По умолчанию конфигурация Kestrel загружается из раздела Kestrel и включается перезагрузка изменений:

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001"
      }
    }
  }
}

Если включена перезагрузка конфигурации и сообщается об изменении, выполняются приведенные ниже действия.

  • Новая конфигурация сравнивается со старой, все конечные точки без изменений конфигурации не изменяются.
  • Для удаленных или измененных конечных точек выделяется 5 секунд для завершения обработки запросов и завершения работы.
  • Запускаются новые или измененные конечные точки.

Клиенты, подключающиеся к измененной конечной точке, могут быть отключены или получить отказ в подключении при перезапуске конечной точки.

ConfigureHttpsDefaults

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>) указывает конфигурацию Action для каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

ListenOptions.UseHttps

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

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

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • 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:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

Если сертификаты считываются с диска, а не в Хранилище сертификатов Windows, содержащий каталог должен иметь соответствующие разрешения, чтобы предотвратить несанкционированный доступ.

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

  • Конфигурация отсутствует
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Конфигурация отсутствует

Kestrel ожидает передачи данных на порту http://localhost:5000.

Замена сертификата по умолчанию из конфигурации

Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

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

  • Установите для AllowInvalid true разрешения использования недопустимых сертификатов (например, самозаверяющий сертификат).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates:Default, или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

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

  • В имена конечных точек регистр не учитывается. Например, выражение HTTPS and Https являются эквивалентными.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в Certificates:Default. Если значения по умолчанию недоступны, используется сертификат разработки. Если значений по умолчанию нет и сертификат разработки отсутствует, сервер выдаст исключение и не сможет запуститься.
  • Раздел Certificate поддерживает несколько источников сертификатов.
  • В конфигурации можно определить любое количество конечных точек, если это не приводит к конфликту портов.

Источники сертификатов

Узлы сертификатов можно настроить для загрузки сертификатов из нескольких источников:

  • Path и Password для загрузки файлов .pfx;
  • Path, KeyPath и Password для загрузки файлов .pem/.crt и .key;
  • Subject и Store для загрузки из хранилища сертификатов.

Например, Certificates:Default сертификат можно указать следующим образом:

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

ConfigurationLoader

Configure(IConfiguration) возвращает KestrelConfigurationLoader с методом Endpoint(String, Action<EndpointConfiguration>), который может использоваться в качестве дополнения для параметров настроенной конечной точки:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    var kestrelSection = context.Configuration.GetSection("Kestrel");

    serverOptions.Configure(kestrelSection)
        .Endpoint("HTTPS", listenOptions =>
        {
            // ...
        });
});

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным WebApplicationBuilder.WebHost.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав Configure(IConfiguration) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // ...
    });

    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // ...
    });
});

Настройка конечных точек посредством указания имени сервера

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

SNI можно настроить двумя способами:

  • Создав конечную точку в коде и выбрав сертификат, используя имя узла с обратным вызовом ServerCertificateSelector.
  • Настроив сопоставление имен узлов и параметров HTTPS в конфигурации. Например, JSON в файле appsettings.json.

SNI с обратным вызовом ServerCertificateSelector

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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)
            {
                ["localhost"] = localhostCert,
                ["example.com"] = exampleCert,
                ["sub.example.com"] = subExampleCert
            };

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

                return exampleCert;
            };
        });
    });
});

SNI с обратным вызовом ServerOptionsSelectionCallback

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов ServerOptionsSelectionCallback. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат и конфигурацию TLS. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этой функцией обратного вызова.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
            {
                if (string.Equals(clientHelloInfo.ServerName, "localhost",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = localhostCert,
                            // Different TLS requirements for this host
                            ClientCertificateRequired = true
                        });
                }

                return new ValueTask<SslServerAuthenticationOptions>(
                    new SslServerAuthenticationOptions
                    {
                        ServerCertificate = exampleCert
                    });
            }, state: null!);
        });
    });
});

SNI с обратным вызовом TlsHandshakeCallbackOptions

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов TlsHandshakeCallbackOptions.OnConnection. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат, конфигурацию TLS и другие параметры сервера. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этой функцией обратного вызова.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps(new TlsHandshakeCallbackOptions
            {
                OnConnection = context =>
                {
                    if (string.Equals(context.ClientHelloInfo.ServerName, "localhost",
                        StringComparison.OrdinalIgnoreCase))
                    {
                        // Different TLS requirements for this host
                        context.AllowDelayedClientCertificateNegotation = true;

                        return new ValueTask<SslServerAuthenticationOptions>(
                            new SslServerAuthenticationOptions
                            {
                                ServerCertificate = localhostCert
                            });
                    }

                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = exampleCert
                        });
                }
            });
        });
    });
});

SNI в конфигурации

Kestrel поддерживает SNI, как определено в конфигурации. Конечную точку можно настроить с помощью объекта Sni, который содержит сопоставление имен узлов и параметров HTTPS. Имя узла подключения сопоставляется с параметрами, которые затем используются для этого подключения.

Следующая конфигурация добавляет конечную точку с именем MySniEndpoint, которая использует SNI для выбора параметров HTTPS на основе имени узла:

{
  "Kestrel": {
    "Endpoints": {
      "MySniEndpoint": {
        "Url": "https://*",
        "SslProtocols": ["Tls11", "Tls12"],
        "Sni": {
          "a.example.org": {
            "Protocols": "Http1AndHttp2",
            "SslProtocols": ["Tls11", "Tls12", "Tls13"],
            "Certificate": {
              "Subject": "<subject; required>",
              "Store": "<certificate store; required>",
            },
            "ClientCertificateMode" : "NoCertificate"
          },
          "*.example.org": {
            "Certificate": {
              "Path": "<path to .pfx file>",
              "Password": "$CREDENTIAL_PLACEHOLDER$"
            }
          },
          "*": {
            // At least one subproperty needs to exist per SNI section or it
            // cannot be discovered via IConfiguration
            "Protocols": "Http1",
          }
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Параметры HTTPS, которые можно переопределить с помощью SNI:

Имя узла поддерживает сопоставление с подстановочными знаками:

  • Точное соответствие. Например, a.example.org соответствует a.example.org.
  • Префикс подстановочного знака. Если определяется несколько совпадений с подстановочными знаками, будет выбран самый длинный шаблон. Например, *.example.org соответствует b.example.org и c.example.org.
  • Подстановочный знак полностью. * соответствует всем остальным элементам, в том числе клиентам, которые не используют SNI и не отправляют имя узла.

Соответствующая конфигурация SNI применяется к конечной точке подключения, переопределяя значения в этой конечной точке. Подключение будет отклонено, если оно не соответствует настроенному имени узла SNI.

Требования SNI

Все веб-сайты нужно выполнять на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.

Протоколы SSL/TLS

Протоколы SSL — это протоколы, используемые для шифрования и расшифровки трафика между двумя одноранговыми узлами, обычно клиентом и сервером.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls13;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "SslProtocols": ["Tls12", "Tls13"],
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Значение по умолчанию SslProtocols.None указывает Kestrel использовать параметры операционной системы по умолчанию для выбора оптимального протокола. Если вам не требуется по какой-либо причине выбрать определенный протокол, используйте значение по умолчанию.

Сертификаты клиента

ClientCertificateMode настраивает требования к сертификату клиента.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "ClientCertificateMode": "AllowCertificate",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault.

По умолчанию используется значение ClientCertificateMode.NoCertificate, где Kestrel не будет запрашивать или требовать сертификат от клиента.

Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик. Это встроенное ПО промежуточного слоя подключения.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Неподдерживаемый пример: UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
});
  • В файле конфигурации Nginx установите для записи server>location>proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту привязан Kestrel во время выполнения:

app.Run(async (context) =>
{
    var serverAddressFeature = context.Features.Get<IServerAddressesFeature>();

    if (serverAddressFeature is not null)
    {
        var listenAddresses = string.Join(", ", serverAddressFeature.Addresses);

        // ...
    }
});

В некоторых ситуациях динамическая привязка порта недоступна:

  • ListenLocalhost
  • Привязка HTTP/1.1 или HTTP/2 на основе TCP с HTTP/3 на основе QUIC.

Ограничения

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

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этой статье).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

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

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

ListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера. Значение свойства Protocols должно входить в перечисление HttpProtocols.

Значение перечисления HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http3 Только HTTP/3. Требуется TLS. Клиент может потребоваться настроить только для использования ПРОТОКОЛА HTTP/3.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется, чтобы клиент выбрал HTTP/2 при подтверждении согласования протокола уровня приложений (ALPN); в противном случае используется подключение по умолчанию HTTP/1.1.
Http1AndHttp2AndHttp3 HTTP/1.1, HTTP/2 и HTTP/3. Первый клиентский запрос обычно использует HTTP/1.1 или HTTP/2, а alt-svc заголовок ответа запрашивает обновление клиента до HTTP/3. Для HTTP/2 и HTTP/3 требуется TLS; в противном случае подключение по умолчанию используется по протоколу HTTP/1.1.

Значение ListenOptions.Protocols по умолчанию для любой конечной точки равно HttpProtocols.Http1AndHttp2.

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

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные временные размеры обмена ключами:
    • эллиптическая кривая Диффи — Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи — Хелмана (DHE) [TLS12]: не менее 2048 бит;
  • Набор шифров не запрещен.

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

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
    });
});

В Linux для фильтрации подтверждений TLS по каждому соединению можно использовать CipherSuitesPolicy:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.OnAuthenticate = (context, sslOptions) =>
        {
            sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
                new[]
                {
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    // ...
                });
        };
    });
});

ПО промежуточного слоя подключения

При необходимости можно использовать ПО промежуточного слоя подключения для фильтрации подтверждений TLS для каждого подключения по конкретным шифрам.

Следующий пример вызывает NotSupportedException для любого алгоритма шифрования, который не поддерживается приложением. Кроме того, определите и сравните ITlsHandshakeFeature.CipherAlgorithm список допустимых наборов шифров.

Шифрование не используется с алгоритмом шифрования CipherAlgorithmType.Null.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");

        listenOptions.Use((context, next) =>
        {
            var tlsFeature = context.Features.Get<ITlsHandshakeFeature>()!;

            if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
            {
                throw new NotSupportedException(
                    $"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
            }

            return next();
        });
    });
});

Установка протокола HTTP из конфигурации

По умолчанию конфигурация Kestrel загружается из раздела Kestrel. В следующем примере appsettings.json для всех конечных точек устанавливается протокол подключения по умолчанию HTTP/1.1:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1"
    }
  }
}

В следующем примере appsettings.json для отдельной конечной точки устанавливается протокол подключения HTTP/1.1:

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

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

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

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

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

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

  • Имя узла с номером порта

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

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер. В качестве обратного прокси-сервера можно использовать IIS, Nginx или Apache.

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

    Для размещения в конфигурации обратного прокси-сервера требуется фильтрация узлов.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

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

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

Проекты ASP.NET Core настраиваются для привязки случайного порта HTTP в диапазоне 5000–5300 и случайного порта HTTPS в диапазоне 7000–7300. Эта конфигурация по умолчанию указана в созданном Properties/launchSettings.json файле и может быть переопределена. Если порты не указаны, Kestrel выполняет привязку к:

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

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

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

Сертификат разработки доступен только для пользователя, который создает сертификат. В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

НастройкаEndpointDefaults

ConfigureEndpointDefaults(Action<ListenOptions>) указывает конфигурацию Action для каждой указанной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Позволяет Kestrel загружать конечные точки из IConfiguration. Для Kestrel конфигурация должна быть ограничена разделом конфигурации. Перегрузку Configure(IConfiguration, bool) можно использовать для включения перезагрузки конечных точек при изменении источника конфигурации.

По умолчанию конфигурация Kestrel загружается из раздела Kestrel и включается перезагрузка изменений:

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001"
      }
    }
  }
}

Если включена перезагрузка конфигурации и сообщается об изменении, выполняются приведенные ниже действия.

  • Новая конфигурация сравнивается со старой, все конечные точки без изменений конфигурации не изменяются.
  • Для удаленных или измененных конечных точек выделяется 5 секунд для завершения обработки запросов и завершения работы.
  • Запускаются новые или измененные конечные точки.

Клиенты, подключающиеся к измененной конечной точке, могут быть отключены или получить отказ в подключении при перезапуске конечной точки.

ConfigureHttpsDefaults

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>) указывает конфигурацию Action для каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // ...
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

ListenOptions.UseHttps

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

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

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • 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:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

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

  • Конфигурация отсутствует
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Конфигурация отсутствует

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).

Замена сертификата по умолчанию из конфигурации

Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

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

  • Установите для AllowInvalid true разрешения использования недопустимых сертификатов (например, самозаверяющий сертификат).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates:Default, или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

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

  • В имена конечных точек регистр не учитывается. Например, выражение HTTPS and Https являются эквивалентными.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в Certificates:Default. Если значения по умолчанию недоступны, используется сертификат разработки. Если значений по умолчанию нет и сертификат разработки отсутствует, сервер выдаст исключение и не сможет запуститься.
  • Раздел Certificate поддерживает несколько источников сертификатов.
  • В конфигурации можно определить любое количество конечных точек, если это не приводит к конфликту портов.

Источники сертификатов

Узлы сертификатов можно настроить для загрузки сертификатов из нескольких источников:

  • Path и Password для загрузки файлов .pfx;
  • Path, KeyPath и Password для загрузки файлов .pem/.crt и .key;
  • Subject и Store для загрузки из хранилища сертификатов.

Например, Certificates:Default сертификат можно указать следующим образом:

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

ConfigurationLoader

Configure(IConfiguration) возвращает KestrelConfigurationLoader с методом Endpoint(String, Action<EndpointConfiguration>), который может использоваться в качестве дополнения для параметров настроенной конечной точки:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    var kestrelSection = context.Configuration.GetSection("Kestrel");

    serverOptions.Configure(kestrelSection)
        .Endpoint("HTTPS", listenOptions =>
        {
            // ...
        });
});

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным WebApplicationBuilder.WebHost.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав Configure(IConfiguration) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // ...
    });

    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // ...
    });
});

Настройка конечных точек посредством указания имени сервера

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

SNI можно настроить двумя способами:

  • Создав конечную точку в коде и выбрав сертификат, используя имя узла с обратным вызовом ServerCertificateSelector.
  • Настроив сопоставление имен узлов и параметров HTTPS в конфигурации. Например, JSON в файле appsettings.json.

SNI с обратным вызовом ServerCertificateSelector

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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)
            {
                ["localhost"] = localhostCert,
                ["example.com"] = exampleCert,
                ["sub.example.com"] = subExampleCert
            };

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

                return exampleCert;
            };
        });
    });
});

SNI с обратным вызовом ServerOptionsSelectionCallback

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов ServerOptionsSelectionCallback. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат и конфигурацию TLS. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этой функцией обратного вызова.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
            {
                if (string.Equals(clientHelloInfo.ServerName, "localhost",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = localhostCert,
                            // Different TLS requirements for this host
                            ClientCertificateRequired = true
                        });
                }

                return new ValueTask<SslServerAuthenticationOptions>(
                    new SslServerAuthenticationOptions
                    {
                        ServerCertificate = exampleCert
                    });
            }, state: null!);
        });
    });
});

SNI с обратным вызовом TlsHandshakeCallbackOptions

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов TlsHandshakeCallbackOptions.OnConnection. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат, конфигурацию TLS и другие параметры сервера. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этой функцией обратного вызова.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps(new TlsHandshakeCallbackOptions
            {
                OnConnection = context =>
                {
                    if (string.Equals(context.ClientHelloInfo.ServerName, "localhost",
                        StringComparison.OrdinalIgnoreCase))
                    {
                        // Different TLS requirements for this host
                        context.AllowDelayedClientCertificateNegotation = true;

                        return new ValueTask<SslServerAuthenticationOptions>(
                            new SslServerAuthenticationOptions
                            {
                                ServerCertificate = localhostCert
                            });
                    }

                    return new ValueTask<SslServerAuthenticationOptions>(
                        new SslServerAuthenticationOptions
                        {
                            ServerCertificate = exampleCert
                        });
                }
            });
        });
    });
});

SNI в конфигурации

Kestrel поддерживает SNI, как определено в конфигурации. Конечную точку можно настроить с помощью объекта Sni, который содержит сопоставление имен узлов и параметров HTTPS. Имя узла подключения сопоставляется с параметрами, которые затем используются для этого подключения.

Следующая конфигурация добавляет конечную точку с именем MySniEndpoint, которая использует SNI для выбора параметров HTTPS на основе имени узла:

{
  "Kestrel": {
    "Endpoints": {
      "MySniEndpoint": {
        "Url": "https://*",
        "SslProtocols": ["Tls11", "Tls12"],
        "Sni": {
          "a.example.org": {
            "Protocols": "Http1AndHttp2",
            "SslProtocols": ["Tls11", "Tls12", "Tls13"],
            "Certificate": {
              "Subject": "<subject; required>",
              "Store": "<certificate store; required>",
            },
            "ClientCertificateMode" : "NoCertificate"
          },
          "*.example.org": {
            "Certificate": {
              "Path": "<path to .pfx file>",
              "Password": "$CREDENTIAL_PLACEHOLDER$"
            }
          },
          "*": {
            // At least one subproperty needs to exist per SNI section or it
            // cannot be discovered via IConfiguration
            "Protocols": "Http1",
          }
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Параметры HTTPS, которые можно переопределить с помощью SNI:

Имя узла поддерживает сопоставление с подстановочными знаками:

  • Точное соответствие. Например, a.example.org соответствует a.example.org.
  • Префикс подстановочного знака. Если определяется несколько совпадений с подстановочными знаками, будет выбран самый длинный шаблон. Например, *.example.org соответствует b.example.org и c.example.org.
  • Подстановочный знак полностью. * соответствует всем остальным элементам, в том числе клиентам, которые не используют SNI и не отправляют имя узла.

Соответствующая конфигурация SNI применяется к конечной точке подключения, переопределяя значения в этой конечной точке. Подключение будет отклонено, если оно не соответствует настроенному имени узла SNI.

Требования SNI

Все веб-сайты нужно выполнять на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.

Протоколы SSL/TLS

Протоколы SSL — это протоколы, используемые для шифрования и расшифровки трафика между двумя одноранговыми узлами, обычно клиентом и сервером.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls13;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "SslProtocols": ["Tls12", "Tls13"],
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Значение по умолчанию SslProtocols.None указывает Kestrel использовать параметры операционной системы по умолчанию для выбора оптимального протокола. Если вам не требуется по какой-либо причине выбрать определенный протокол, используйте значение по умолчанию.

Сертификаты клиента

ClientCertificateMode настраивает требования к сертификату клиента.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "ClientCertificateMode": "AllowCertificate",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault.

По умолчанию используется значение ClientCertificateMode.NoCertificate, где Kestrel не будет запрашивать или требовать сертификат от клиента.

Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик. Это встроенное ПО промежуточного слоя подключения.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Неподдерживаемый пример: UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
});
  • В файле конфигурации Nginx установите для записи server>location>proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту привязан Kestrel во время выполнения:

app.Run(async (context) =>
{
    var serverAddressFeature = context.Features.Get<IServerAddressesFeature>();

    if (serverAddressFeature is not null)
    {
        var listenAddresses = string.Join(", ", serverAddressFeature.Addresses);

        // ...
    }
});

Ограничения

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

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этой статье).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

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

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

ListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера. Значение свойства Protocols должно входить в перечисление HttpProtocols.

Значение перечисления HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется, чтобы клиент выбрал HTTP/2 при подтверждении согласования протокола уровня приложений (ALPN); в противном случае используется подключение по умолчанию HTTP/1.1.

Значение ListenOptions.Protocols по умолчанию для любой конечной точки равно HttpProtocols.Http1AndHttp2.

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

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные временные размеры обмена ключами:
    • эллиптическая кривая Диффи — Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи — Хелмана (DHE) [TLS12]: не менее 2048 бит;
  • Набор шифров не запрещен.

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

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
    });
});

В Linux для фильтрации подтверждений TLS по каждому соединению можно использовать CipherSuitesPolicy:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.OnAuthenticate = (context, sslOptions) =>
        {
            sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
                new[]
                {
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    // ...
                });
        };
    });
});

ПО промежуточного слоя подключения

При необходимости можно использовать ПО промежуточного слоя подключения для фильтрации подтверждений TLS для каждого подключения по конкретным шифрам.

Следующий пример вызывает NotSupportedException для любого алгоритма шифрования, который не поддерживается приложением. Кроме того, определите и сравните ITlsHandshakeFeature.CipherAlgorithm список допустимых наборов шифров.

Шифрование не используется с алгоритмом шифрования CipherAlgorithmType.Null.

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");

        listenOptions.Use((context, next) =>
        {
            var tlsFeature = context.Features.Get<ITlsHandshakeFeature>()!;

            if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
            {
                throw new NotSupportedException(
                    $"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
            }

            return next();
        });
    });
});

Установка протокола HTTP из конфигурации

По умолчанию конфигурация Kestrel загружается из раздела Kestrel. В следующем примере appsettings.json для всех конечных точек устанавливается протокол подключения по умолчанию HTTP/1.1:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1"
    }
  }
}

В следующем примере appsettings.json для отдельной конечной точки устанавливается протокол подключения HTTP/1.1:

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

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

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

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

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

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

  • Имя узла с номером порта

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

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер. В качестве обратного прокси-сервера можно использовать IIS, Nginx или Apache.

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

    Для размещения в конфигурации обратного прокси-сервера требуется фильтрация узлов.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

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

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

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

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

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

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

НастройкаEndpointDefaults

ConfigureEndpointDefaults(Action<ListenOptions>) указывает конфигурацию Action для каждой указанной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // Configure endpoint defaults
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Позволяет Kestrel загружать конечные точки из IConfiguration. Для Kestrel конфигурация должна быть ограничена разделом конфигурации.

Перегрузку Configure(IConfiguration, bool) можно использовать для включения перезагрузки конечных точек при изменении источника конфигурации.

IHostBuilder.ConfigureWebHostDefaults по умолчанию вызывает Configure(context.Configuration.GetSection("Kestrel"), reloadOnChange: true), чтобы загрузить конфигурацию Kestrel и включить перезагрузку.

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001"
      }
    }
  }
}

Если включена перезагрузка конфигурации и сообщается об изменении, выполняются приведенные ниже действия.

  • Новая конфигурация сравнивается со старой, все конечные точки без изменений конфигурации не изменяются.
  • Для удаленных или измененных конечных точек выделяется 5 секунд для завершения обработки запросов и завершения работы.
  • Запускаются новые или измененные конечные точки.

Клиенты, подключающиеся к измененной конечной точке, могут быть отключены или получить отказ в подключении при перезапуске конечной точки.

ConfigureHttpsDefaults

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>) указывает конфигурацию Action для каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // certificate is an X509Certificate2
        listenOptions.ServerCertificate = certificate;
    });
});

Примечание.

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

ListenOptions.UseHttps

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

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

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • 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:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

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

  • Конфигурация отсутствует
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Конфигурация отсутствует

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).

Замена сертификата по умолчанию из конфигурации

Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

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

  • Установите для AllowInvalid true разрешения использования недопустимых сертификатов (например, самозаверяющий сертификат).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates:Default, или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

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

  • В имена конечных точек регистр не учитывается. Например, выражение HTTPS and Https являются эквивалентными.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в Certificates:Default. Если значения по умолчанию недоступны, используется сертификат разработки. Если значений по умолчанию нет и сертификат разработки отсутствует, сервер выдаст исключение и не сможет запуститься.
  • Раздел Certificate поддерживает несколько источников сертификатов.
  • В конфигурации можно определить любое количество конечных точек, если это не приводит к конфликту портов.

Источники сертификатов

Узлы сертификатов можно настроить для загрузки сертификатов из нескольких источников:

  • Path и Password для загрузки файлов .pfx;
  • Path, KeyPath и Password для загрузки файлов .pem/.crt и .key;
  • Subject и Store для загрузки из хранилища сертификатов.

Например, Certificates:Default сертификат можно указать следующим образом:

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

ConfigurationLoader

options.Configure(context.Configuration.GetSection("{SECTION}")) возвращает KestrelConfigurationLoader с методом .Endpoint(string name, listenOptions => { }), который может использоваться в качестве дополнения для параметров настроенной конечной точки:

webBuilder.UseKestrel((context, serverOptions) =>
{
    serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
        .Endpoint("HTTPS", listenOptions =>
        {
            listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
        });
});

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным CreateDefaultBuilder.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав options.Configure(context.Configuration.GetSection("{SECTION}")) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // Configure endpoint defaults
    });

    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls12;
    });
});

Настройка конечных точек посредством указания имени сервера

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

SNI можно настроить двумя способами:

  • Создав конечную точку в коде и выбрав сертификат, используя имя узла с обратным вызовом ServerCertificateSelector.
  • Настроив сопоставление имен узлов и параметров HTTPS в конфигурации. Например, JSON в файле appsettings.json.

SNI с обратным вызовом ServerCertificateSelector

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат. Приведенный ниже код обратного вызова можно использовать в вызове метода ConfigureWebHostDefaults файла Program.cs проекта:

// using System.Security.Cryptography.X509Certificates;
// using Microsoft.AspNetCore.Server.Kestrel.Https;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.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)
            {
                { "localhost", localhostCert },
                { "example.com", exampleCert },
                { "sub.example.com", subExampleCert },
            };            

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

                return exampleCert;
            };
        });
    });
});

SNI с обратным вызовом ServerOptionsSelectionCallback

Kestrel поддерживает дополнительную динамическую конфигурацию TLS через обратный вызов ServerOptionsSelectionCallback. Функция обратного вызова вызывается один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат и конфигурацию TLS. Сертификаты по умолчанию и ConfigureHttpsDefaults не используются с этой функцией обратного вызова.

// using System.Security.Cryptography.X509Certificates;
// using Microsoft.AspNetCore.Server.Kestrel.Https;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.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);

            listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
            {
                if (string.Equals(clientHelloInfo.ServerName, "localhost", StringComparison.OrdinalIgnoreCase))
                {
                    return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions
                    {
                        ServerCertificate = localhostCert,
                        // Different TLS requirements for this host
                        ClientCertificateRequired = true,
                    });
                }

                return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions
                {
                    ServerCertificate = exampleCert,
                });
            }, state: null);
        });
    });
});

SNI в конфигурации

Kestrel поддерживает SNI, как определено в конфигурации. Конечную точку можно настроить с помощью объекта Sni, который содержит сопоставление имен узлов и параметров HTTPS. Имя узла подключения сопоставляется с параметрами, которые затем используются для этого подключения.

Следующая конфигурация добавляет конечную точку с именем MySniEndpoint, которая использует SNI для выбора параметров HTTPS на основе имени узла:

{
  "Kestrel": {
    "Endpoints": {
      "MySniEndpoint": {
        "Url": "https://*",
        "SslProtocols": ["Tls11", "Tls12"],
        "Sni": {
          "a.example.org": {
            "Protocols": "Http1AndHttp2",
            "SslProtocols": ["Tls11", "Tls12", "Tls13"],
            "Certificate": {
              "Subject": "<subject; required>",
              "Store": "<certificate store; required>",
            },
            "ClientCertificateMode" : "NoCertificate"
          },
          "*.example.org": {
            "Certificate": {
              "Path": "<path to .pfx file>",
              "Password": "$CREDENTIAL_PLACEHOLDER$"
            }
          },
          "*": {
            // At least one subproperty needs to exist per SNI section or it
            // cannot be discovered via IConfiguration
            "Protocols": "Http1",
          }
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Параметры HTTPS, которые можно переопределить с помощью SNI:

Имя узла поддерживает сопоставление с подстановочными знаками:

  • Точное соответствие. Например, a.example.org соответствует a.example.org.
  • Префикс подстановочного знака. Если определяется несколько совпадений с подстановочными знаками, будет выбран самый длинный шаблон. Например, *.example.org соответствует b.example.org и c.example.org.
  • Подстановочный знак полностью. * соответствует всем остальным элементам, в том числе клиентам, которые не используют SNI и не отправляют имя узла.

Соответствующая конфигурация SNI применяется к конечной точке подключения, переопределяя значения в этой конечной точке. Подключение будет отклонено, если оно не соответствует настроенному имени узла SNI.

Требования SNI

  • Запуск на целевой платформе netcoreapp2.1 или более поздней версии. В net461 или более поздней версии обратный вызов выполняется, но name всегда имеет значение null. name также имеет значение null, если клиент не предоставляет параметр имени узла при подтверждении TLS.
  • Все веб-сайты выполняются на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.

Протоколы SSL/TLS

Протоколы SSL — это протоколы, используемые для шифрования и расшифровки трафика между двумя одноранговыми узлами, обычно клиентом и сервером.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls13;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "SslProtocols": ["Tls12", "Tls13"],
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

Значение по умолчанию SslProtocols.None указывает Kestrel использовать параметры операционной системы по умолчанию для выбора оптимального протокола. Если вам не требуется по какой-либо причине выбрать определенный протокол, используйте значение по умолчанию.

Сертификаты клиента

ClientCertificateMode настраивает требования к сертификату клиента.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
    });
});
{
  "Kestrel": {
    "Endpoints": {
      "MyHttpsEndpoint": {
        "Url": "https://localhost:5001",
        "ClientCertificateMode": "AllowCertificate",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      }
    }
  }
}

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

В предыдущем примере пароли сертификатов хранятся в виде обычного текста в appsettings.json. Токен $CREDENTIAL_PLACEHOLDER$ используется в качестве заполнителя для пароля каждого сертификата. Сведения о безопасном хранении паролей сертификатов в средах разработки см. в статье Защита секретов в разработке. Сведения о безопасном хранении паролей сертификатов в рабочих средах см. в статье Поставщик конфигурации Azure Key Vault. Секреты, используемые для разработки, не следует использовать для рабочей среды или тестирования.

По умолчанию используется значение ClientCertificateMode.NoCertificate, где Kestrel не будет запрашивать или требовать сертификат от клиента.

Дополнительные сведения см. в статье Настройка проверки подлинности по сертификату в ASP.NET Core.

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик. Это встроенное ПО промежуточного слоя подключения.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

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

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                serverOptions.Listen(IPAddress.Loopback, 5000);
                serverOptions.Listen(IPAddress.Loopback, 5001, 
                    listenOptions =>
                    {
                        listenOptions.UseHttps("testCert.pfx", 
                            "testPassword");
                    });
            })
            .UseStartup<Startup>();
        });

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Неподдерживаемый пример: UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testpassword");
        });
})
  • В файле конфигурации Nginx установите для записи server>location>proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту привязан Kestrel во время выполнения:

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

Когда приложение выполняется, в выходных данных в окне консоли указывается динамический порт, по которому можно связаться с приложением:

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

Ограничения

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

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этой статье).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

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

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

ListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера. Значение свойства Protocols должно входить в перечисление HttpProtocols.

Значение перечисления HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется, чтобы клиент выбрал HTTP/2 при подтверждении согласования протокола уровня приложений (ALPN); в противном случае используется подключение по умолчанию HTTP/1.1.

Значение ListenOptions.Protocols по умолчанию для любой конечной точки равно HttpProtocols.Http1AndHttp2.

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

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные временные размеры обмена ключами:
    • эллиптическая кривая Диффи — Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи — Хелмана (DHE) [TLS12]: не менее 2048 бит;
  • Набор шифров не запрещен.

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

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

В Linux для фильтрации подтверждений TLS по каждому соединению можно использовать CipherSuitesPolicy:

// using System.Net.Security;
// using Microsoft.AspNetCore.Hosting;
// using Microsoft.AspNetCore.Server.Kestrel.Core;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Hosting;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.OnAuthenticate = (context, sslOptions) =>
        {
            sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
                new[]
                {
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    // ...
                });
        };
    });
});

ПО промежуточного слоя подключения

При необходимости можно использовать ПО промежуточного слоя подключения для фильтрации подтверждений TLS для каждого подключения по конкретным шифрам.

Следующий пример вызывает NotSupportedException для любого алгоритма шифрования, который не поддерживается приложением. Также можно определить и сравнить ITlsHandshakeFeature.CipherAlgorithm со списком приемлемых наборов шифров.

При использовании алгоритма шифрования CipherAlgorithmType.Null шифрование не используется.

// using System.Net;
// using Microsoft.AspNetCore.Connections;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.UseTlsFilter();
    });
});
using System;
using System.Security.Authentication;
using Microsoft.AspNetCore.Connections.Features;

namespace Microsoft.AspNetCore.Connections
{
    public static class TlsFilterConnectionMiddlewareExtensions
    {
        public static IConnectionBuilder UseTlsFilter(
            this IConnectionBuilder builder)
        {
            return builder.Use((connection, next) =>
            {
                var tlsFeature = connection.Features.Get<ITlsHandshakeFeature>();

                if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
                {
                    throw new NotSupportedException("Prohibited cipher: " +
                        tlsFeature.CipherAlgorithm);
                }

                return next();
            });
        }
    }
}

Фильтрацию соединений также можно настроить с помощью лямбды IConnectionBuilder:

// using System;
// using System.Net;
// using System.Security.Authentication;
// using Microsoft.AspNetCore.Connections;
// using Microsoft.AspNetCore.Connections.Features;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.Use((context, next) =>
        {
            var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();

            if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
            {
                throw new NotSupportedException(
                    $"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
            }

            return next();
        });
    });
});

Установка протокола HTTP из конфигурации

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

В следующем примере appsettings.json для всех конечных точек устанавливается протокол подключения по умолчанию HTTP/1.1:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1"
    }
  }
}

В следующем примере appsettings.json для отдельной конечной точки устанавливается протокол подключения HTTP/1.1:

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

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

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

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

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

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

  • Имя узла с номером порта

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

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер. В качестве обратного прокси-сервера можно использовать IIS, Nginx или Apache.

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

    Для размещения в конфигурации обратного прокси-сервера требуется фильтрация узлов.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

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

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.