Kestrel 是一个跨平台的适用于 Asp.NET Core 的 Web 服务器。 Kestrel 是 Web 服务器,默认包括在 ASP.NET Core 项目模板中。

Kestrel 支持以下方案:

macOS 的未来版本将支持 †HTTP/2。

.NET Core 支持的所有平台和版本均支持 Kestrel。

HTTP/2 支持

如果满足以下基本要求,将为 ASP.NET Core 应用提供 HTTP/2:

macOS 的未来版本将支持 †HTTP/2。 ‡Kestrel 在 Windows Server 2012 R2 和 Windows 8.1 上对 HTTP/2 的支持有限。 支持受限是因为可在这些操作系统上使用的受支持 TLS 密码套件列表有限。 可能需要使用椭圆曲线数字签名算法 (ECDSA) 生成的证书来保护 TLS 连接。

如果已建立 HTTP/2 连接,HttpRequest.Protocol 会报告 HTTP/2。

从 .NET Core 3.0 开始,HTTP/2 默认处于启用状态。 有关配置的详细信息,请参阅 Kestrel 选项和 ListenOptions.Protocols 部分。

何时将 Kestrel 与反向代理结合使用

可以单独使用 Kestrel,也可以将其与反向代理服务器(如 Internet Information Services (IIS)、Nginx 或 Apache)结合使用。 反向代理服务器接收来自网络的 HTTP 请求,并将这些请求转发到 Kestrel。

Kestrel 用作边缘(面向 Internet)Web 服务器:

asp.netcore发布部署(ASP.NETCore中的)(1)

Kestrel 用于反向代理配置:

asp.netcore发布部署(ASP.NETCore中的)(2)

无论配置是否使用反向代理服务器,都是受支持的托管配置。

在没有反向代理服务器的情况下用作边缘服务器的 Kestrel 不支持在多个进程间共享相同的 IP 和端口。 如果将 Kestrel 配置为侦听某个端口,Kestrel 会处理该端口的所有流量(无视请求的 Host 标头)。 可以共享端口的反向代理能在唯一的 IP 和端口上将请求转发至 Kestrel。

即使不需要反向代理服务器,使用反向代理服务器可能也是个不错的选择。

反向代理:

警告

采用反向代理配置进行托管需要转接头中间件配置。

ASP.NET Core 应用中的 Kestrel

默认情况下,ASP.NET Core 项目模板使用 Kestrel。 在“Program.cs”中,ConfigureWebHostDefaults 方法调用 UseKestrel:

C#

public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });

有关生成主机的详细信息,请参阅 ASP.NET Core 中的 .NET 通用主机 的“设置主机”和“默认生成器设置”部分 。

若要在调用 ConfigureWebHostDefaults 后提供其他配置,请使用 ConfigureKestrel:

