ASP.NET Core 中的 Kestrel Web 服务器实现
Kestrel
是一个跨平台的适用于 ASP.NET Core
的 Web 服务器。 Kestrel
是 Web 服务器,默认包括在 ASP.NET Core
项目模板中。
Kestrel
支持以下方案:
HTTPS
WebSocket
的不透明升级Nginx
高性能的 Unix 套接字HTTP/2
(除 macOS以外)macOS
的未来版本将支持HTTP/2。
.NET Core 支持的所有平台和版本均支持 Kestrel
。
HTTP/2
支持如果满足以下基本要求,将为 ASP.NET Core
应用提供 HTTP/2
:
Windows Server 2016/Windows 10
或更高版本OpenSSL 1.0.2
或更高版本的 Linux
(例如,Ubuntu 16.04 或更高版本).NET Core 2.2
或更高版本macOS
的未来版本将支持HTTP/2
。Kestrel
在 Windows Server 2012 R2
和 Windows 8.1
上对 HTTP/2
的支持有限。支持受限是因为可在这些操作系统上使用的受支持 TLS
密码套件列表有限。 可能需要使用椭圆曲线数字签名算法 (ECDSA
) 生成的证书来保护 TLS
连接。
如果已建立 HTTP/2
连接,HttpRequest.Protocol
会报告 HTTP/2
。
默认情况下,禁用 HTTP/2
。 有关配置的详细信息,请参阅 Kestrel
选项和 ListenOptions.Protocols
部分。
Kestrel
和反向代理可以单独使用 Kestrel
,也可以将其与反向代理服务器(如 Internet Information Services
(IIS)、Nginx
或 Apache
)结合使用。 反向代理服务器接收来自网络的 HTTP
请求,并将这些请求转发到 Kestrel
。
Kestrel 用作边缘(面向 Internet)Web 服务器:
Kestrel 用于反向代理配置:
无论配置是否使用反向代理服务器——,都是从 Internet
接收请求的 ASP.NET Core 2.1
或更高版本应用的支持托管配置。
在没有反向代理服务器的情况下用作边缘服务器的 Kestrel
不支持在多个进程间共享相同的 IP 和端口。 如果将 Kestrel
配置为侦听某个端口,Kestrel
会处理该端口的所有流量(无视请求的 Host
标头)。 可以共享端口的反向代理能在唯一的 IP
和端口上将请求转发至 Kestrel
。
即使不需要反向代理服务器,使用反向代理服务器可能也是个不错的选择。
反向代理:
HTTPS
) 配置。 仅反向代理服务器需要 X.509
证书,并且该服务器可使用普通 HTTP在内部网络上与应用服务器通信。警告
采用反向代理配置进行托管需要主机筛选。
ASP.NET Core
应用中使用Kestrel
Microsoft.AspNetCore.App
元包中包括 Microsoft.AspNetCore.Server.Kestrel
包(ASP.NET Core 2.1
或更高版本)。
默认情况下,ASP.NET Core
项目模板使用 Kestrel
。 在 Program.cs
中,模板代码调用 CreateDefaultBuilder
,后者在后台调用 UseKestrel
。
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
若要在调用 CreateDefaultBuilder
后提供其他配置,请使用 ConfigureKestrel
:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
// Set properties and call methods on options
});
如果应用未调用 CreateDefaultBuilder
来设置主机,请在调用 ConfigureKestrel
之前先调用 UseKestrel
:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
.UseIISIntegration()
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
// Set properties and call methods on options
})
.Build();
host.Run();
}
Kestrel
选项Kestrel Web
服务器具有约束配置选项,这些选项在面向 Internet
的部署中尤其有用。
可在 KestrelServerOptions
类的 Limits
属性上设置约束。 Limits
属性包含 KestrelServerLimits
类的实例。
MaxConcurrentConnections
MaxConcurrentUpgradedConnections
可使用以下代码为整个应用设置并发打开的最大 TCP 连接数:
.ConfigureKestrel((context, options) =>
{
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
options.Limits.MaxRequestBodySize = 10 * 1024;
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
对于已从 HTTP
或 HTTPS
升级到另一个协议(例如,Websocket
请求)的连接,有一个单独的限制。 连接升级后,不会计入 MaxConcurrentConnections
限制。
.ConfigureKestrel((context, options) =>
{
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
options.Limits.MaxRequestBodySize = 10 * 1024;
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
默认情况下,最大连接数不受限制 (NULL
)。
MaxRequestBodySize
默认的请求正文最大大小为 30,000,000 字节,大约 28.6 MB。
在 ASP.NET Core MVC
应用中替代限制的推荐方法是在操作方法上使用 RequestSizeLimit
属性:
[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()
以下示例演示如何为每个请求上的应用配置约束:
.ConfigureKestrel((context, options) =>
{
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
options.Limits.MaxRequestBodySize = 10 * 1024;
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
如果在应用开始读取请求后尝试配置请求限制,则会引发异常。 IsReadOnly
属性指示 MaxRequestBodySize
属性处于只读状态,意味已经无法再配置限制。
MinRequestBodyDataRate
MinResponseDataRate
Kestrel
每秒检查一次数据是否以指定的速率(字节/秒)传入。 如果速率低于最小值,则连接超时。宽限期是 Kestrel
提供给客户端用于将其发送速率提升到最小值的时间量;在此期间不会检查速率。 宽限期有助于避免最初由于 TCP
慢启动而以较慢速率发送数据的连接中断。
默认的最小速率为 240
字节/秒,包含 5 秒的宽限期。
最小速率也适用于响应。 除了属性和接口名称中具有 RequestBody
或 Response
以外,用于设置请求限制和响应限制的代码相同。
以下示例演示如何在 Program.cs
中配置最小数据速率:
.ConfigureKestrel((context, options) =>
{
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
options.Limits.MaxRequestBodySize = 10 * 1024;
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
可以在中间件中替代每个请求的最低速率限制:
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
不支持基于每个请求修改速率限制,因此 HTTP/2
请求的 HttpContext.Features
中不存在前面示例中引用的速率特性。 通过 KestrelServerOptions.Limits
配置的服务器范围的速率限制仍适用于 HTTP/1.x
和 HTTP/2
连接。
Http2.MaxStreamsPerConnection
限制每个 HTTP/2
连接的并发请求流的数量。 拒绝过多的流。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.MaxStreamsPerConnection = 100;
});
默认值为 100。
HPACK
解码器解压缩 HTTP/2
连接的 HTTP
标头。 Http2.HeaderTableSize
限制 HPACK
解码器使用的标头压缩表的大小。 该值以八位字节提供,且必须大于零 (0)。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.HeaderTableSize = 4096;
});
默认值为 4096。
Http2.MaxFrameSize
指示要接收的 HTTP/2
连接帧有效负载的最大大小。 该值以八位字节提供,必须介于 2^14 (16,384)
和 2^24-1 (16,777,215)
之间。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.MaxFrameSize = 16384;
});
默认值为 2^14 (16,384)
。
Http2.MaxRequestHeaderFieldSize
表示请求标头值的允许的最大大小(用八进制表示)。 此限制同时适用于压缩和未压缩表示形式中的名称和值。 该值必须大于零 (0)。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});
默认值为 8,192。
Http2.InitialConnectionWindowSize
表示服务器一次性缓存的最大请求主体数据大小(每次连接时在所有请求(流)中汇总,以字节为单位)。 请求也受 Http2.InitialStreamWindowSize
限制。 该值必须大于或等于 65,535
,并小于 2^31
(2,147,483,648)。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.InitialConnectionWindowSize = 131072;
});
默认值为 128 KB (131,072)。
Http2.InitialStreamWindowSize
表示服务器针对每个请求(流)的一次性缓存的最大请求主体数据大小(以字节为单位)。 请求也受 Http2.InitialStreamWindowSize
限制。 该值必须大于或等于 65,535
,并小于 2^31
(2,147,483,648)。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Limits.Http2.InitialStreamWindowSize = 98304;
});
默认值为 96 KB (98,304)。
有关其他 Kestrel
选项和限制的信息,请参阅:
KestrelServerOptions
KestrelServerLimits
ListenOptions
默认情况下,ASP.NET Core 绑定到:
开发证书会创建于以下情况:
部分浏览器需要获取信任本地开发证书的显示权限。
ASP.NET Core 2.1 及更高版本的项目模板将应用配置为默认情况下在 HTTPS 上运行,并包括 HTTPS 重定向和 HSTS 支持。
在 KestrelServerOptions
上调用 Listen
或 ListenUnixSocket
方法,从而配置 Kestrel
的 URL
前缀和端口。
UseUrls
、--urls
命令行参数、urls
主机配置键以及 ASPNETCORE_URLS
环境变量也有用,但具有本节后面注明的限制(必须要有可用于 HTTPS
终结点配置的默认证书)。
ASP.NET Core 2.1 KestrelServerOptions
配置:
ConfigureEndpointDefaults(Action)
指定一个为每个指定的终结点运行的配置 Action
。 多次调用 ConfigureEndpointDefaults
,用最新指定的 Action
替换之前的 Action
。
ConfigureHttpsDefaults(Action)
指定一个为每个 HTTPS
终结点运行的配置 Action
。 多次调用 ConfigureHttpsDefaults
,用最新指定的 Action
替换之前的 Action
。
Configure(IConfiguration)
创建配置加载程序,用于设置将 IConfiguration
作为输入的 Kestrel
。 配置必须针对 Kestrel
的配置节。
ListenOptions.UseHttps
将 Kestrel
配置为使用 HTTPS
。
ListenOptions.UseHttps
扩展:
UseHttps
– 将 Kestrel 配置为使用 HTTPS,采用默认证书。 如果没有配置默认证书,则会引发异常。UseHttps(X509Certificate2 serverCertificate, Action configureOptions)
UseHttps(Action configureOptions)
ListenOptions.UseHttps
参数:
X.509
证书数据所需的密码。HttpsConnectionAdapterOptions
的 Action
。 返回X.509
证书。在生产中,必须显式配置 HTTPS
。 至少必须提供默认证书。
下面要描述的支持的配置:
无配置
Kestrel
在 http://localhost:5000 和 https://localhost:5001 上进行侦听(如果默认证书可用)。
使用以下内容指定 URL:
ASPNETCORE_URLS 环境变量。
--urls 命令行参数。
urls 主机配置键。
UseUrls 扩展方法。
有关详细信息,请参阅服务器 URL 和重写配置。
采用这些方法提供的值可以是一个或多个 HTTP 和 HTTPS 终结点(如果默认证书可用,则为 HTTPS)。 将值配置为以分号分隔的列表(例如 “Urls”: “http://localhost:8000;http://localhost:8001”)。
从配置中替换默认证书
WebHost.CreateDefaultBuilder
在默认情况下调用 serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
来加载 Kestrel
配置。 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": "" ,
"Password": ""
}
},
"HttpsInlineCertStore": {
"Url": "https://localhost:5002",
"Certificate": {
"Subject": "" ,
"Store": "" ,
"Location": "" ,
"AllowInvalid": ""
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5003"
},
"Https": {
"Url": "https://*:5004",
"Certificate": {
"Path": "" ,
"Password": ""
}
}
},
"Certificates": {
"Default": {
"Path": "" ,
"Password": ""
}
}
}
}
此外还可以使用任何证书节点的 Path 和 Password,采用证书存储字段指定证书。 例如,可将 Certificates > Default 证书指定为:
"Default": {
"Subject": "" ,
"Store": "" ,
"Location": "" ,
"AllowInvalid": ""
}
架构的注意事项:
Listen
Certificate
部分是可选的。 如果为指定 Certificate 部分,则使用在之前的方案中定义的默认值。Certificate
支持 Path–Password
和 Subject–Store
证书。options.Configure(context.Configuration.GetSection("Kestrel"))
通过 .Endpoint(string name, options => { })
方法返回 KestrelConfigurationLoader
,可以用于补充已配置的终结点设置: options.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("HTTPS", opt =>
{
opt.HttpsOptions.SslProtocols = SslProtocols.Tls12;
});
也可以直接访问 KestrelServerOptions.ConfigurationLoader
在现有加载程序上保持迭代,例如由 WebHost.CreateDefaultBuilder
提供的加载程序。Endpoint
方法中的选项,以便读取自定义设置。options.Configure(context.Configuration.GetSection("Kestrel"))
KestrelConfigurationLoader
从 KestrelServerOptions
将 API 的 Listen
Endpoint
重载,因此可在同样的位置配置代码和配置终结点。 这些重载不使用名称,且只使用配置中的默认设置。更改代码中的默认值
可以使用 ConfigureEndpointDefaults
和 ConfigureHttpsDefaults
更改 ListenOptions
和 HttpsConnectionAdapterOptions
的默认设置,包括重写之前的方案指定的默认证书。 需要在配置任何终结点之前调用 ConfigureEndpointDefaults
和 ConfigureHttpsDefaults
。
options.ConfigureEndpointDefaults(opt =>
{
opt.NoDelay = true;
});
options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.SslProtocols = SslProtocols.Tls12;
});
SNI
的 Kestrel
支持
服务器名称指示 (SNI
) 可用于承载相同 IP 地址和端口上的多个域。 为了运行 SNI,客户端在 TLS 握手过程中将进行安全会话的主机名发送至服务器,从而让服务器可以提供正确的证书。 在 TLS 握手后的安全会话期间,客户端将服务器提供的证书用于与服务器进行加密通信。
Kestrel
通过 ServerCertificateSelector
回调支持 SNI
。 每次连接调用一次回调,从而允许应用检查主机名并选择合适的证书。
SNI 支持要求:
netcoreapp2.1
上运行。 在 netcoreapp2.0
和 net461
上,回调也会调用,但是 name
null
。 如果客户端未在 TLS 握手过程中提供主机名参数,则 name
也为 null
。Kestrel
实例上运行。 Kestrel
在无反向代理时不支持跨多个实例共享一个 IP
地址和端口。public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var subExampleCert = CertificateLoader.LoadFromStoreCert(
"sub.example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var certs = new Dictionary<string, X509Certificate2>(
StringComparer.OrdinalIgnoreCase);
certs["localhost"] = localhostCert;
certs["example.com"] = exampleCert;
certs["sub.example.com"] = subExampleCert;
httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
{
if (name != null && certs.TryGetValue(name, out var cert))
{
return cert;
}
return exampleCert;
};
});
});
});
Listen
方法绑定至 TCP 套接字,且 options lambda
允许 X.509
证书配置:
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
示例代码使用 ListenOptions
为终结点配置 HTTPS
。 可使用相同 API
为特定终结点配置其他 Kestrel
设置。
在 Windows
上,可以使用 New-SelfSignedCertificate PowerShell cmdlet
创建自签名证书。 有关不支持的示例,请参阅 UpdateIISExpressSSLForChrome.ps1
。
在 macOS、Linux 和 Windows 上,可以使用 OpenSSL
创建证书。
Unix
套接字可通过 ListenUnixSocket
侦听 Unix
套接字以提高 Nginx
的性能,如以下示例所示:
.ConfigureKestrel((context, options) =>
{
options.ListenUnixSocket("/tmp/kestrel-test.sock");
options.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testpassword");
});
});
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("" +
"Hosted by Kestrel
");
if (serverAddressesFeature != null)
{
await context.Response
.WriteAsync("Listening on the following addresses: "
+
string.Join(", ", serverAddressesFeature.Addresses) +
"");
}
await context.Response.WriteAsync("Request URL: "
+
$"{context.Request.GetDisplayUrl()}"
);
});
}
在应用运行时,控制台窗口输出指示可用于访问应用的动态端口:
console
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 时,由 Listen
或 UseUrls
设置用于 IIS 覆盖绑定的 URL 绑定。 有关详细信息,请参阅 ASP.NET Core 模块主题。
ListenOptions.Protocols
Protocols
属性建立在连接终结点上或为服务器启用的 HTTP 协议(HttpProtocols
)。 从 HttpProtocols
枚举向 Protocols
属性赋值。
HttpProtocols 枚举值 允许的连接协议
Http1 仅 HTTP/1.1。 可以在具有 TLS
或没有 TLS
的情况下使用。
Http2 仅 HTTP/2。 主要在具有 TLS 的情况下使用。 仅当客户端支持先验知识模式时,才可以在没有 TLS 的情况下使用。
Http1AndHttp2 HTTP/1.1 和 HTTP/2。 需要 TLS 和应用程序层协议协商 (ALPN) 连接来协商 HTTP/2;否则,连接默认为 HTTP/1.1。
默认协议是 HTTP/1.1。
HTTP/2 的 TLS 限制:
TLS 版本 1.2 或更高版本
重新协商已禁用
压缩已禁用
最小的临时密钥交换大小:
椭圆曲线 Diffie-Hellman (ECDHE) [RFC4492] –最小 224 位
有限字段 Diffie-Hellman (DHE) [TLS12] – 最小 2048 位
密码套件未列入阻止列表
默认情况下,支持具有 P-256 椭圆曲线 [FIPS186] 的 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE]。
以下示例允许端口 8000 上的 HTTP/1.1 和 HTTP/2 连接。 TLS 使用提供的证书来保护连接:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
(可选)创建 IConnectionAdapter 实现,以针对特定密码的每个连接筛选 TLS 握手:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps("testCert.pfx", "testPassword");
listenOptions.ConnectionAdapters.Add(new TlsFilterAdapter());
});
});
private class TlsFilterAdapter : IConnectionAdapter
{
public bool IsHttps => false;
public Task OnConnectionAsync(ConnectionAdapterContext context)
{
var tlsFeature = context.Features.Get();
// Throw NotSupportedException for any cipher algorithm that you don't
// wish to support. Alternatively, define and compare
// ITlsHandshakeFeature.CipherAlgorithm to a list of acceptable cipher
// suites.
//
// A ITlsHandshakeFeature.CipherAlgorithm of CipherAlgorithmType.Null
// indicates that no cipher algorithm supported by Kestrel matches the
// requested algorithm(s).
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
{
throw new NotSupportedException("Prohibited cipher: " + tlsFeature.CipherAlgorithm);
}
return Task.FromResult(new AdaptedConnection(context.ConnectionStream));
}
private class AdaptedConnection : IAdaptedConnection
{
public AdaptedConnection(Stream adaptedStream)
{
ConnectionStream = adaptedStream;
}
public Stream ConnectionStream { get; }
public void Dispose()
{
}
}
}
从配置中设置协议
WebHost.CreateDefaultBuilder
在默认情况下调用 serverOptions.Configure(context.Configuration.GetSection(“Kestrel”)) 来加载 Kestrel 配置。
在以下 appsettings.json
示例中,为 Kestrel 的所有终结点建立默认的连接协议(HTTP/1.1 和 HTTP/2):
JSON
{
"Kestrel": {
"EndPointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
以下配置文件示例为特定终结点建立了连接协议:
JSON
{
"Kestrel": {
"EndPoints": {
"HttpsDefaultCert": {
"Url": "https://localhost:5001",
"Protocols": "Http1AndHttp2"
}
}
}
}
代码中指定的协议覆盖了由配置设置的值。
对于 ASP.NET Core 2.1 版,Kestrel 默认传输不再基于 Libuv,而是基于托管的套接字。 这是 ASP.NET Core 2.0 应用升级到 2.1 时的一个重大更改,它调用 WebHostBuilderLibuvExtensions.UseLibuv 并依赖于以下包中的一个:
Microsoft.AspNetCore.Server.Kestrel(直接包引用)
Microsoft.AspNetCore.App
对于使用 Microsoft.AspNetCore.App 元包且需要使用 Libuv 的 ASP.NET Core 2.1 或更高版本的项目:
将用于 Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv 包的依赖项添加到应用的项目文件:
XML
调用 WebHostBuilderLibuvExtensions.UseLibuv:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseLibuv()
.UseStartup<Startup>();
}
URL 前缀
如果使用 UseUrls
、--urls
命令行参数、urls
主机配置键或 ASPNETCORE_URLS
环境变量,URL
前缀可采用以下任意格式。
仅 HTTP URL 前缀是有效的。 使用 UseUrls 配置 URL 绑定时,Kestrel
不支持 HTTPS
。
包含端口号的 IPv4 地址
http://65.55.39.10:80/
0.0.0.0 是一种绑定到所有 IPv4 地址的特殊情况。
包含端口号的 IPv6 地址
http://[0:0:0:0:0:ffff:4137:270a]:80/
[::] 是 IPv4 0.0.0.0 的 IPv6 等效项。
包含端口号的主机名
http://contoso.com:80/
http://*:80/
主机名、*和 + 并不特殊。 没有识别为有效 IP 地址或 localhost 的任何内容都将绑定到所有 IPv4 和 IPv6 IP。 若要将不同主机名绑定到相同端口上的不同 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
将记录一个警告。
尽管 Kestrel 支持基于前缀的配置(例如 http://example.com:5000),但 Kestrel
在很大程度上会忽略主机名。 主机 localhost
是一个特殊情况,用于绑定至环回地址。 除了显式 IP 地址以外的所有主机都绑定至所有公共 IP 地址。 不验证 Host 标头。
解决方法是,使用主机筛选中间件。 主机筛选中间件由 Microsoft.AspNetCore.HostFiltering
包提供,此包包含在 Microsoft.AspNetCore.App
元包中(ASP.NET Core 2.1
或更高版本)。 该中间件由 CreateDefaultBuilder
添加,可调用 AddHostFiltering
:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
默认情况下,主机筛选中间件处于禁用状态。 要启用该中间件,请在 appsettings.json/appsettings.
中定义一个 AllowedHosts
键。 此值是以分号分隔的不带端口号的主机名列表:
appsettings.json:
JSON
{
"AllowedHosts": "example.com;localhost"
}
备注
转接头中间件同样提供
ForwardedHeadersOptions.AllowedHosts
选项。
转接头中间件和主机筛选中间件具有适合不同方案的相似功能。 如果未保留Host
标头,并且使用反向代理服务器或负载均衡器转接请求,则使用转接头中间件设置AllowedHosts
比较合适。 将Kestrel
用作面向公众的边缘服务器或直接转接Host
标头时,使用主机筛选中间件设置AllowedHosts
比较合适。有关转接头中间件的详细信息,请参阅 配置 ASP.NET Core 以使用代理服务器和负载均衡器。