C#

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(serverOptions => { // Set properties and call methods on options }) .UseStartup<Startup>(); });

Kestrel 选项

Kestrel Web 服务器具有约束配置选项,这些选项在面向 Internet 的部署中尤其有用。

对 KestrelServerOptions 类的 Limits 属性设置约束。 Limits 属性包含 KestrelServerLimits 类的实例。

下面的示例使用 Microsoft.AspNetCore.Server.Kestrel.Core 命名空间。

C#

using Microsoft.AspNetCore.Server.Kestrel.Core;

在本文后面的示例中,Kestrel 选项是采用 C# 代码配置的。 还可以使用配置提供程序设置 Kestrel 选项。 例如,文件配置提供程序可以从 appsettings.JSON 或 appsettings.{Environment}.json 文件加载 Kestrel 配置:

JSON复制

{ "Kestrel": { "Limits": { "MaxConcurrentConnections": 100, "MaxConcurrentUpgradedConnections": 100 }, "DisableStringReuse": true } }

备注

KestrelServerOptions 和 终结点配置 可以通过配置提供程序进行配置。 其余的 Kestrel 配置必须采用 C# 代码进行配置。

使用以下方法之一:

上述两种方法适用于任何配置提供程序。

保持活动状态超时

KeepAliveTimeout

获取或设置保持活动状态超时。 默认值为 2 分钟。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

客户端最大连接数

MaxConcurrentConnections MaxConcurrentUpgradedConnections

可使用以下代码为整个应用设置并发打开的最大 TCP 连接数:

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

对于已从 HTTP 或 HTTPS 升级到另一个协议(例如,Websocket 请求)的连接,有一个单独的限制。 连接升级后,不会计入 MaxConcurrentConnections 限制。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

默认情况下,最大连接数不受限制 (NULL)。

请求正文最大大小

MaxRequestBodySize

默认的请求正文最大大小为 30,000,000 字节,大约 28.6 MB。

在 ASP.NET Core MVC 应用中替代限制的推荐方法是在操作方法上使用 RequestSizeLimitAttribute 属性:

C#

[RequestSizeLimit(100000000)] public IActionResult MyActionMethod()

以下示例演示如何为每个请求上的应用配置约束:

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

在中间件中替代特定请求的设置:

C#

app.Run(async (context) => { context.Features.Get<IHttpMaxRequestBodySizeFeature>() .MaxRequestBodySize = 10 * 1024; var minRequestRateFeature = context.Features.Get<IHttpMinRequestBodyDataRateFeature>(); var minResponseRateFeature = context.Features.Get<IHttpMinResponseDataRateFeature>(); if (minRequestRateFeature != null) { minRequestRateFeature.MinDataRate = new MinDataRate( bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); } if (minResponseRateFeature != null) { minResponseRateFeature.MinDataRate = new MinDataRate( bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); }

如果应用在开始读取请求后配置请求限制,则会引发异常。 IsReadOnly 属性指示 MaxRequestBodySize 属性处于只读状态,意味已经无法再配置限制。

当应用在 ASP.NET Core 模块后于进程外运行时,由于 IIS 已设置限制,因此禁用了 Kestrel 的请求正文大小限制。

请求正文最小数据速率

MinRequestBodyDataRate MinResponseDataRate

Kestrel 每秒检查一次数据是否以指定的速率(字节/秒)传入。 如果速率低于最小值,则连接超时。宽限期是 Kestrel 提供给客户端用于将其发送速率提升到最小值的时间量;在此期间不会检查速率。 宽限期有助于避免最初由于 TCP 慢启动而以较慢速率发送数据的连接中断。

默认的最小速率为 240 字节/秒,包含 5 秒的宽限期。

最小速率也适用于响应。 除了属性和接口名称中具有 RequestBody 或 Response 以外,用于设置请求限制和响应限制的代码相同。

以下示例演示如何在 Program.cs 中配置最小数据速率:

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

在中间件中替代每个请求的最低速率限制:

C#

app.Run(async (context) => { context.Features.Get<IHttpMaxRequestBodySizeFeature>() .MaxRequestBodySize = 10 * 1024; var minRequestRateFeature = context.Features.Get<IHttpMinRequestBodyDataRateFeature>(); var minResponseRateFeature = context.Features.Get<IHttpMinResponseDataRateFeature>(); if (minRequestRateFeature != null) { minRequestRateFeature.MinDataRate = new MinDataRate( bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); } if (minResponseRateFeature != null) { minResponseRateFeature.MinDataRate = new MinDataRate( bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); }

用于 HTTP/2 请求的 HttpContext.Features 中不存在前面示例中引用的 IHttpMinResponseDataRateFeature,因为鉴于协议支持请求多路复用,HTTP/2 通常不支持按请求修改速率限制。 不过,用于 HTTP/2 请求的 HttpContext.Features 中仍存在 IHttpMinRequestBodyDataRateFeature,因为仍可以通过将 IHttpMinRequestBodyDataRateFeature.MinDataRate 设置为 null(甚至对于 HTTP/2 请求),按请求完全禁用读取速率限制。 对于给定 HTTP/2 请求,尝试读取 IHttpMinRequestBodyDataRateFeature.MinDataRate 或尝试将它设置为除 null 以外的值会导致 NotSupportedException 抛出。

通过 KestrelServerOptions.Limits 配置的服务器范围的速率限制仍适用于 HTTP/1.x 和 HTTP/2 连接。

请求标头超时

RequestHeadersTimeout

获取或设置服务器接收请求标头所花费的最大时间量。 默认值为 30 秒。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; serverOptions.Limits.MaxRequestBodySize = 10 * 1024; serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); serverOptions.Listen(IPAddress.Loopback, 5000); serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1); })

每个连接的最大流

Http2.MaxStreamsPerConnection 限制每个 HTTP/2 连接的并发请求流的数量。 拒绝过多的流。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.MaxStreamsPerConnection = 100; });

默认值为 100。

标题表大小

HPACK 解码器解压缩 HTTP/2 连接的 HTTP 标头。 Http2.HeaderTableSize 限制 HPACK 解码器使用的标头压缩表的大小。 该值以八位字节提供,且必须大于零 (0)。

C#复制

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.HeaderTableSize = 4096; });

默认值为 4096。

最大帧大小

Http2.MaxFrameSize 表示服务器接收或发送的 HTTP/2 连接帧有效负载的最大允许大小。 该值以八位字节提供,必须介于 2^14 (16,384) 和 2^24-1 (16,777,215) 之间。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.MaxFrameSize = 16384; });

默认值为 2^14 (16,384)。

最大请求标头大小

Http2.MaxRequestHeaderFieldSize 表示请求标头值的允许的最大大小(用八进制表示)。 此限制适用于名称和值的压缩和未压缩表示形式。 该值必须大于零 (0)。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192; });

默认值为 8192。

初始连接窗口大小

Http2.InitialConnectionWindowSize 表示服务器一次性缓存的最大请求主体数据大小(每次连接时在所有请求(流)中汇总,以字节为单位)。 请求也受 Http2.InitialStreamWindowSize 限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072; });

默认值为 128 KB (131,072)。

初始流窗口大小

Http2.InitialStreamWindowSize 表示服务器针对每个请求(流)的一次性缓存的最大请求主体数据大小(以字节为单位)。 请求也受 Http2.InitialConnectionWindowSize 限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.Limits.Http2.InitialStreamWindowSize = 98304; });

默认值为 96 KB (98,304)。

预告片

HTTP 尾部类似于 HTTP 标头,只不过它是在发送响应正文后发送的。 IIS 和 HTTP.sys 仅支持 HTTP/2 响应尾部。

C#

if (httpContext.Response.SupportsTrailers()) { httpContext.Response.DeclareTrailer("trailername"); // Write body httpContext.Response.WriteAsync("Hello world"); httpContext.Response.AppendTrailer("trailername", "TrailerValue"); }

在前面的示例代码中:

重置

通过“Reset”,服务器可以使用指定的错误代码重置 HTTP/2 请求。 重置请求被视为中止。

C#复制

var resetFeature = httpContext.Features.Get<IHttpResetFeature>(); resetFeature.Reset(errorCode: 2);

前述代码示例中的 Reset 指定 INTERNAL_ERROR 错误代码。 有关 HTTP/2 错误代码的详细信息,请访问“HTTP/2 规范错误代码”部分。

同步 I/O

AllowSynchronousIO 控制是否允许对请求和响应使用同步 I/O。 默认值为 false。

警告

大量阻止同步 I/O 的操作可能会导致线程池资源不足,进而导致应用无响应。 仅在使用不支持异步 I/O 的库时,才启用 AllowSynchronousIO。

以下示例会启用同步 I/O:

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.AllowSynchronousIO = true; })

有关其他 Kestrel 选项和限制的信息,请参阅:

终结点配置

默认情况下,ASP.NET Core 绑定到:

使用以下内容指定 URL:

采用这些方法提供的值可以是一个或多个 HTTP 和 HTTPS 终结点(如果默认证书可用,则为 HTTPS)。 将值配置为以分号分隔的列表(例如 "Urls": "http://localhost:8000;http://localhost:8001")。

有关这些方法的详细信息,请参阅服务器 URL 和重写配置。

关于开发证书的创建:

某些浏览器需要授予显式权限才能信任本地开发证书。

项目模板将应用配置为默认情况下在 HTTPS 上运行,并包括 HTTPS 重定向和 HSTS 支持。

调用 KestrelServerOptions 上的 Listen 或 ListenUnixSocket 方法以配置 URL 前缀和 Kestrel 的端口。

UseUrls、--urls 命令行参数、urls 主机配置键以及 ASPNETCORE_URLS 环境变量也有用,但具有本节后面注明的限制(必须要有可用于 HTTPS 终结点配置的默认证书)。

KestrelServerOptions 配置:

ConfigureEndpointDefaults(Action<ListenOptions>)

指定一个为每个指定的终结点运行的配置 Action。 多次调用 ConfigureEndpointDefaults,用最新指定的 Action 替换之前的 Action。

C#

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

备注

通过在调用 ConfigureEndpointDefaults 之前调用 Listen 创建的终结点将不会应用默认值。

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

指定一个为每个 HTTPS 终结点运行的配置 Action。 多次调用 ConfigureHttpsDefaults,用最新指定的 Action 替换之前的 Action。

C#

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

备注

通过在调用 ConfigureHttpsDefaults 之前调用 Listen 创建的终结点将不会应用默认值。

Configure(IConfiguration)

创建配置加载程序,用于设置将 IConfiguration 作为输入的 Kestrel。 配置必须针对 Kestrel 的配置节。

ListenOptions.UseHttps

将 Kestrel 配置为使用 HTTPS。

ListenOptions.UseHttps 扩展:

ListenOptions.UseHttps 参数:

在生产中,必须显式配置 HTTPS。 至少必须提供默认证书。

下面要描述的支持的配置:

无配置

Kestrel 在 http://localhost:5000 和 https://localhost:5001 上进行侦听(如果默认证书可用)。

从配置中替换默认证书

CreateDefaultBuilder 在默认情况下调用 Configure(context.Configuration.GetSection("Kestrel")) 来加载 Kestrel 配置。 Kestrel 可以使用默认 HTTPS 应用设置配置架构。 从磁盘上的文件或从证书存储中配置多个终结点,包括要使用的 URL 和证书。

在以下 appsettings.json 示例中:

JSON

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

此外还可以使用任何证书节点的 Path 和 Password,采用证书存储字段指定证书 。 例如,可将 Certificates > Default 证书指定为 :

JSON

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

架构的注意事项:

C#

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

可以直接访问 KestrelServerOptions.ConfigurationLoader 以继续迭代现有加载程序,例如由 CreateDefaultBuilder 提供的加载程序。

更改代码中的默认值

可以使用 ConfigureEndpointDefaults 和 ConfigureHttpsDefaults 更改 ListenOptions 和 HttpsConnectionAdapterOptions 的默认设置,包括重写之前的方案指定的默认证书。 需要在配置任何终结点之前调用 ConfigureEndpointDefaults 和 ConfigureHttpsDefaults。

C#

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

Kestrel 支持 SNI

服务器名称指示 (SNI) 可用于承载相同 IP 地址和端口上的多个域。 为了运行 SNI,客户端在 TLS 握手过程中将进行安全会话的主机名发送至服务器,从而让服务器可以提供正确的证书。 在 TLS 握手后的安全会话期间,客户端将服务器提供的证书用于与服务器进行加密通信。

Kestrel 通过 ServerCertificateSelector 回调支持 SNI。 每次连接调用一次回调,从而允许应用检查主机名并选择合适的证书。

SNI 支持要求:

C#

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); certs["localhost"] = localhostCert; certs["example.com"] = exampleCert; certs["sub.example.com"] = subExampleCert; httpsOptions.ServerCertificateSelector = (connectionContext, name) => { if (name != null && certs.TryGetValue(name, out var cert)) { return cert; } return exampleCert; }; }); }); });

连接日志记录

调用 UseConnectionLogging 以发出用于进行连接上的字节级别通信的调试级别日志。 连接日志记录有助于排查低级通信中的问题,例如在 TLS 加密期间和代理后。 如果 UseConnectionLogging 放置在 UseHttps 之前,则会记录加密的流量。 如果 UseConnectionLogging 放置于 UseHttps 之后,则会记录解密的流量。

C#

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

绑定到 TCP 套接字

Listen 方法绑定至 TCP 套接字,且 options lambda 允许 X.509 证书配置:

C#

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

示例使用 ListenOptions 为终结点配置 HTTPS。 可使用相同 API 为特定终结点配置其他 Kestrel 设置。

在 Windows 上,可以使用 New-SelfSignedCertificate PowerShell cmdlet 创建自签名证书。 有关不支持的示例,请参阅 UpdateIISExpressSSLForChrome.ps1。

在 macOS、Linux 和 Windows 上,可以使用 OpenSSL 创建证书。

绑定到 Unix 套接字

可通过 ListenUnixSocket 侦听 Unix 套接字以提高 Nginx 的性能,如以下示例所示:

C#

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock"); serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions => { listenOptions.UseHttps("testCert.pfx", "testpassword"); }); })

端口 0

如果指定端口号 0,Kestrel 将动态绑定到可用端口。 以下示例演示如何确定 Kestrel 在运行时实际绑定到的端口:

C#

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

限制

使用以下方法配置终结点:

若要将代码用于 Kestrel 以外的服务器,这些方法非常有用。 不过,请注意以下限制:

IIS 终结点配置

使用 IIS 时,由 Listen 或 UseUrls 设置用于 IIS 覆盖绑定的 URL 绑定。 有关详细信息,请参阅 ASP.NET Core 模块主题。

ListenOptions.Protocols

Protocols 属性建立在连接终结点上或为服务器启用的 HTTP 协议(HttpProtocols)。 从 HttpProtocols 枚举向 Protocols 属性赋值。

HTTP/2 的 TLS 限制:

默认情况下,支持具有 P-256 椭圆曲线 [FIPS186] 的 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE]。

以下示例允许端口 8000 上的 HTTP/1.1 和 HTTP/2 连接。 TLS 使用提供的证书来保护连接:

C#

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

使用连接中间件,针对特定密码的每个连接筛选 TLS 握手(如有必要)。

下面的示例针对应用不支持的任何密码算法引发 NotSupportedException。 或者,定义 ITlsHandshakeFeature.CipherAlgorithm 并将其与可接受的密码套件列表进行比较。

没有哪种加密是使用 CipherAlgorithmType.Null 密码算法。

C#

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

C#

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 lambda 进行配置:

C#

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

在 Linux 上,CipherSuitesPolicy 可用于针对每个连接筛选 TLS 握手:

C#

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

从配置中设置协议

CreateDefaultBuilder 在默认情况下调用 serverOptions.Configure(context.Configuration.GetSection("Kestrel")) 来加载 Kestrel 配置。

以下 appsettings.json 示例将 HTTP/1.1 建立为所有终结点的默认连接协议:

JSON

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

以下 appsettings.json 示例将为所有指定终结点建立 HTTP/1.1 连接协议:

JSON复制

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

代码中指定的协议覆盖了由配置设置的值。

URL 前缀

如果使用 UseUrls、--urls 命令行参数、urls 主机配置键或 ASPNETCORE_URLS 环境变量,URL 前缀可采用以下任意格式。

仅 HTTP URL 前缀是有效的。 使用 UseUrls 配置 URL 绑定时,Kestrel 不支持 HTTPS。

主机筛选

尽管 Kestrel 支持基于前缀的配置(例如 http://example.com:5000),但 Kestrel 在很大程度上会忽略主机名。 主机 localhost 是一个特殊情况,用于绑定至环回地址。 除了显式 IP 地址以外的所有主机都绑定至所有公共 IP 地址。 不验证 Host 标头。

解决方法是,使用主机筛选中间件。 主机筛选中间件由 Microsoft.AspNetCore.HostFiltering 包提供,此包为 ASP.NET Core 应用隐式提供。 由调用 AddHostFiltering 的 CreateDefaultBuilder 添加中间件:

C#复制

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

默认情况下,主机筛选中间件处于禁用状态。 要启用该中间件,请在 appsettings.json/appsettings.<EnvironmentName>.json 中定义一个 AllowedHosts 键。 此值是以分号分隔的不带端口号的主机名列表:

appsettings.json:

JSON

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

备注

转接头中间件 同样包含 AllowedHosts 选项。 转接头中间件和主机筛选中间件具有适合不同方案的相似功能。 如果未保留 Host 标头,并且使用反向代理服务器或负载均衡器转接请求,则使用转接头中间件设置 AllowedHosts 比较合适。 将 Kestrel 用作面向公众的边缘服务器或直接转接 Host 标头时,使用主机筛选中间件设置 AllowedHosts 比较合适。

有关转接头中间件的详细信息,请参阅 配置 ASP.NET Core 以使用代理服务器和负载均衡器。

Libuv 传输配置

对于需要使用 Libuv (UseLibuv) 的项目:

HTTP/1.1 请求排出

打开 HTTP 连接非常耗时。 对于 HTTPS 而言,这也是资源密集型。 因此,Kestrel 会尝试按 HTTP/1.1 协议重新使用连接。 请求正文必须完全使用才能允许重新使用连接。 应用不会始终使用请求正文,例如 POST 请求,其中服务器返回重定向或 404 响应。 在 POST 重定向的情况下:

排出过程会在允许重新使用连接与排出任何剩余数据所用的时间之间进行权衡:

有时,你可能想要在写入响应之前或之后立即终止请求。 例如,客户端可能具有限制性的数据上限,因此可以优先考虑限制上传的数据。 在这种情况下,若要终止请求,请从控制器、Razor 页面或中间件调用 HttpContext。

在调用 Abort 时,存在一些注意事项:

调用 Abort 之前调用 HttpResponse.CompleteAsync 可确保服务器已完成写入响应。 但是,客户端行为是不可预测的,在连接中止前它们可能未读取响应。

对于 HTTP/2,此过程又有所不同,因为协议支持在不关闭连接的情况下中止单个请求流。 五秒排出超时不适用。 如果在完成响应后存在任何未读的请求正文数据,则服务器会发送 HTTP/2 RST 帧。 其他请求正文数据帧将被忽略。

如果可能,客户端最好使用 Expect:100-continue 请求标头,然后等到服务器响应后再开始发送请求正文。 这样,客户端便有机会在发送不需要的数据之前检查响应和中止。

,