diff --git a/aspnetcore/blazor/call-web-api.md b/aspnetcore/blazor/call-web-api.md index 907dc6304655..16ec04cfdcb9 100644 --- a/aspnetcore/blazor/call-web-api.md +++ b/aspnetcore/blazor/call-web-api.md @@ -397,5 +397,10 @@ For general information on CORS with ASP.NET Core apps, see * : Includes coverage on using to make secure web API requests. * * +::: moniker range=">= aspnetcore-5.0" +* [Kestrel HTTPS endpoint configuration](xref:fundamentals/servers/kestrel/endpoints) +::: moniker-end +::: moniker range="< aspnetcore-5.0" * [Kestrel HTTPS endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration) +::: moniker-end * [Cross Origin Resource Sharing (CORS) at W3C](https://www.w3.org/TR/cors/) diff --git a/aspnetcore/blazor/common/samples/5.x/BlazorWebAssemblySample/Pages/CallWebAPI.razor b/aspnetcore/blazor/common/samples/5.x/BlazorWebAssemblySample/Pages/CallWebAPI.razor index 8114bd5aa538..28df7cddac3e 100644 --- a/aspnetcore/blazor/common/samples/5.x/BlazorWebAssemblySample/Pages/CallWebAPI.razor +++ b/aspnetcore/blazor/common/samples/5.x/BlazorWebAssemblySample/Pages/CallWebAPI.razor @@ -16,7 +16,7 @@

Adjust the domains and ports of WithOrigins as needed for the Blazor app.

-

By default, ASP.NET Core apps use ports 5000 (HTTP) and 5001 (HTTPS). To run both apps on the same machine at the same time for testing, use a different port for the web API app (for example, port 10000). For more information on setting the port, see the Kestrel web server implementation: Endpoint configuration.

+

By default, ASP.NET Core apps use ports 5000 (HTTP) and 5001 (HTTPS). To run both apps on the same machine at the same time for testing, use a different port for the web API app (for example, port 10000). For more information on setting the port, see the Kestrel web server implementation: Endpoint configuration.

Todo Items

diff --git a/aspnetcore/fundamentals/host/generic-host.md b/aspnetcore/fundamentals/host/generic-host.md index 7092caac611e..f445739d1a24 100644 --- a/aspnetcore/fundamentals/host/generic-host.md +++ b/aspnetcore/fundamentals/host/generic-host.md @@ -112,8 +112,8 @@ The method: The method: * Loads host configuration from environment variables prefixed with `ASPNETCORE_`. -* Sets [Kestrel](xref:fundamentals/servers/kestrel) server as the web server and configures it using the app's hosting configuration providers. For the Kestrel server's default options, see . -* Adds [Host Filtering middleware](xref:fundamentals/servers/kestrel#host-filtering). +* Sets [Kestrel](xref:fundamentals/servers/kestrel) server as the web server and configures it using the app's hosting configuration providers. For the Kestrel server's default options, see . +* Adds [Host Filtering middleware](xref:fundamentals/servers/kestrel/host-filtering). * Adds [Forwarded Headers middleware](xref:host-and-deploy/proxy-load-balancer#forwarded-headers) if `ASPNETCORE_FORWARDEDHEADERS_ENABLED` equals `true`. * Enables IIS integration. For the IIS default options, see . @@ -420,7 +420,7 @@ To set this value, use the environment variable or call `UseUrls`: webBuilder.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002"); ``` -Kestrel has its own endpoint configuration API. For more information, see . +Kestrel has its own endpoint configuration API. For more information, see . ### WebRoot diff --git a/aspnetcore/fundamentals/host/web-host.md b/aspnetcore/fundamentals/host/web-host.md index 42a1ef4ce8c2..543fa672600d 100644 --- a/aspnetcore/fundamentals/host/web-host.md +++ b/aspnetcore/fundamentals/host/web-host.md @@ -49,7 +49,12 @@ The code that calls `CreateDefaultBuilder` is in a method named `CreateWebHostBu `CreateDefaultBuilder` performs the following tasks: +::: moniker range=">= aspnetcore-5.0" +* Configures [Kestrel](xref:fundamentals/servers/kestrel) server as the web server using the app's hosting configuration providers. For the Kestrel server's default options, see . +::: moniker-end +::: moniker range="< aspnetcore-5.0" * Configures [Kestrel](xref:fundamentals/servers/kestrel) server as the web server using the app's hosting configuration providers. For the Kestrel server's default options, see . +::: moniker-end * Sets the [content root](xref:fundamentals/index#content-root) to the path returned by [Directory.GetCurrentDirectory](/dotnet/api/system.io.directory.getcurrentdirectory). * Loads [host configuration](#host-configuration-values) from: * Environment variables prefixed with `ASPNETCORE_` (for example, `ASPNETCORE_ENVIRONMENT`). @@ -329,7 +334,12 @@ WebHost.CreateDefaultBuilder(args) .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002") ``` +::: moniker range=">= aspnetcore-5.0" +Kestrel has its own endpoint configuration API. For more information, see . +::: moniker-end +::: moniker range="< aspnetcore-5.0" Kestrel has its own endpoint configuration API. For more information, see . +::: moniker-end ### Shutdown Timeout diff --git a/aspnetcore/fundamentals/servers/index.md b/aspnetcore/fundamentals/servers/index.md index 2d7644b0edeb..b50e26344d06 100644 --- a/aspnetcore/fundamentals/servers/index.md +++ b/aspnetcore/fundamentals/servers/index.md @@ -159,7 +159,30 @@ A *launchSettings.json* file provides configuration when launching an app with ` [HTTP/2](https://httpwg.org/specs/rfc7540.html) is supported with ASP.NET Core in the following deployment scenarios: -::: moniker range=">= aspnetcore-2.2" +::: moniker range=">= aspnetcore-5.0" + +* [Kestrel](xref:fundamentals/servers/kestrel/http2) + * Operating system + * Windows Server 2016/Windows 10 or later† + * Linux with OpenSSL 1.0.2 or later (for example, Ubuntu 16.04 or later) + * HTTP/2 will be supported on macOS in a future release. + * Target framework: .NET Core 2.2 or later +* [HTTP.sys](xref:fundamentals/servers/httpsys#http2-support) + * Windows Server 2016/Windows 10 or later + * Target framework: Not applicable to HTTP.sys deployments. +* [IIS (in-process)](xref:host-and-deploy/iis/index#http2-support) + * Windows Server 2016/Windows 10 or later; IIS 10 or later + * Target framework: .NET Core 2.2 or later +* [IIS (out-of-process)](xref:host-and-deploy/iis/index#http2-support) + * Windows Server 2016/Windows 10 or later; IIS 10 or later + * Public-facing edge server connections use HTTP/2, but the reverse proxy connection to Kestrel uses HTTP/1.1. + * Target framework: Not applicable to IIS out-of-process deployments. + +†Kestrel has limited support for HTTP/2 on Windows Server 2012 R2 and Windows 8.1. Support is limited because the list of supported TLS cipher suites available on these operating systems is limited. A certificate generated using an Elliptic Curve Digital Signature Algorithm (ECDSA) may be required to secure TLS connections. + +::: moniker-end + +::: moniker range=">= aspnetcore-2.2 < aspnetcore-5.0" * [Kestrel](xref:fundamentals/servers/kestrel#http2-support) * Operating system diff --git a/aspnetcore/fundamentals/servers/kestrel.md b/aspnetcore/fundamentals/servers/kestrel.md index 901c5401dc61..b3778a521297 100644 --- a/aspnetcore/fundamentals/servers/kestrel.md +++ b/aspnetcore/fundamentals/servers/kestrel.md @@ -13,7 +13,56 @@ uid: fundamentals/servers/kestrel By [Tom Dykstra](https://github.com/tdykstra), [Chris Ross](https://github.com/Tratcher), and [Stephen Halter](https://twitter.com/halter73) -::: moniker range=">= aspnetcore-3.0" +::: moniker range=">= aspnetcore-5.0" + +Kestrel is a cross-platform [web server for ASP.NET Core](xref:fundamentals/servers/index). Kestrel is the web server that's included and enabled by default in ASP.NET Core project templates. + +Kestrel supports the following scenarios: + +* HTTPS +* [HTTP/2](xref:fundamentals/servers/kestrel/http2) (except on macOS†) +* Opaque upgrade used to enable [WebSockets](xref:fundamentals/websockets) +* Unix sockets for high performance behind Nginx + +†HTTP/2 will be supported on macOS in a future release. + +Kestrel is supported on all platforms and versions that .NET Core supports. + +[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples/5.x) ([how to download](xref:index#how-to-download-a-sample)) + +## Get started + +ASP.NET Core project templates use Kestrel by default. In *Program.cs*, the + method calls : + +[!code-csharp[](kestrel/samples/5.x/KestrelSample/Program.cs?name=snippet_DefaultBuilder&highlight=8)] + +For more information on building the host, see the *Set up a host* and *Default builder settings* sections of . + +## Additional resournces + + +* + +* + +* + +* + +* +* +* +* +* [RFC 7230: Message Syntax and Routing (Section 5.4: Host)](https://tools.ietf.org/html/rfc7230#section-5.4) +* When using UNIX sockets on Linux, the socket is not automatically deleted on app shut down. For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/14134). + +> [!NOTE] +> As of ASP.NET Core 5.0, Kestrel's libuv transport is obsolete. The libuv transport doesn't receive updates to support new OS platforms, such as Windows ARM64, and will be removed in a future release. Remove any calls to the obsolete method and use Kestrel's default Socket transport instead. + +::: moniker-end + +::: moniker range=">= aspnetcore-3.0 < aspnetcore-5.0" Kestrel is a cross-platform [web server for ASP.NET Core](xref:fundamentals/servers/index). Kestrel is the web server that's included by default in ASP.NET Core project templates. @@ -28,7 +77,7 @@ Kestrel supports the following scenarios: Kestrel is supported on all platforms and versions that .NET Core supports. -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples) ([how to download](xref:index#how-to-download-a-sample)) +[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples/3.x) ([how to download](xref:index#how-to-download-a-sample)) ## HTTP/2 support @@ -46,7 +95,7 @@ Kestrel is supported on all platforms and versions that .NET Core supports. If an HTTP/2 connection is established, [HttpRequest.Protocol](xref:Microsoft.AspNetCore.Http.HttpRequest.Protocol*) reports `HTTP/2`. -HTTP/2 is disabled by default. For more information on configuration, see the [Kestrel options](#kestrel-options) and [ListenOptions.Protocols](#listenoptionsprotocols) sections. +Starting with .NET Core 3.0, HTTP/2 is enabled by default. For more information on configuration, see the [Kestrel options](#kestrel-options) and [ListenOptions.Protocols](#listenoptionsprotocols) sections. ## When to use Kestrel with a reverse proxy @@ -340,34 +389,6 @@ webBuilder.ConfigureKestrel(serverOptions => The default value is 96 KB (98,304). -::: moniker-end - -::: moniker range=">= aspnetcore-5.0" - -### HTTP/2 keep alive ping configuration - -Kestrel can be configured to send HTTP/2 pings to connected clients. HTTP/2 pings serve multiple purposes: - -* Keep idle connections alive. Some clients and proxy servers close connections that are idle. HTTP/2 pings are considered as activity on a connection and prevent the connection from being closed as idle. -* Close unhealthy connections. Connections where the client doesn't respond to the keep alive ping in the configured time are closed by the server. - -There are two configuration options related to HTTP/2 keep alive pings: - -* `Http2.KeepAlivePingInterval` is a `TimeSpan` that configures the ping internal. The server sends a keep alive ping to the client if it doesn't receive any frames for this period of time. Keep alive pings are disabled when this option is set to `TimeSpan.MaxValue`. The default value is `TimeSpan.MaxValue`. -* `Http2.KeepAlivePingTimeout` is a `TimeSpan` that configures the ping timeout. If the server doesn't receive any frames, such as a response ping, during this timeout then the connection is closed. Keep alive timeout is disabled when this option is set to `TimeSpan.MaxValue`. The default value is 20 seconds. - -```csharp -webBuilder.ConfigureKestrel(serverOptions => -{ - serverOptions.Limits.Http2.KeepAlivePingInterval = TimeSpan.FromSeconds(30); - serverOptions.Limits.Http2.KeepAlivePingTimeout = TimeSpan.FromSeconds(60); -}); -``` - -::: moniker-end - -::: moniker range=">= aspnetcore-3.0" - ### Trailers [!INCLUDE[](~/includes/trailers.md)] @@ -970,18 +991,6 @@ Host Filtering Middleware is disabled by default. To enable the middleware, defi > > For more information on Forwarded Headers Middleware, see . -::: moniker-end - -::: moniker range=">= aspnetcore-5.0" - -## Libuv transport configuration - -As of ASP.NET Core 5.0, Kestrel's Libuv transport is obsolete. Libuv transport doesn't receive updates to support new OS platforms, such as Windows ARM64, and will be removed in a future release. Remove any calls to the obsolete method and use Kestrel's default Socket transport instead. - -::: moniker-end - -::: moniker range=">= aspnetcore-3.0 < aspnetcore-5.0" - ## Libuv transport configuration For projects that require the use of Libuv (): @@ -1013,6 +1022,44 @@ For projects that require the use of Libuv ( +* +* +* [RFC 7230: Message Syntax and Routing (Section 5.4: Host)](https://tools.ietf.org/html/rfc7230#section-5.4) + ::: moniker-end ::: moniker range="= aspnetcore-2.2" @@ -1030,7 +1077,7 @@ Kestrel supports the following scenarios: Kestrel is supported on all platforms and versions that .NET Core supports. -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples) ([how to download](xref:index#how-to-download-a-sample)) +[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples/2.x) ([how to download](xref:index#how-to-download-a-sample)) ## HTTP/2 support @@ -1964,6 +2011,44 @@ Host Filtering Middleware is disabled by default. To enable the middleware, defi > > For more information on Forwarded Headers Middleware, see . +## HTTP/1.1 request draining + +Opening HTTP connections is time consuming. For HTTPS, it's also resource intensive. Therefore, Kestrel tries to reuse connections per the HTTP/1.1 protocol. A request body must be fully consumed to allow the connection to be reused. The app doesn't always consume the request body, such as a `POST` requests where the server returns a redirect or 404 response. In the `POST`-redirect case: + +* The client may already have sent part of the `POST` data. +* The server writes the 301 response. +* The connection can't be used for a new request until the `POST` data from the previous request body has been fully read. +* Kestrel tries to drain the request body. Draining the request body means reading and discarding the data without processing it. + +The draining process makes a tradoff between allowing the connection to be reused and the time it takes to drain any remaining data: + +* Draining has a timeout of five seconds, which isn't configurable. +* If all of the data specified by the `Content-Length` or `Transfer-Encoding` header hasn't been read before the timeout, the connection is closed. + +Sometimes you may want to terminate the request immediately, before or after writing the response. For example, clients may have restrictive data caps, so limiting uploaded data might be a priority. In such cases to terminate a request, call [HttpContext.Abort](xref:Microsoft.AspNetCore.Http.HttpContext.Abort%2A) from a controller, Razor Page, or middleware. + +There are caveats to calling `Abort`: + +* Creating new connections can be slow and expensive. +* There's no guarantee that the client has read the response before the connection closes. +* Calling `Abort` should be rare and reserved for severe error cases, not common errors. + * Only call `Abort` when a specific problem needs to be solved. For example, call `Abort` if malicious clients are trying to `POST` data or when there's a bug in client code that causes large or numerous requests. + * Don't call `Abort` for common error situations, such as HTTP 404 (Not Found). + +Calling [HttpResponse.CompleteAsync](xref:Microsoft.AspNetCore.Http.HttpResponse.CompleteAsync%2A) before calling `Abort` ensures that the server has completed writing the response. However, client behavior isn't predictable and they may not read the response before the connection is aborted. + +This process is different for HTTP/2 because the protocol supports aborting individual request streams without closing the connection. The five second drain timeout doesn't apply. If there's any unread request body data after completing a response, then the server sends an HTTP/2 RST frame. Additional request body data frames are ignored. + +If possible, it's better for clients to utilize the [Expect: 100-continue](https://developer.mozilla.org/docs/Web/HTTP/Status/100) request header and wait for the server to respond before starting to send the request body. That gives the client an opportunity to examine the response and abort before sending unneeded data. + +## Additional resources + +* When using UNIX sockets on Linux, the socket is not automatically deleted on app shut down. For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/14134). +* +* +* +* [RFC 7230: Message Syntax and Routing (Section 5.4: Host)](https://tools.ietf.org/html/rfc7230#section-5.4) + ::: moniker-end ::: moniker range="= aspnetcore-2.1" @@ -1978,7 +2063,7 @@ Kestrel supports the following scenarios: Kestrel is supported on all platforms and versions that .NET Core supports. -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples) ([how to download](xref:index#how-to-download-a-sample)) +[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/servers/kestrel/samples/2.x) ([how to download](xref:index#how-to-download-a-sample)) ## When to use Kestrel with a reverse proxy @@ -2754,8 +2839,6 @@ Host Filtering Middleware is disabled by default. To enable the middleware, defi > > For more information on Forwarded Headers Middleware, see . -::: moniker-end - ## HTTP/1.1 request draining Opening HTTP connections is time consuming. For HTTPS, it's also resource intensive. Therefore, Kestrel tries to reuse connections per the HTTP/1.1 protocol. A request body must be fully consumed to allow the connection to be reused. The app doesn't always consume the request body, such as a `POST` requests where the server returns a redirect or 404 response. In the `POST`-redirect case: @@ -2793,3 +2876,5 @@ If possible, it's better for clients to utilize the [Expect: 100-continue](https * * * [RFC 7230: Message Syntax and Routing (Section 5.4: Host)](https://tools.ietf.org/html/rfc7230#section-5.4) + +::: moniker-end \ No newline at end of file diff --git a/aspnetcore/fundamentals/servers/kestrel/endpoints.md b/aspnetcore/fundamentals/servers/kestrel/endpoints.md new file mode 100644 index 000000000000..22dc69495298 --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/endpoints.md @@ -0,0 +1,592 @@ +--- +title: Configure endpoints for the ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about configuring endpoints with Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 05/04/2020 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/endpoints +--- + +# Configure endpoints for the ASP.NET Core Kestrel web server + +By default, ASP.NET Core binds to: + +* `http://localhost:5000` +* `https://localhost:5001` (when a local development certificate is present) + +Specify URLs using the: + +* `ASPNETCORE_URLS` environment variable. +* `--urls` command-line argument. +* `urls` host configuration key. +* `UseUrls` extension method. + +The value provided using these approaches can be one or more HTTP and HTTPS endpoints (HTTPS if a default cert is available). Configure the value as a semicolon-separated list (for example, `"Urls": "http://localhost:8000;http://localhost:8001"`). + +For more information on these approaches, see [Server URLs](xref:fundamentals/host/web-host#server-urls) and [Override configuration](xref:fundamentals/host/web-host#override-configuration). + +A development certificate is created: + +* When the [.NET SDK](/dotnet/core/sdk) is installed. +* The [dev-certs tool](xref:aspnetcore-2.1#https) is used to create a certificate. + +Some browsers require granting explicit permission to trust the local development certificate. + +Project templates configure apps to run on HTTPS by default and include [HTTPS redirection and HSTS support](xref:security/enforcing-ssl). + +Call or methods on to configure URL prefixes and ports for Kestrel. + +`UseUrls`, the `--urls` command-line argument, `urls` host configuration key, and the `ASPNETCORE_URLS` environment variable also work but have the limitations noted later in this section (a default certificate must be available for HTTPS endpoint configuration). + +`KestrelServerOptions` configuration: + +## ConfigureEndpointDefaults(Action\) + +Specifies a configuration `Action` to run for each specified endpoint. Calling `ConfigureEndpointDefaults` multiple times replaces prior `Action`s with the last `Action` specified. + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.ConfigureEndpointDefaults(listenOptions => + { + // Configure endpoint defaults + }); +}); +``` + +> [!NOTE] +> Endpoints created by calling **before** calling won't have the defaults applied. + +## ConfigureHttpsDefaults(Action\) + +Specifies a configuration `Action` to run for each HTTPS endpoint. Calling `ConfigureHttpsDefaults` multiple times replaces prior `Action`s with the last `Action` specified. + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.ConfigureHttpsDefaults(listenOptions => + { + // certificate is an X509Certificate2 + listenOptions.ServerCertificate = certificate; + }); +}); +``` + +> [!NOTE] +> Endpoints created by calling **before** calling won't have the defaults applied. + +## Configure(IConfiguration) + +Creates a configuration loader for setting up Kestrel that takes an as input. The configuration must be scoped to the configuration section for Kestrel. + +`CreateDefaultBuilder` calls `Configure(context.Configuration.GetSection("Kestrel"))` by default to load Kestrel configuration. + +```json +{ + "Kestrel": { + "Endpoints": { + "Http": { + "Url": "http://localhost:5000" + }, + "Https": { + "Url": "https://localhost:5001", + "Certificate": { + "Path": "", + "Password": "" + } + } + } + } +} +``` + +## ListenOptions.UseHttps + +Configure Kestrel to use HTTPS. + +`ListenOptions.UseHttps` extensions: + +* `UseHttps`: Configure Kestrel to use HTTPS with the default certificate. Throws an exception if no default certificate is configured. +* `UseHttps(string fileName)` +* `UseHttps(string fileName, string password)` +* `UseHttps(string fileName, string password, Action 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 configureOptions)` +* `UseHttps(X509Certificate2 serverCertificate)` +* `UseHttps(X509Certificate2 serverCertificate, Action configureOptions)` +* `UseHttps(Action configureOptions)` + +`ListenOptions.UseHttps` parameters: + +* `filename` is the path and file name of a certificate file, relative to the directory that contains the app's content files. +* `password` is the password required to access the X.509 certificate data. +* `configureOptions` is an `Action` to configure the `HttpsConnectionAdapterOptions`. Returns the `ListenOptions`. +* `storeName` is the certificate store from which to load the certificate. +* `subject` is the subject name for the certificate. +* `allowInvalid` indicates if invalid certificates should be considered, such as self-signed certificates. +* `location` is the store location to load the certificate from. +* `serverCertificate` is the X.509 certificate. + +In production, HTTPS must be explicitly configured. At a minimum, a default certificate must be provided. + +Supported configurations described next: + +* No configuration +* Replace the default certificate from configuration +* Change the defaults in code + +### No configuration + +Kestrel listens on `http://localhost:5000` and `https://localhost:5001` (if a default cert is available). + + + +### Replace the default certificate from configuration + +A default HTTPS app settings configuration schema is available for Kestrel. Configure multiple endpoints, including the URLs and the certificates to use, either from a file on disk or from a certificate store. + +In the following *appsettings.json* example: + +* Set `AllowInvalid` to `true` to permit the use of invalid certificates (for example, self-signed certificates). +* Any HTTPS endpoint that doesn't specify a certificate (`HttpsDefaultCert` in the example that follows) falls back to the cert defined under `Certificates` > `Default` or the development certificate. + +```json +{ + "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": "" + } + } + } +} +``` + +An alternative to using `Path` and `Password` for any certificate node is to specify the certificate using certificate store fields. For example, the `Certificates` > `Default` certificate can be specified as: + +```json +"Default": { + "Subject": "", + "Store": "", + "Location": "", + "AllowInvalid": "" +} +``` + +Schema notes: + +* Endpoints names are case-insensitive. For example, `HTTPS` and `Https` are valid. +* The `Url` parameter is required for each endpoint. The format for this parameter is the same as the top-level `Urls` configuration parameter except that it's limited to a single value. +* These endpoints replace those defined in the top-level `Urls` configuration rather than adding to them. Endpoints defined in code via `Listen` are cumulative with the endpoints defined in the configuration section. +* The `Certificate` section is optional. If the `Certificate` section isn't specified, the defaults defined in earlier scenarios are used. If no defaults are available, the server throws an exception and fails to start. +* The `Certificate` section supports both `Path`–`Password` and `Subject`–`Store` certificates. +* Any number of endpoints may be defined in this way so long as they don't cause port conflicts. +* `options.Configure(context.Configuration.GetSection("{SECTION}"))` returns a `KestrelConfigurationLoader` with an `.Endpoint(string name, listenOptions => { })` method that can be used to supplement a configured endpoint's settings: + +```csharp +webBuilder.UseKestrel((context, serverOptions) => +{ + serverOptions.Configure(context.Configuration.GetSection("Kestrel")) + .Endpoint("HTTPS", listenOptions => + { + listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12; + }); +}); +``` + +`KestrelServerOptions.ConfigurationLoader` can be directly accessed to continue iterating on the existing loader, such as the one provided by . + +* The configuration section for each endpoint is available on the options in the `Endpoint` method so that custom settings may be read. +* Multiple configurations may be loaded by calling `options.Configure(context.Configuration.GetSection("{SECTION}"))` again with another section. Only the last configuration is used, unless `Load` is explicitly called on prior instances. The metapackage doesn't call `Load` so that its default configuration section may be replaced. +* `KestrelConfigurationLoader` mirrors the `Listen` family of APIs from `KestrelServerOptions` as `Endpoint` overloads, so code and config endpoints may be configured in the same place. These overloads don't use names and only consume default settings from configuration. + +### Change the defaults in code + +`ConfigureEndpointDefaults` and `ConfigureHttpsDefaults` can be used to change default settings for `ListenOptions` and `HttpsConnectionAdapterOptions`, including overriding the default certificate specified in the prior scenario. `ConfigureEndpointDefaults` and `ConfigureHttpsDefaults` should be called before any endpoints are configured. + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.ConfigureEndpointDefaults(listenOptions => + { + // Configure endpoint defaults + }); + + serverOptions.ConfigureHttpsDefaults(listenOptions => + { + listenOptions.SslProtocols = SslProtocols.Tls12; + }); +}); +``` + +## Configure endpoints using Server Name Indication + +[Server Name Indication (SNI)](https://tools.ietf.org/html/rfc6066#section-3) can be used to host multiple domains on the same IP address and port. For SNI to function, the client sends the host name for the secure session to the server during the TLS handshake so that the server can provide the correct certificate. The client uses the furnished certificate for encrypted communication with the server during the secure session that follows the TLS handshake. + +Kestrel supports SNI via the `ServerCertificateSelector` callback. The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate. The following callback code can be used in the `ConfigureWebHostDefaults` method call of a project's *Program.cs* file: + +```csharp +//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(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 support requires: + +* Running on target framework `netcoreapp2.1` or later. On `net461` or later, the callback is invoked but the `name` is always `null`. The `name` is also `null` if the client doesn't provide the host name parameter in the TLS handshake. +* All websites run on the same Kestrel instance. Kestrel doesn't support sharing an IP address and port across multiple instances without a reverse proxy. + +## Connection logging + +Call to emit Debug level logs for byte-level communication on a connection. Connection logging is helpful for troubleshooting problems in low-level communication, such as during TLS encryption and behind proxies. If `UseConnectionLogging` is placed before `UseHttps`, encrypted traffic is logged. If `UseConnectionLogging` is placed after `UseHttps`, decrypted traffic is logged. This is built-in [Connection Middleware](#connection-middleware). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Listen(IPAddress.Any, 8000, listenOptions => + { + listenOptions.UseConnectionLogging(); + }); +}); +``` + +## Bind to a TCP socket + +The method binds to a TCP socket, and an options lambda permits X.509 certificate configuration: + +[!code-csharp[](samples/5.x/KestrelSample/Program.cs?name=snippet_TCPSocket&highlight=12-18)] + +The example configures HTTPS for an endpoint with . Use the same API to configure other Kestrel settings for specific endpoints. + +[!INCLUDE [How to make an X.509 cert](~/includes/make-x509-cert.md)] + +## Bind to a Unix socket + +Listen on a Unix socket with for improved performance with Nginx, as shown in this example: + +[!code-csharp[](samples/5.x/KestrelSample/Program.cs?name=snippet_UnixSocket)] + +* In the Nginx configuration file, set the `server` > `location` > `proxy_pass` entry to `http://unix:/tmp/{KESTREL SOCKET}:/;`. `{KESTREL SOCKET}` is the name of the socket provided to (for example, `kestrel-test.sock` in the preceding example). +* Ensure that the socket is writeable by Nginx (for example, `chmod go+w /tmp/kestrel-test.sock`). + +## Port 0 + +When the port number `0` is specified, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel bound at runtime: + +[!code-csharp[](samples/5.x/KestrelSample/Startup.cs?name=snippet_Configure&highlight=3-4,15-21)] + +When the app is run, the console window output indicates the dynamic port where the app can be reached: + +```console +Listening on the following addresses: http://127.0.0.1:48508 +``` + +## Limitations + +Configure endpoints with the following approaches: + +* +* `--urls` command-line argument +* `urls` host configuration key +* `ASPNETCORE_URLS` environment variable + +These methods are useful for making code work with servers other than Kestrel. However, be aware of the following limitations: + +* HTTPS can't be used with these approaches unless a default certificate is provided in the HTTPS endpoint configuration (for example, using `KestrelServerOptions` configuration or a configuration file as shown earlier in this article). +* When both the `Listen` and `UseUrls` approaches are used simultaneously, the `Listen` endpoints override the `UseUrls` endpoints. + +## IIS endpoint configuration + +When using IIS, the URL bindings for IIS override bindings are set by either `Listen` or `UseUrls`. For more information, see [ASP.NET Core Module](xref:host-and-deploy/aspnet-core-module). + +## ListenOptions.Protocols + +The `Protocols` property establishes the HTTP protocols (`HttpProtocols`) enabled on a connection endpoint or for the server. Assign a value to the `Protocols` property from the `HttpProtocols` enum. + +| `HttpProtocols` enum value | Connection protocol permitted | +| -------------------------- | ----------------------------- | +| `Http1` | HTTP/1.1 only. Can be used with or without TLS. | +| `Http2` | HTTP/2 only. May be used without TLS only if the client supports a [Prior Knowledge mode](https://tools.ietf.org/html/rfc7540#section-3.4). | +| `Http1AndHttp2` | HTTP/1.1 and HTTP/2. HTTP/2 requires the client to select HTTP/2 in the TLS [Application-Layer Protocol Negotiation (ALPN)](https://tools.ietf.org/html/rfc7301#section-3) handshake; otherwise, the connection defaults to HTTP/1.1. | + +The default `ListenOptions.Protocols` value for any endpoint is `HttpProtocols.Http1AndHttp2`. + +TLS restrictions for HTTP/2: + +* TLS version 1.2 or later +* Renegotiation disabled +* Compression disabled +* Minimum ephemeral key exchange sizes: + * Elliptic curve Diffie-Hellman (ECDHE) [[RFC4492](https://www.ietf.org/rfc/rfc4492.txt)]: 224 bits minimum + * Finite field Diffie-Hellman (DHE) [`TLS12`]: 2048 bits minimum +* Cipher suite not prohibited. + +`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` [`TLS-ECDHE`] with the P-256 elliptic curve [`FIPS186`] is supported by default. + +The following example permits HTTP/1.1 and HTTP/2 connections on port 8000. Connections are secured by TLS with a supplied certificate: + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Listen(IPAddress.Any, 8000, listenOptions => + { + listenOptions.UseHttps("testCert.pfx", "testPassword"); + }); +}); +``` + +On Linux, can be used to filter TLS handshakes on a per-connection basis: + +```csharp +// 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, + // ... + }); + }; + }); +}); +``` + +## Connection Middleware + +Custom connection middleware can filter TLS handshakes on a per-connection basis for specific ciphers if necessary. + +The following example throws for any cipher algorithm that the app doesn't support. Alternatively, define and compare [ITlsHandshakeFeature.CipherAlgorithm](xref:Microsoft.AspNetCore.Connections.Features.ITlsHandshakeFeature.CipherAlgorithm) to a list of acceptable cipher suites. + +No encryption is used with a [CipherAlgorithmType.Null](xref:System.Security.Authentication.CipherAlgorithmType) cipher algorithm. + +```csharp +// using System.Net; +// using Microsoft.AspNetCore.Connections; + +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Listen(IPAddress.Any, 8000, listenOptions => + { + listenOptions.UseHttps("testCert.pfx", "testPassword"); + listenOptions.UseTlsFilter(); + }); +}); +``` + +```csharp +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(); + + if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null) + { + throw new NotSupportedException("Prohibited cipher: " + + tlsFeature.CipherAlgorithm); + } + + return next(); + }); + } + } +} +``` + +Connection filtering can also be configured via an lambda: + +```csharp +// 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(); + + if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null) + { + throw new NotSupportedException( + $"Prohibited cipher: {tlsFeature.CipherAlgorithm}"); + } + + return next(); + }); + }); +}); +``` + +## Set the HTTP protocol from configuration + +`CreateDefaultBuilder` calls `serverOptions.Configure(context.Configuration.GetSection("Kestrel"))` by default to load Kestrel configuration. + +The following *appsettings.json* example establishes HTTP/1.1 as the default connection protocol for all endpoints: + +```json +{ + "Kestrel": { + "EndpointDefaults": { + "Protocols": "Http1" + } + } +} +``` + +The following *appsettings.json* example establishes the HTTP/1.1 connection protocol for a specific endpoint: + +```json +{ + "Kestrel": { + "Endpoints": { + "HttpsDefaultCert": { + "Url": "https://localhost:5001", + "Protocols": "Http1" + } + } + } +} +``` + +Protocols specified in code override values set by configuration. + +## URL prefixes + +When using `UseUrls`, `--urls` command-line argument, `urls` host configuration key, or `ASPNETCORE_URLS` environment variable, the URL prefixes can be in any of the following formats. + +Only HTTP URL prefixes are valid. Kestrel doesn't support HTTPS when configuring URL bindings using `UseUrls`. + +* IPv4 address with port number + + ``` + http://65.55.39.10:80/ + ``` + + `0.0.0.0` is a special case that binds to all IPv4 addresses. + +* IPv6 address with port number + + ``` + http://[0:0:0:0:0:ffff:4137:270a]:80/ + ``` + + `[::]` is the IPv6 equivalent of IPv4 `0.0.0.0`. + +* Host name with port number + + ``` + http://contoso.com:80/ + http://*:80/ + ``` + + Host names, `*`, and `+`, aren't special. Anything not recognized as a valid IP address or `localhost` binds to all IPv4 and IPv6 IPs. To bind different host names to different ASP.NET Core apps on the same port, use [HTTP.sys](xref:fundamentals/servers/httpsys) or a reverse proxy server. Reverse proxy server examples include IIS, Nginx, or Apache. + + > [!WARNING] + > Hosting in a reverse proxy configuration requires [host filtering](xref:fundamentals/servers/kestrel/host-filtering). + +* Host `localhost` name with port number or loopback IP with port number + + ``` + http://localhost:5000/ + http://127.0.0.1:5000/ + http://[::1]:5000/ + ``` + + When `localhost` is specified, Kestrel attempts to bind to both IPv4 and IPv6 loopback interfaces. If the requested port is in use by another service on either loopback interface, Kestrel fails to start. If either loopback interface is unavailable for any other reason (most commonly because IPv6 isn't supported), Kestrel logs a warning. diff --git a/aspnetcore/fundamentals/servers/kestrel/host-filtering.md b/aspnetcore/fundamentals/servers/kestrel/host-filtering.md new file mode 100644 index 000000000000..fcddeb95cdd2 --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/host-filtering.md @@ -0,0 +1,34 @@ +--- +title: Host filtering with ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about using host filtering with Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 05/04/2020 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/host-filtering +--- + +# Host filtering with ASP.NET Core Kestrel web server + +While Kestrel supports configuration based on prefixes such as `http://example.com:5000`, Kestrel largely ignores the host name. Host `localhost` is a special case used for binding to loopback addresses. Any host other than an explicit IP address binds to all public IP addresses. `Host` headers aren't validated. + +As a workaround, use Host Filtering Middleware. Host Filtering Middleware is provided by the [Microsoft.AspNetCore.HostFiltering](https://www.nuget.org/packages/Microsoft.AspNetCore.HostFiltering) package, which is implicitly provided for ASP.NET Core apps. The middleware is added by , which calls : + +[!code-csharp[](samples-snapshot/2.x/KestrelSample/Program.cs?name=snippet_Program&highlight=9)] + +Host Filtering Middleware is disabled by default. To enable the middleware, define an `AllowedHosts` key in *appsettings.json*/*appsettings.\.json*. The value is a semicolon-delimited list of host names without port numbers: + +*appsettings.json*: + +```json +{ + "AllowedHosts": "example.com;localhost" +} +``` + +> [!NOTE] +> [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) also has an option. Forwarded Headers Middleware and Host Filtering Middleware have similar functionality for different scenarios. Setting `AllowedHosts` with Forwarded Headers Middleware is appropriate when the `Host` header isn't preserved while forwarding requests with a reverse proxy server or load balancer. Setting `AllowedHosts` with Host Filtering Middleware is appropriate when Kestrel is used as a public-facing edge server or when the `Host` header is directly forwarded. +> +> For more information on Forwarded Headers Middleware, see . diff --git a/aspnetcore/fundamentals/servers/kestrel/http2.md b/aspnetcore/fundamentals/servers/kestrel/http2.md new file mode 100644 index 000000000000..fc5ca25f122f --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/http2.md @@ -0,0 +1,41 @@ +--- +title: Use HTTP/2 with the ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about using HTTP/2 with Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 05/04/2020 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/http2 +--- + +# Use HTTP/2 with the ASP.NET Core Kestrel web server + +[HTTP/2](https://httpwg.org/specs/rfc7540.html) is available for ASP.NET Core apps if the following base requirements are met: + +* Operating system† + * Windows Server 2016/Windows 10 or later‡ + * Linux with OpenSSL 1.0.2 or later (for example, Ubuntu 16.04 or later) +* Target framework: .NET Core 2.2 or later +* [Application-Layer Protocol Negotiation (ALPN)](https://tools.ietf.org/html/rfc7301#section-3) connection +* TLS 1.2 or later connection + +†HTTP/2 will be supported on macOS in a future release. +‡Kestrel has limited support for HTTP/2 on Windows Server 2012 R2 and Windows 8.1. Support is limited because the list of supported TLS cipher suites available on these operating systems is limited. A certificate generated using an Elliptic Curve Digital Signature Algorithm (ECDSA) may be required to secure TLS connections. + +If an HTTP/2 connection is established, [HttpRequest.Protocol](xref:Microsoft.AspNetCore.Http.HttpRequest.Protocol%2A) reports `HTTP/2`. + +Starting with .NET Core 3.0, HTTP/2 is enabled by default. For more information on configuration, see the [Kestrel HTTP/2 limits](xref:fundamentals/servers/kestrel/options#http2-limits) and [ListenOptions.Protocols](xref:fundamentals/servers/kestrel/endpoints#listenoptionsprotocols) sections. + +## Advanced HTTP/2 features + +Additional HTTP/2 features in Kestrel support gRPC, including support for response trailers and sending reset frames. + +### Trailers + +[!INCLUDE[](~/includes/trailers.md)] + +### Reset + +[!INCLUDE[](~/includes/reset.md)] diff --git a/aspnetcore/fundamentals/servers/kestrel/options.md b/aspnetcore/fundamentals/servers/kestrel/options.md new file mode 100644 index 000000000000..6a8c90a91657 --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/options.md @@ -0,0 +1,309 @@ +--- +title: Configure options for the ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about configuring options for Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 05/04/2020 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/options +--- + +# Configure options for the ASP.NET Core Kestrel web server + +The Kestrel web server has constraint configuration options that are especially useful in Internet-facing deployments. + +To provide additional configuration after calling `ConfigureWebHostDefaults`, use `ConfigureKestrel`: + +```csharp +public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureKestrel(serverOptions => + { + // Set properties and call methods on options + }) + .UseStartup(); + }); +``` + +Set constraints on the property of the class. The `Limits` property holds an instance of the class. + +The following examples use the namespace: + +```csharp +using Microsoft.AspNetCore.Server.Kestrel.Core; +``` + +In examples shown later in this article, Kestrel options are configured in C# code. Kestrel options can also be set using a [configuration provider](xref:fundamentals/configuration/index). For example, the [File Configuration Provider](xref:fundamentals/configuration/index#file-configuration-provider) can load Kestrel configuration from an *appsettings.json* or *appsettings.{Environment}.json* file: + +```json +{ + "Kestrel": { + "Limits": { + "MaxConcurrentConnections": 100, + "MaxConcurrentUpgradedConnections": 100 + }, + "DisableStringReuse": true + } +} +``` + +> [!NOTE] +> and [endpoint configuration](xref:fundamentals/servers/kestrel/endpoints) are configurable from configuration providers. Remaining Kestrel configuration must be configured in C# code. + +Use **one** of the following approaches: + +* Configure Kestrel in `Startup.ConfigureServices`: + + 1. Inject an instance of `IConfiguration` into the `Startup` class. The following example assumes that the injected configuration is assigned to the `Configuration` property. + 2. In `Startup.ConfigureServices`, load the `Kestrel` section of configuration into Kestrel's configuration: + + ```csharp + using Microsoft.Extensions.Configuration + + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.Configure( + Configuration.GetSection("Kestrel")); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + ... + } + } + ``` + +* Configure Kestrel when building the host: + + In *Program.cs*, load the `Kestrel` section of configuration into Kestrel's configuration: + + ```csharp + // using Microsoft.Extensions.DependencyInjection; + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((context, services) => + { + services.Configure( + context.Configuration.GetSection("Kestrel")); + }) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + ``` + +Both of the preceding approaches work with any [configuration provider](xref:fundamentals/configuration/index). + +## General limits + +### Keep-alive timeout + + + +Gets or sets the [keep-alive timeout](https://tools.ietf.org/html/rfc7230#section-6.5). Defaults to 2 minutes. + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=19-20)] + +### Maximum client connections + + + + +The maximum number of concurrent open TCP connections can be set for the entire app with the following code: + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=3)] + +There's a separate limit for connections that have been upgraded from HTTP or HTTPS to another protocol (for example, on a WebSockets request). After a connection is upgraded, it isn't counted against the `MaxConcurrentConnections` limit. + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=4)] + +The maximum number of connections is unlimited (null) by default. + +### Maximum request body size + + + +The default maximum request body size is 30,000,000 bytes, which is approximately 28.6 MB. + +The recommended approach to override the limit in an ASP.NET Core MVC app is to use the attribute on an action method: + +```csharp +[RequestSizeLimit(100000000)] +public IActionResult MyActionMethod() +``` + +Here's an example that shows how to configure the constraint for the app on every request: + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=5)] + +Override the setting on a specific request in middleware: + +[!code-csharp[](samples/3.x/KestrelSample/Startup.cs?name=snippet_Limits&highlight=3-4)] + +An exception is thrown if the app configures the limit on a request after the app has started to read the request. There's an `IsReadOnly` property that indicates if the `MaxRequestBodySize` property is in read-only state, meaning it's too late to configure the limit. + +When an app runs [out-of-process](xref:host-and-deploy/iis/index#out-of-process-hosting-model) behind the [ASP.NET Core Module](xref:host-and-deploy/aspnet-core-module), Kestrel's request body size limit is disabled. IIS already sets the limit. + +### Minimum request body data rate + + + + +Kestrel checks every second if data is arriving at the specified rate in bytes/second. If the rate drops below the minimum, the connection is timed out. The grace period is the amount of time Kestrel allows the client to increase its send rate up to the minimum. The rate isn't checked during that time. The grace period helps avoid dropping connections that are initially sending data at a slow rate because of TCP slow-start. + +The default minimum rate is 240 bytes/second with a 5-second grace period. + +A minimum rate also applies to the response. The code to set the request limit and the response limit is the same except for having `RequestBody` or `Response` in the property and interface names. + +Here's an example that shows how to configure the minimum data rates in *Program.cs*: + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=6-11)] + +Override the minimum rate limits per request in middleware: + +[!code-csharp[](samples/3.x/KestrelSample/Startup.cs?name=snippet_Limits&highlight=6-21)] + +The referenced in the prior sample isn't present in `HttpContext.Features` for HTTP/2 requests. Modifying rate limits on a per-request basis is generally not supported for HTTP/2 because of the protocol's support for request multiplexing. However, the is still present `HttpContext.Features` for HTTP/2 requests, because the read rate limit can still be *disabled entirely* on a per-request basis by setting `IHttpMinRequestBodyDataRateFeature.MinDataRate` to `null` even for an HTTP/2 request. Attempting to read `IHttpMinRequestBodyDataRateFeature.MinDataRate` or attempting to set it to a value other than `null` will result in a `NotSupportedException` being thrown given an HTTP/2 request. + +Server-wide rate limits configured via `KestrelServerOptions.Limits` still apply to both HTTP/1.x and HTTP/2 connections. + +### Request headers timeout + + + +Gets or sets the maximum amount of time the server spends receiving request headers. Defaults to 30 seconds. + +[!code-csharp[](samples/3.x/KestrelSample/Program.cs?name=snippet_Limits&highlight=21-22)] + +## HTTP/2 limits + +### Maximum streams per connection + +`Http2.MaxStreamsPerConnection` limits the number of concurrent request streams per HTTP/2 connection. Excess streams are refused. + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.MaxStreamsPerConnection = 100; +}); +``` + +The default value is 100. + +### Header table size + +The HPACK decoder decompresses HTTP headers for HTTP/2 connections. `Http2.HeaderTableSize` limits the size of the header compression table that the HPACK decoder uses. The value is provided in octets and must be greater than zero (0). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.HeaderTableSize = 4096; +}); +``` + +The default value is 4096. + +### Maximum frame size + +`Http2.MaxFrameSize` indicates the maximum allowed size of an HTTP/2 connection frame payload received or sent by the server. The value is provided in octets and must be between 2^14 (16,384) and 2^24-1 (16,777,215). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.MaxFrameSize = 16384; +}); +``` + +The default value is 2^14 (16,384). + +### Maximum request header size + +`Http2.MaxRequestHeaderFieldSize` indicates the maximum allowed size in octets of request header values. This limit applies to both name and value in their compressed and uncompressed representations. The value must be greater than zero (0). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192; +}); +``` + +The default value is 8,192. + +### Initial connection window size + +`Http2.InitialConnectionWindowSize` indicates the maximum request body data in bytes the server buffers at one time aggregated across all requests (streams) per connection. Requests are also limited by `Http2.InitialStreamWindowSize`. The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072; +}); +``` + +The default value is 128 KB (131,072). + +### Initial stream window size + +`Http2.InitialStreamWindowSize` indicates the maximum request body data in bytes the server buffers at one time per request (stream). Requests are also limited by `Http2.InitialConnectionWindowSize`. The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648). + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.InitialStreamWindowSize = 98304; +}); +``` + +The default value is 96 KB (98,304). + +### HTTP/2 keep alive ping configuration + +Kestrel can be configured to send HTTP/2 pings to connected clients. HTTP/2 pings serve multiple purposes: + +* Keep idle connections alive. Some clients and proxy servers close connections that are idle. HTTP/2 pings are considered as activity on a connection and prevent the connection from being closed as idle. +* Close unhealthy connections. Connections where the client doesn't respond to the keep alive ping in the configured time are closed by the server. + +There are two configuration options related to HTTP/2 keep alive pings: + +* `Http2.KeepAlivePingInterval` is a `TimeSpan` that configures the ping interval. The server sends a keep alive ping to the client if it doesn't receive any frames for this period of time. Keep alive pings are disabled when this option is set to `TimeSpan.MaxValue`. The default value is `TimeSpan.MaxValue`. +* `Http2.KeepAlivePingTimeout` is a `TimeSpan` that configures the ping timeout. If the server doesn't receive any frames, such as a response ping, during this timeout then the connection is closed. Keep alive timeout is disabled when this option is set to `TimeSpan.MaxValue`. The default value is 20 seconds. + +```csharp +webBuilder.ConfigureKestrel(serverOptions => +{ + serverOptions.Limits.Http2.KeepAlivePingInterval = TimeSpan.FromSeconds(30); + serverOptions.Limits.Http2.KeepAlivePingTimeout = TimeSpan.FromSeconds(60); +}); +``` + +## Other options + +### Synchronous I/O + + controls whether synchronous I/O is allowed for the request and response. The default value is `false`. + +> [!WARNING] +> A large number of blocking synchronous I/O operations can lead to thread pool starvation, which makes the app unresponsive. Only enable `AllowSynchronousIO` when using a library that doesn't support asynchronous I/O. + +The following example enables synchronous I/O: + +[!code-csharp[](samples/5.x/KestrelSample/Program.cs?name=snippet_SyncIO)] + +For information about other Kestrel options and limits, see: + +* +* +* diff --git a/aspnetcore/fundamentals/servers/kestrel/request-draining.md b/aspnetcore/fundamentals/servers/kestrel/request-draining.md new file mode 100644 index 000000000000..3bebe227d992 --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/request-draining.md @@ -0,0 +1,41 @@ +--- +title: Request draining with ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about request draining with Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 05/04/2020 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/request-draining +--- + +# Request draining with ASP.NET Core Kestrel web server + +Opening HTTP connections is time consuming. For HTTPS, it's also resource intensive. Therefore, Kestrel tries to reuse connections per the HTTP/1.1 protocol. A request body must be fully consumed to allow the connection to be reused. The app doesn't always consume the request body, such as HTTP POST requests where the server returns a redirect or 404 response. In the HTTP POST redirect case: + +* The client may already have sent part of the POST data. +* The server writes the 301 response. +* The connection can't be used for a new request until the POST data from the previous request body has been fully read. +* Kestrel tries to drain the request body. Draining the request body means reading and discarding the data without processing it. + +The draining process makes a tradeoff between allowing the connection to be reused and the time it takes to drain any remaining data: + +* Draining has a timeout of five seconds, which isn't configurable. +* If all of the data specified by the `Content-Length` or `Transfer-Encoding` header hasn't been read before the timeout, the connection is closed. + +Sometimes you may want to terminate the request immediately, before or after writing the response. For example, clients may have restrictive data caps. Limiting uploaded data might be a priority. In such cases to terminate a request, call [HttpContext.Abort](xref:Microsoft.AspNetCore.Http.HttpContext.Abort%2A) from a controller, Razor Page, or middleware. + +There are caveats to calling `Abort`: + +* Creating new connections can be slow and expensive. +* There's no guarantee that the client has read the response before the connection closes. +* Calling `Abort` should be rare and reserved for severe error cases, not common errors. + * Only call `Abort` when a specific problem needs to be solved. For example, call `Abort` if malicious clients are trying to POST data or when there's a bug in client code that causes large or several requests. + * Don't call `Abort` for common error situations, such as HTTP 404 (Not Found). + +Calling [HttpResponse.CompleteAsync](xref:Microsoft.AspNetCore.Http.HttpResponse.CompleteAsync%2A) before calling `Abort` ensures that the server has completed writing the response. However, client behavior isn't predictable and they may not read the response before the connection is aborted. + +This process is different for HTTP/2 because the protocol supports aborting individual request streams without closing the connection. The five-second drain timeout doesn't apply. If there's any unread request body data after completing a response, then the server sends an HTTP/2 RST frame. Additional request body data frames are ignored. + +If possible, it's better for clients to use the [Expect: 100-continue](https://developer.mozilla.org/docs/Web/HTTP/Status/100) request header and wait for the server to respond before starting to send the request body. That gives the client an opportunity to examine the response and abort before sending unneeded data. diff --git a/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/KestrelSample.csproj b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/KestrelSample.csproj new file mode 100644 index 000000000000..adf24d47c78c --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/KestrelSample.csproj @@ -0,0 +1,7 @@ + + + + net5.0 + + + diff --git a/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Program.cs b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Program.cs new file mode 100644 index 000000000000..74001c4b913c --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Program.cs @@ -0,0 +1,181 @@ +#define DefaultBuilder +// Define any of the following for the scenarios described in the Kestrel topic: +// DefaultBuilder Limits TCPSocket UnixSocket FileDescriptor Port0 SyncIO +// The following require an X.509 certificate: +// TCPSocket UnixSocket FileDescriptor Limits + +using System; +using System.Net; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Hosting; + +namespace KestrelSample +{ + public class Program + { +#if DefaultBuilder + #region snippet_DefaultBuilder + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + #endregion +#elif TCPSocket + #region snippet_TCPSocket + 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(); + }); + #endregion +#elif UnixSocket + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + #region snippet_UnixSocket + webBuilder.ConfigureKestrel(serverOptions => + { + serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock"); + serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", + listenOptions => + { + listenOptions.UseHttps("testCert.pfx", + "testpassword"); + }); + }) + #endregion + .UseStartup(); + }); +#elif FileDescriptor + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + #region snippet_FileDescriptor + webBuilder.ConfigureKestrel(serverOptions => + { + var fds = Environment + .GetEnvironmentVariable("SD_LISTEN_FDS_START"); + var fd = ulong.Parse(fds); + + serverOptions.ListenHandle(fd); + serverOptions.ListenHandle(fd, listenOptions => + { + listenOptions.UseHttps("testCert.pfx", "testpassword"); + }); + }) + #endregion + .UseStartup(); + }); +#elif Limits + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + #region snippet_Limits + 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); + }) + #endregion + .UseStartup(); + }); +#elif Port0 + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + #region snippet_Port0 + webBuilder.ConfigureKestrel(serverOptions => + { + serverOptions.Listen(IPAddress.Loopback, 0); + }) + #endregion + .UseStartup(); + }); +#elif SyncIO + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + #region snippet_SyncIO + webBuilder.ConfigureKestrel(serverOptions => + { + serverOptions.AllowSynchronousIO = true; + }) + #endregion + .UseStartup(); + }); +#endif + } +} diff --git a/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Startup.cs b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Startup.cs new file mode 100644 index 000000000000..52b4dbfd4890 --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/samples/5.x/KestrelSample/Startup.cs @@ -0,0 +1,96 @@ +#define Default // or Limits + +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.AspNetCore.Server.Kestrel.Core.Features; + +namespace KestrelSample +{ + public class Startup + { +#if Default + #region snippet_Configure + public void Configure(IApplicationBuilder app) + { + var serverAddressesFeature = + app.ServerFeatures.Get(); + + 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()}

"); + }); + } + #endregion +#elif Limits + public void Configure(IApplicationBuilder app) + { + var serverAddressesFeature = app.ServerFeatures.Get(); + + app.UseStaticFiles(); + + #region snippet_Limits + app.Run(async (context) => + { + context.Features.Get() + .MaxRequestBodySize = 10 * 1024; + + var minRequestRateFeature = + context.Features.Get(); + var minResponseRateFeature = + context.Features.Get(); + + 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)); + } + #endregion + 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()}

"); + }); + } +#endif + } +} diff --git a/aspnetcore/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy.md b/aspnetcore/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy.md new file mode 100644 index 000000000000..c86017e4acad --- /dev/null +++ b/aspnetcore/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy.md @@ -0,0 +1,44 @@ +--- +title: When to use a reverse proxy with the ASP.NET Core Kestrel web server +author: rick-anderson +description: Learn about when to use a reverse proxy in front of Kestrel, the cross-platform web server for ASP.NET Core. +monikerRange: '>= aspnetcore-5.0' +ms.author: riande +ms.custom: mvc +ms.date: 01/14/2021 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: fundamentals/servers/kestrel/when-to-use-a-reverse-proxy +--- + +# When to use Kestrel with a reverse proxy + +Kestrel can be used by itself or with a *reverse proxy server*, such as [Internet Information Services (IIS)](https://www.iis.net/), [Nginx](https://nginx.org), or [Apache](https://httpd.apache.org/). A reverse proxy server receives HTTP requests from the network and forwards them to Kestrel. + +Kestrel used as an edge (Internet-facing) web server: + +![Kestrel communicates directly with the Internet without a reverse proxy server](_static/kestrel-to-internet2.png) + +Kestrel used in a reverse proxy configuration: + +![Kestrel communicates indirectly with the Internet through a reverse proxy server, such as IIS, Nginx, or Apache](_static/kestrel-to-internet.png) + +Either configuration, with or without a reverse proxy server, is a supported hosting configuration. + +When Kestrel is used as an edge server without a reverse proxy server, sharing of the same IP address and port among multiple processes is unsupported. When Kestrel is configured to listen on a port, Kestrel handles all traffic for that port regardless of requests' `Host` headers. A reverse proxy that can share ports can forward requests to Kestrel on a unique IP and port. + +Even if a reverse proxy server isn't required, using a reverse proxy server might be a good choice. + +A reverse proxy: + +* Can limit the exposed public surface area of the apps that it hosts. +* Provide an additional layer of configuration and defense. +* Might integrate better with existing infrastructure. +* Simplify load balancing and secure communication (HTTPS) configuration. Only the reverse proxy server requires an X.509 certificate, and that server can communicate with the app's servers on the internal network using plain HTTP. + +> [!WARNING] +> Hosting in a reverse proxy configuration requires [host filtering](xref:fundamentals/servers/kestrel/host-filtering). + +## Additional resources + + + diff --git a/aspnetcore/grpc/aspnetcore.md b/aspnetcore/grpc/aspnetcore.md index 4f0018ab074e..2440c6d951d4 100644 --- a/aspnetcore/grpc/aspnetcore.md +++ b/aspnetcore/grpc/aspnetcore.md @@ -4,7 +4,7 @@ author: juntaoluo description: Learn the basic concepts when writing gRPC services with ASP.NET Core. monikerRange: '>= aspnetcore-3.0' ms.author: johluo -ms.date: 09/03/2019 +ms.date: 01/14/2021 no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] uid: grpc/aspnetcore --- @@ -58,7 +58,49 @@ In *Startup.cs*: [!code-csharp[](~/tutorials/grpc/grpc-start/sample/GrpcGreeter/Startup.cs?name=snippet&highlight=7,24)] [!INCLUDE[about the series](~/includes/code-comments-loc.md)] -ASP.NET Core middlewares and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. +ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. + +::: moniker range=">= aspnetcore-5.0" + +### Configure Kestrel + +Kestrel gRPC endpoints: + +* Require HTTP/2. +* Should be secured with [Transport Layer Security (TLS)](https://tools.ietf.org/html/rfc5246). + +#### HTTP/2 + +gRPC requires HTTP/2. gRPC for ASP.NET Core validates [HttpRequest.Protocol](xref:Microsoft.AspNetCore.Http.HttpRequest.Protocol%2A) is `HTTP/2`. + +Kestrel [supports HTTP/2](xref:fundamentals/servers/kestrel/http2) on most modern operating systems. Kestrel endpoints are configured to support HTTP/1.1 and HTTP/2 connections by default. + +#### TLS + +Kestrel endpoints used for gRPC should be secured with TLS. In development, an endpoint secured with TLS is automatically created at `https://localhost:5001` when the ASP.NET Core development certificate is present. No configuration is required. An `https` prefix verifies the Kestrel endpoint is using TLS. + +In production, TLS must be explicitly configured. In the following *appsettings.json* example, an HTTP/2 endpoint secured with TLS is provided: + +[!code-json[](~/grpc/aspnetcore/sample/appsettings.json?highlight=4)] + +Alternatively, Kestrel endpoints can be configured in *Program.cs*: + +[!code-csharp[](~/grpc/aspnetcore/sample/Program.cs?highlight=7&name=snippet)] + +#### Protocol negotiation + +TLS is used for more than securing communication. The TLS [Application-Layer Protocol Negotiation (ALPN)](https://tools.ietf.org/html/rfc7301#section-3) handshake is used to negotiate the connection protocol between the client and the server when an endpoint supports multiple protocols. This negotiation determines whether the connection uses HTTP/1.1 or HTTP/2. + +If an HTTP/2 endpoint is configured without TLS, the endpoint's [ListenOptions.Protocols](xref:fundamentals/servers/kestrel/endpoints#listenoptionsprotocols) must be set to `HttpProtocols.Http2`. An endpoint with multiple protocols (for example, `HttpProtocols.Http1AndHttp2`) can't be used without TLS because there's no negotiation. All connections to the unsecured endpoint default to HTTP/1.1, and gRPC calls fail. + +For more information on enabling HTTP/2 and TLS with Kestrel, see [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel/endpoints). + +> [!NOTE] +> macOS doesn't support ASP.NET Core gRPC with TLS. Additional configuration is required to successfully run gRPC services on macOS. For more information, see [Unable to start ASP.NET Core gRPC app on macOS](xref:grpc/troubleshoot#unable-to-start-aspnet-core-grpc-app-on-macos). + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" ### Configure Kestrel @@ -69,7 +111,7 @@ Kestrel gRPC endpoints: #### HTTP/2 -gRPC requires HTTP/2. gRPC for ASP.NET Core validates [HttpRequest.Protocol](xref:Microsoft.AspNetCore.Http.HttpRequest.Protocol*) is `HTTP/2`. +gRPC requires HTTP/2. gRPC for ASP.NET Core validates [HttpRequest.Protocol](xref:Microsoft.AspNetCore.Http.HttpRequest.Protocol%2A) is `HTTP/2`. Kestrel [supports HTTP/2](xref:fundamentals/servers/kestrel#http2-support) on most modern operating systems. Kestrel endpoints are configured to support HTTP/1.1 and HTTP/2 connections by default. @@ -89,13 +131,15 @@ Alternatively, Kestrel endpoints can be configured in *Program.cs*: TLS is used for more than securing communication. The TLS [Application-Layer Protocol Negotiation (ALPN)](https://tools.ietf.org/html/rfc7301#section-3) handshake is used to negotiate the connection protocol between the client and the server when an endpoint supports multiple protocols. This negotiation determines whether the connection uses HTTP/1.1 or HTTP/2. -If an HTTP/2 endpoint is configured without TLS, the endpoint's [ListenOptions.Protocols](xref:fundamentals/servers/kestrel#listenoptionsprotocols) must be set to `HttpProtocols.Http2`. An endpoint with multiple protocols (for example, `HttpProtocols.Http1AndHttp2`) can't be used without TLS because there is no negotiation. All connections to the unsecured endpoint default to HTTP/1.1, and gRPC calls fail. +If an HTTP/2 endpoint is configured without TLS, the endpoint's [ListenOptions.Protocols](xref:fundamentals/servers/kestrel#listenoptionsprotocols) must be set to `HttpProtocols.Http2`. An endpoint with multiple protocols (for example, `HttpProtocols.Http1AndHttp2`) can't be used without TLS because there's no negotiation. All connections to the unsecured endpoint default to HTTP/1.1, and gRPC calls fail. For more information on enabling HTTP/2 and TLS with Kestrel, see [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). > [!NOTE] > macOS doesn't support ASP.NET Core gRPC with TLS. Additional configuration is required to successfully run gRPC services on macOS. For more information, see [Unable to start ASP.NET Core gRPC app on macOS](xref:grpc/troubleshoot#unable-to-start-aspnet-core-grpc-app-on-macos). +::: moniker-end + ## Integration with ASP.NET Core APIs gRPC services have full access to the ASP.NET Core features such as [Dependency Injection](xref:fundamentals/dependency-injection) (DI) and [Logging](xref:fundamentals/logging/index). For example, the service implementation can resolve a logger service from the DI container via the constructor: @@ -117,7 +161,7 @@ The gRPC API provides access to some HTTP/2 message data, such as the method, ho [!code-csharp[](~/grpc/aspnetcore/sample/GrcpService/GreeterService.cs?highlight=3-4&name=snippet)] -`ServerCallContext` does not provide full access to `HttpContext` in all ASP.NET APIs. The `GetHttpContext` extension method provides full access to the `HttpContext` representing the underlying HTTP/2 message in ASP.NET APIs: +`ServerCallContext` doesn't provide full access to `HttpContext` in all ASP.NET APIs. The `GetHttpContext` extension method provides full access to the `HttpContext` representing the underlying HTTP/2 message in ASP.NET APIs: [!code-csharp[](~/grpc/aspnetcore/sample/GrcpService/GreeterService2.cs?highlight=6-7&name=snippet)] diff --git a/aspnetcore/grpc/migration.md b/aspnetcore/grpc/migration.md index 13607e2b6944..b038058f2cf7 100644 --- a/aspnetcore/grpc/migration.md +++ b/aspnetcore/grpc/migration.md @@ -73,7 +73,13 @@ public class GreeterService : Greeter.GreeterBase ## HTTPS +::: moniker range=">= aspnetcore-5.0" +C-core-based apps configure HTTPS through the [Server.Ports property](https://grpc.io/grpc/csharp/api/Grpc.Core.Server.html#Grpc_Core_Server_Ports). A similar concept is used to configure servers in ASP.NET Core. For example, Kestrel uses [endpoint configuration](xref:fundamentals/servers/kestrel/endpoints) for this functionality. +::: moniker-end + +::: moniker range="< aspnetcore-5.0" C-core-based apps configure HTTPS through the [Server.Ports property](https://grpc.io/grpc/csharp/api/Grpc.Core.Server.html#Grpc_Core_Server_Ports). A similar concept is used to configure servers in ASP.NET Core. For example, Kestrel uses [endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration) for this functionality. +::: moniker-end ## gRPC Interceptors vs Middleware diff --git a/aspnetcore/grpc/security.md b/aspnetcore/grpc/security.md index 380969596431..9ccae16b7946 100644 --- a/aspnetcore/grpc/security.md +++ b/aspnetcore/grpc/security.md @@ -22,7 +22,13 @@ gRPC messages are sent and received using HTTP/2. We recommend: * [Transport Layer Security (TLS)](https://tools.ietf.org/html/rfc5246) be used to secure messages in production gRPC apps. * gRPC services should only listen and respond over secured ports. +::: moniker range=">= aspnetcore-5.0" +TLS is configured in Kestrel. For more information on configuring Kestrel endpoints, see [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel/endpoints). +::: moniker-end + +::: moniker range="< aspnetcore-5.0" TLS is configured in Kestrel. For more information on configuring Kestrel endpoints, see [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). +::: moniker-end ## Exceptions diff --git a/aspnetcore/grpc/troubleshoot.md b/aspnetcore/grpc/troubleshoot.md index 18fa77c2c4b7..cc22f6aa42fc 100644 --- a/aspnetcore/grpc/troubleshoot.md +++ b/aspnetcore/grpc/troubleshoot.md @@ -109,7 +109,13 @@ public static IHostBuilder CreateHostBuilder(string[] args) => }); ``` +::: moniker range=">= aspnetcore-5.0" +When an HTTP/2 endpoint is configured without TLS, the endpoint's [ListenOptions.Protocols](xref:fundamentals/servers/kestrel/endpoints#listenoptionsprotocols) must be set to `HttpProtocols.Http2`. `HttpProtocols.Http1AndHttp2` can't be used because TLS is required to negotiate HTTP/2. Without TLS, all connections to the endpoint default to HTTP/1.1, and gRPC calls fail. +::: moniker-end + +::: moniker range="< aspnetcore-5.0" When an HTTP/2 endpoint is configured without TLS, the endpoint's [ListenOptions.Protocols](xref:fundamentals/servers/kestrel#listenoptionsprotocols) must be set to `HttpProtocols.Http2`. `HttpProtocols.Http1AndHttp2` can't be used because TLS is required to negotiate HTTP/2. Without TLS, all connections to the endpoint default to HTTP/1.1, and gRPC calls fail. +::: moniker-end The gRPC client must also be configured to not use TLS. For more information, see [Call insecure gRPC services with .NET Core client](#call-insecure-grpc-services-with-net-core-client). diff --git a/aspnetcore/host-and-deploy/index.md b/aspnetcore/host-and-deploy/index.md index c53daec4f061..9521c01e48fc 100644 --- a/aspnetcore/host-and-deploy/index.md +++ b/aspnetcore/host-and-deploy/index.md @@ -57,7 +57,17 @@ An ASP.NET Core app is a console app that must be started when a server boots an If the app uses the [Kestrel](xref:fundamentals/servers/kestrel) server, [Nginx](xref:host-and-deploy/linux-nginx), [Apache](xref:host-and-deploy/linux-apache), or [IIS](xref:host-and-deploy/iis/index) can be used as a reverse proxy server. A reverse proxy server receives HTTP requests from the Internet and forwards them to Kestrel. +::: moniker-end + +::: moniker range=">= aspnetcore-5.0" +Either configuration—with or without a reverse proxy server—is a supported hosting configuration. For more information, see [When to use Kestrel with a reverse proxy](xref:fundamentals/servers/kestrel/when-to-use-a-reverse-proxy). +::: moniker-end + +::: moniker range=">= aspnetcore-2.2 < aspnetcore-5.0" Either configuration—with or without a reverse proxy server—is a supported hosting configuration. For more information, see [When to use Kestrel with a reverse proxy](xref:fundamentals/servers/kestrel#when-to-use-kestrel-with-a-reverse-proxy). +::: moniker-end + +::: moniker range=">= aspnetcore-2.2" ## Proxy server and load balancer scenarios diff --git a/aspnetcore/host-and-deploy/linux-apache.md b/aspnetcore/host-and-deploy/linux-apache.md index 3a54b1a95a2e..141fcab06dbc 100644 --- a/aspnetcore/host-and-deploy/linux-apache.md +++ b/aspnetcore/host-and-deploy/linux-apache.md @@ -53,7 +53,7 @@ Copy the ASP.NET Core app to the server using a tool that integrates into the or A reverse proxy is a common setup for serving dynamic web apps. The reverse proxy terminates the HTTP request and forwards it to the ASP.NET app. -A proxy server is one which forwards client requests to another server instead of fulfilling requests itself. A reverse proxy forwards to a fixed destination, typically on behalf of arbitrary clients. In this guide, Apache is configured as the reverse proxy running on the same server that Kestrel is serving the ASP.NET Core app. +A proxy server forwards client requests to another server instead of fulfilling requests itself. A reverse proxy forwards to a fixed destination, typically on behalf of arbitrary clients. In this guide, Apache is configured as the reverse proxy running on the same server that Kestrel is serving the ASP.NET Core app. Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [Microsoft.AspNetCore.HttpOverrides](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides/) package. The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. @@ -61,7 +61,7 @@ Any component that depends on the scheme, such as authentication, link generatio [!INCLUDE[](~/includes/ForwardedHeaders.md)] -Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: +Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: ```csharp // using Microsoft.AspNetCore.HttpOverrides; @@ -76,7 +76,7 @@ app.UseAuthentication(); If no are specified to the middleware, the default headers to forward are `None`. -Proxies running on loopback addresses (127.0.0.0/8, [::1]), including the standard localhost address (127.0.0.1), are trusted by default. If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of or with . The following example adds a trusted proxy server at IP address 10.0.0.100 to the Forwarded Headers Middleware `KnownProxies` in `Startup.ConfigureServices`: +Proxies running on loopback addresses (`127.0.0.0/8, [::1]`), including the standard localhost address (127.0.0.1), are trusted by default. If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of or with . The following example adds a trusted proxy server at IP address 10.0.0.100 to the Forwarded Headers Middleware `KnownProxies` in `Startup.ConfigureServices`: ```csharp // using System.Net; @@ -146,10 +146,20 @@ Create a configuration file, named *helloapp.conf*, for the app: ``` -The `VirtualHost` block can appear multiple times, in one or more files on a server. In the preceding configuration file, Apache accepts public traffic on port 80. The domain `www.example.com` is being served, and the `*.example.com` alias resolves to the same website. See [Name-based virtual host support](https://httpd.apache.org/docs/current/vhosts/name-based.html) for more information. Requests are proxied at the root to port 5000 of the server at 127.0.0.1. For bi-directional communication, `ProxyPass` and `ProxyPassReverse` are required. To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). +::: moniker range=">= aspnetcore-5.0" + +The `VirtualHost` block can appear multiple times, in one or more files on a server. In the preceding configuration file, Apache accepts public traffic on port 80. The domain `www.example.com` is being served, and the `*.example.com` alias resolves to the same website. For more information, see [Name-based virtual host support](https://httpd.apache.org/docs/current/vhosts/name-based.html). Requests are proxied at the root to port 5000 of the server at 127.0.0.1. For bi-directional communication, `ProxyPass` and `ProxyPassReverse` are required. To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel/endpoints). + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" + +The `VirtualHost` block can appear multiple times, in one or more files on a server. In the preceding configuration file, Apache accepts public traffic on port 80. The domain `www.example.com` is being served, and the `*.example.com` alias resolves to the same website. For more information, see [Name-based virtual host support](https://httpd.apache.org/docs/current/vhosts/name-based.html). Requests are proxied at the root to port 5000 of the server at 127.0.0.1. For bi-directional communication, `ProxyPass` and `ProxyPassReverse` are required. To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). + +::: moniker-end > [!WARNING] -> Failure to specify a proper [ServerName directive](https://httpd.apache.org/docs/current/mod/core.html#servername) in the **VirtualHost** block exposes your app to security vulnerabilities. Subdomain wildcard binding (for example, `*.example.com`) doesn't pose this security risk if you control the entire parent domain (as opposed to `*.com`, which is vulnerable). See [rfc7230 section-5.4](https://tools.ietf.org/html/rfc7230#section-5.4) for more information. +> Failure to specify a proper [ServerName directive](https://httpd.apache.org/docs/current/mod/core.html#servername) in the **VirtualHost** block exposes your app to security vulnerabilities. Subdomain wildcard binding (for example, `*.example.com`) doesn't pose this security risk if you control the entire parent domain (as opposed to `*.com`, which is vulnerable). For more information, see [rfc7230 section-5.4](https://tools.ietf.org/html/rfc7230#section-5.4). Logging can be configured per `VirtualHost` using `ErrorLog` and `CustomLog` directives. `ErrorLog` is the location where the server logs errors, and `CustomLog` sets the filename and format of log file. In this case, this is where request information is logged. There's one line for each request. @@ -168,7 +178,7 @@ sudo systemctl enable httpd ## Monitor the app -Apache is now setup to forward requests made to `http://localhost:80` to the ASP.NET Core app running on Kestrel at `http://127.0.0.1:5000`. However, Apache isn't set up to manage the Kestrel process. Use *systemd* and create a service file to start and monitor the underlying web app. *systemd* is an init system that provides many powerful features for starting, stopping, and managing processes. +Apache is now set up to forward requests made to `http://localhost:80` to the ASP.NET Core app running on Kestrel at `http://127.0.0.1:5000`. However, Apache isn't set up to manage the Kestrel process. Use *systemd* and create a service file to start and monitor the underlying web app. *systemd* is an init system that provides many powerful features for starting, stopping, and managing processes. ### Create the service file @@ -219,6 +229,7 @@ systemd-escape "" Colon (`:`) separators aren't supported in environment variable names. Use a double underscore (`__`) in place of a colon. The [Environment Variables configuration provider](xref:fundamentals/configuration/index#environment-variables-configuration-provider) converts double-underscores into colons when environment variables are read into configuration. In the following example, the connection string key `ConnectionStrings:DefaultConnection` is set into the service definition file as `ConnectionStrings__DefaultConnection`: ::: moniker-end + ::: moniker range="< aspnetcore-3.0" Colon (`:`) separators aren't supported in environment variable names. Use a double underscore (`__`) in place of a colon. The [Environment Variables configuration provider](xref:fundamentals/configuration/index#environment-variables) converts double-underscores into colons when environment variables are read into configuration. In the following example, the connection string key `ConnectionStrings:DefaultConnection` is set into the service definition file as `ConnectionStrings__DefaultConnection`: @@ -299,7 +310,7 @@ To configure data protection to persist and encrypt the key ring, see: sudo yum install firewalld -y ``` -Use `firewalld` to open only the ports needed for the app. In this case, port 80 and 443 are used. The following commands permanently set ports 80 and 443 to open: +Use `firewalld` to open only the ports needed for the app. In this case, ports 80 and 443 are used. The following commands permanently set ports 80 and 443 to open: ```bash sudo firewall-cmd --add-port=80/tcp --permanent @@ -333,9 +344,20 @@ The [dotnet run](/dotnet/core/tools/dotnet-run) command uses the app's *Properti Configure the app to use a certificate in development for the `dotnet run` command or development environment (F5 or Ctrl+F5 in Visual Studio Code) using one of the following approaches: +::: moniker range=">= aspnetcore-5.0" + +* [Replace the default certificate from configuration](xref:fundamentals/servers/kestrel/endpoints#configuration) (*Recommended*) +* [KestrelServerOptions.ConfigureHttpsDefaults](xref:fundamentals/servers/kestrel/endpoints#configurehttpsdefaultsactionhttpsconnectionadapteroptions) + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" + * [Replace the default certificate from configuration](xref:fundamentals/servers/kestrel#configuration) (*Recommended*) * [KestrelServerOptions.ConfigureHttpsDefaults](xref:fundamentals/servers/kestrel#configurehttpsdefaultsactionhttpsconnectionadapteroptions) +::: moniker-end + **Configure the reverse proxy for secure (HTTPS) client connections** To configure Apache for HTTPS, the *mod_ssl* module is used. When the *httpd* module was installed, the *mod_ssl* module was also installed. If it wasn't installed, use `yum` to add it to the configuration. @@ -400,7 +422,7 @@ After upgrading the shared framework on the server, restart the ASP.NET Core app ### Additional headers -In order to secure against malicious attacks, there are a few headers that should either be modified or added. Ensure that the `mod_headers` module is installed: +To secure against malicious attacks, there are a few headers that should either be modified or added. Ensure that the `mod_headers` module is installed: ```bash sudo yum install mod_headers @@ -436,7 +458,7 @@ Add the line `Header set X-Content-Type-Options "nosniff"`. Save the file. Resta ### Load Balancing -This example shows how to setup and configure Apache on CentOS 7 and Kestrel on the same instance machine. In order to not have a single point of failure; using *mod_proxy_balancer* and modifying the **VirtualHost** would allow for managing multiple instances of the web apps behind the Apache proxy server. +This example shows how to setup and configure Apache on CentOS 7 and Kestrel on the same instance machine. To not have a single point of failure; using *mod_proxy_balancer* and modifying the **VirtualHost** would allow for managing multiple instances of the web apps behind the Apache proxy server. ```bash sudo yum install mod_proxy_balancer diff --git a/aspnetcore/host-and-deploy/linux-nginx.md b/aspnetcore/host-and-deploy/linux-nginx.md index 94d1a9cf5ea6..c9e4bd4f6237 100644 --- a/aspnetcore/host-and-deploy/linux-nginx.md +++ b/aspnetcore/host-and-deploy/linux-nginx.md @@ -1,7 +1,7 @@ --- title: Host ASP.NET Core on Linux with Nginx author: rick-anderson -description: Learn how to setup Nginx as a reverse proxy on Ubuntu 16.04 to forward HTTP traffic to an ASP.NET Core web app running on Kestrel. +description: Learn how to set up Nginx as a reverse proxy on Ubuntu 16.04 to forward HTTP traffic to an ASP.NET Core web app running on Kestrel. monikerRange: '>= aspnetcore-2.1' ms.author: riande ms.custom: mvc @@ -80,7 +80,7 @@ Because requests are forwarded by reverse proxy, use the [Forwarded Headers Midd [!INCLUDE[](~/includes/ForwardedHeaders.md)] -Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: +Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: ```csharp using Microsoft.AspNetCore.HttpOverrides; @@ -97,7 +97,7 @@ app.UseAuthentication(); If no are specified to the middleware, the default headers to forward are `None`. -Proxies running on loopback addresses (`127.0.0.0/8`, `[::1]`), including the standard localhost address (`127.0.0.1`), are trusted by default. If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of or with . The following example adds a trusted proxy server at IP address 10.0.0.100 to the Forwarded Headers Middleware `KnownProxies` in `Startup.ConfigureServices`: +Proxies running on loopback addresses (`127.0.0.0/8`, `[::1]`), including the standard localhost address (`127.0.0.1`), are trusted by default. If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of or with . The following example adds a trusted proxy server at IP address 10.0.0.100 to the Forwarded Headers Middleware `KnownProxies` in `Startup.ConfigureServices`: ```csharp using System.Net; @@ -129,7 +129,7 @@ Verify a browser displays the default landing page for Nginx. The landing page i ### Configure Nginx -To configure Nginx as a reverse proxy to forward HTTP requests to your ASP.NET Core app, modify `/etc/nginx/sites-available/default`. Open it in a text editor, and replace the contents with the following: +To configure Nginx as a reverse proxy to forward HTTP requests to your ASP.NET Core app, modify `/etc/nginx/sites-available/default`. Open it in a text editor, and replace the contents with the following snippet: ```nginx server { @@ -148,9 +148,9 @@ server { } ``` -If the app is a SignalR or Blazor Server app see and respectively for more information. +If the app is a SignalR or Blazor Server app, see and respectively for more information. -When no `server_name` matches, Nginx uses the default server. If no default server is defined, the first server in the configuration file is the default server. As a best practice, add a specific default server which returns a status code of 444 in your configuration file. A default server configuration example is: +When no `server_name` matches, Nginx uses the default server. If no default server is defined, the first server in the configuration file is the default server. As a best practice, add a specific default server that returns a status code of 444 in your configuration file. A default server configuration example is: ```nginx server { @@ -160,10 +160,20 @@ server { } ``` -With the preceding configuration file and default server, Nginx accepts public traffic on port 80 with host header `example.com` or `*.example.com`. Requests not matching these hosts won't get forwarded to Kestrel. Nginx forwards the matching requests to Kestrel at `http://localhost:5000`. See [How nginx processes a request](https://nginx.org/docs/http/request_processing.html) for more information. To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). +::: moniker range=">= aspnetcore-5.0" + +With the preceding configuration file and default server, Nginx accepts public traffic on port 80 with host header `example.com` or `*.example.com`. Requests not matching these hosts won't get forwarded to Kestrel. Nginx forwards the matching requests to Kestrel at `http://localhost:5000`. For more information, see [How nginx processes a request](https://nginx.org/docs/http/request_processing.html). To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel/endpoints). + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" + +With the preceding configuration file and default server, Nginx accepts public traffic on port 80 with host header `example.com` or `*.example.com`. Requests not matching these hosts won't get forwarded to Kestrel. Nginx forwards the matching requests to Kestrel at `http://localhost:5000`. For more information, see [How nginx processes a request](https://nginx.org/docs/http/request_processing.html). To change Kestrel's IP/port, see [Kestrel: Endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration). + +::: moniker-end > [!WARNING] -> Failure to specify a proper [server_name directive](https://nginx.org/docs/http/server_names.html) exposes your app to security vulnerabilities. Subdomain wildcard binding (for example, `*.example.com`) doesn't pose this security risk if you control the entire parent domain (as opposed to `*.com`, which is vulnerable). See [rfc7230 section-5.4](https://tools.ietf.org/html/rfc7230#section-5.4) for more information. +> Failure to specify a proper [server_name directive](https://nginx.org/docs/http/server_names.html) exposes your app to security vulnerabilities. Subdomain wildcard binding (for example, `*.example.com`) doesn't pose this security risk if you control the entire parent domain (as opposed to `*.com`, which is vulnerable). For more information, see [rfc7230 section-5.4](https://tools.ietf.org/html/rfc7230#section-5.4). Once the Nginx configuration is established, run `sudo nginx -t` to verify the syntax of the configuration files. If the configuration file test is successful, force Nginx to pick up the changes by running `sudo nginx -s reload`. @@ -172,13 +182,13 @@ To directly run the app on the server: 1. Navigate to the app's directory. 1. Run the app: `dotnet `, where `app_assembly.dll` is the assembly file name of the app. -If the app runs on the server but fails to respond over the Internet, check the server's firewall and confirm that port 80 is open. If using an Azure Ubuntu VM, add a Network Security Group (NSG) rule that enables inbound port 80 traffic. There's no need to enable an outbound port 80 rule, as the outbound traffic is automatically granted when the inbound rule is enabled. +If the app runs on the server but fails to respond over the Internet, check the server's firewall and confirm port 80 is open. If using an Azure Ubuntu VM, add a Network Security Group (NSG) rule that enables inbound port 80 traffic. There's no need to enable an outbound port 80 rule, as the outbound traffic is automatically granted when the inbound rule is enabled. -When done testing the app, shut the app down with `Ctrl+C` at the command prompt. +When done testing the app, shut down the app with Ctrl + C at the command prompt. ## Monitor the app -The server is setup to forward requests made to `http://:80` on to the ASP.NET Core app running on Kestrel at `http://127.0.0.1:5000`. However, Nginx isn't set up to manage the Kestrel process. `systemd` can be used to create a service file to start and monitor the underlying web app. `systemd` is an init system that provides many powerful features for starting, stopping, and managing processes. +The server is set up to forward requests made to `http://:80` on to the ASP.NET Core app running on Kestrel at `http://127.0.0.1:5000`. However, Nginx isn't set up to manage the Kestrel process. `systemd` can be used to create a service file to start and monitor the underlying web app. `systemd` is an init system that provides many powerful features for starting, stopping, and managing processes. ### Create the service file @@ -188,7 +198,7 @@ Create the service definition file: sudo nano /etc/systemd/system/kestrel-helloapp.service ``` -The following is an example service file for the app: +The following example is a service file for the app: ```ini [Unit] @@ -281,7 +291,7 @@ Since the web app using Kestrel is managed using `systemd`, all events and proce sudo journalctl -fu kestrel-helloapp.service ``` -For further filtering, time options such as `--since today`, `--until 1 hour ago` or a combination of these can reduce the amount of entries returned. +For further filtering, time options such as `--since today`, `--until 1 hour ago`, or a combination of these can reduce the number of entries returned. ```bash sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00" @@ -318,11 +328,11 @@ Proxy server default settings typically limit request header fields to 4 K or 8 ### Enable AppArmor -Linux Security Modules (LSM) is a framework that's part of the Linux kernel since Linux 2.6. LSM supports different implementations of security modules. [AppArmor](https://wiki.ubuntu.com/AppArmor) is a LSM that implements a Mandatory Access Control system which allows confining the program to a limited set of resources. Ensure AppArmor is enabled and properly configured. +Linux Security Modules (LSM) is a framework that's part of the Linux kernel since Linux 2.6. LSM supports different implementations of security modules. [AppArmor](https://wiki.ubuntu.com/AppArmor) is an LSM that implements a Mandatory Access Control system, which allows confining the program to a limited set of resources. Ensure AppArmor is enabled and properly configured. ### Configure the firewall -Close off all external ports that are not in use. Uncomplicated firewall (ufw) provides a front end for `iptables` by providing a CLI for configuring the firewall. +Close off all external ports that aren't in use. Uncomplicated firewall (ufw) provides a front end for `iptables` by providing a CLI for configuring the firewall. > [!WARNING] > A firewall will prevent access to the whole system if not configured correctly. Failure to specify the correct SSH port will effectively lock you out of the system if you are using SSH to connect to it. The default port is 22. For more information, see the [introduction to ufw](https://help.ubuntu.com/community/UFW) and the [manual](https://manpages.ubuntu.com/manpages/bionic/man8/ufw.8.html). @@ -358,18 +368,29 @@ Configure the server with additional required modules. Consider using a web app **Configure the app for secure (HTTPS) local connections** -The [dotnet run](/dotnet/core/tools/dotnet-run) command uses the app's `Properties/launchSettings.json` file, which configures the app to listen on the URLs provided by the `applicationUrl` property (for example, `https://localhost:5001;http://localhost:5000`). +The [dotnet run](/dotnet/core/tools/dotnet-run) command uses the app's *Properties/launchSettings.json* file, which configures the app to listen on the URLs provided by the `applicationUrl` property. For example, `https://localhost:5001;http://localhost:5000`. Configure the app to use a certificate in development for the `dotnet run` command or development environment (F5 or Ctrl+F5 in Visual Studio Code) using one of the following approaches: +::: moniker range=">= aspnetcore-5.0" + +* [Replace the default certificate from configuration](xref:fundamentals/servers/kestrel/endpoints#configuration) (*Recommended*) +* [KestrelServerOptions.ConfigureHttpsDefaults](xref:fundamentals/servers/kestrel/endpoints#configurehttpsdefaultsactionhttpsconnectionadapteroptions) + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" + * [Replace the default certificate from configuration](xref:fundamentals/servers/kestrel#configuration) (*Recommended*) * [KestrelServerOptions.ConfigureHttpsDefaults](xref:fundamentals/servers/kestrel#configurehttpsdefaultsactionhttpsconnectionadapteroptions) +::: moniker-end + **Configure the reverse proxy for secure (HTTPS) client connections** -* Configure the server to listen to HTTPS traffic on port `443` by specifying a valid certificate issued by a trusted Certificate Authority (CA). +* Configure the server to listen to HTTPS traffic on port 443 by specifying a valid certificate issued by a trusted Certificate Authority (CA). -* Harden the security by employing some of the practices depicted in the following `/etc/nginx/nginx.conf` file. Examples include choosing a stronger cipher and redirecting all traffic over HTTP to HTTPS. +* Harden the security by employing some of the practices depicted in the following */etc/nginx/nginx.conf* file. Examples include choosing a stronger cipher and redirecting all traffic over HTTP to HTTPS. > [!NOTE] > For development environments, we recommend using temporary redirects (302) rather than permanent redirects (301). Link caching can cause unstable behavior in development environments. @@ -383,11 +404,11 @@ Configure the app to use a certificate in development for the `dotnet run` comma * Don't add the HSTS header. * Choose a short `max-age` value. -Add the `/etc/nginx/proxy.conf` configuration file: +Add the */etc/nginx/proxy.conf* configuration file: [!code-nginx[](linux-nginx/proxy.conf)] -**Replace** the contents of the `/etc/nginx/nginx.conf` configuration file with the following file. The example contains both `http` and `server` sections in one configuration file. +**Replace** the contents of the */etc/nginx/nginx.conf* configuration file with the following file. The example contains both `http` and `server` sections in one configuration file. [!code-nginx[](linux-nginx/nginx.conf?highlight=2)] @@ -400,7 +421,7 @@ Add the `/etc/nginx/proxy.conf` configuration file: To mitigate clickjacking attacks: -1. Edit the `nginx.conf` file: +1. Edit the *nginx.conf* file: ```bash sudo nano /etc/nginx/nginx.conf @@ -415,7 +436,7 @@ To mitigate clickjacking attacks: This header prevents most browsers from MIME-sniffing a response away from the declared content type, as the header instructs the browser not to override the response content type. With the `nosniff` option, if the server says the content is `text/html`, the browser renders it as `text/html`. -1. Edit the `nginx.conf` file: +1. Edit the *nginx.conf* file: ```bash sudo nano /etc/nginx/nginx.conf diff --git a/aspnetcore/host-and-deploy/windows-service.md b/aspnetcore/host-and-deploy/windows-service.md index a686057c187d..1eb155f72aa4 100644 --- a/aspnetcore/host-and-deploy/windows-service.md +++ b/aspnetcore/host-and-deploy/windows-service.md @@ -219,7 +219,22 @@ By default, ASP.NET Core binds to `http://localhost:5000`. Configure the URL and For additional URL and port configuration approaches, see the relevant server article: +::: moniker-end + +::: moniker range=">= aspnetcore-5.0" + +* + +::: moniker-end + +::: moniker range="< aspnetcore-5.0 >= aspnetcore-3.0" + * + +::: moniker-end + +::: moniker range=">= aspnetcore-3.0" + * The preceding guidance covers support for HTTPS endpoints. For example, configure the app for HTTPS when authentication is used with a Windows Service. @@ -229,25 +244,25 @@ The preceding guidance covers support for HTTPS endpoints. For example, configur ## Current directory and content root -The current working directory returned by calling for a Windows Service is the *C:\\WINDOWS\\system32* folder. The *system32* folder isn't a suitable location to store a service's files (for example, settings files). Use one of the following approaches to maintain and access a service's assets and settings files. +The current working directory returned by calling for a Windows Service is the *C:\\WINDOWS\\system32* folder. The *system32* folder isn't a suitable location to store a service's files (for example, settings files). Use one of the following approaches to maintain and access a service's assets and settings files. ### Use ContentRootPath or ContentRootFileProvider Use [IHostEnvironment.ContentRootPath](xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath) or to locate an app's resources. -When the app runs as a service, sets the to [AppContext.BaseDirectory](xref:System.AppContext.BaseDirectory). +When the app runs as a service, sets the to [AppContext.BaseDirectory](xref:System.AppContext.BaseDirectory). The app's default settings files, *appsettings.json* and *appsettings.{Environment}.json*, are loaded from the app's content root by calling [CreateDefaultBuilder during host construction](xref:fundamentals/host/generic-host#set-up-a-host). -For other settings files loaded by developer code in , there's no need to call . In the following example, the *custom_settings.json* file exists in the app's content root and is loaded without explicitly setting a base path: +For other settings files loaded by developer code in , there's no need to call . In the following example, the *custom_settings.json* file exists in the app's content root and is loaded without explicitly setting a base path: [!code-csharp[](windows-service/samples_snapshot/CustomSettingsExample.cs?highlight=13)] -Don't attempt to use to obtain a resource path because a Windows Service app returns the *C:\\WINDOWS\\system32* folder as its current directory. +Don't attempt to use to obtain a resource path because a Windows Service app returns the *C:\\WINDOWS\\system32* folder as its current directory. ### Store a service's files in a suitable location on disk -Specify an absolute path with when using an to the folder containing the files. +Specify an absolute path with when using an to the folder containing the files. ## Troubleshoot @@ -328,7 +343,16 @@ A dump can be analyzed using several approaches. For more information, see [Anal ## Additional resources +::: moniker-end + +::: moniker range=">= aspnetcore-5.0" +* [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel/endpoints) (includes HTTPS configuration and SNI support) +::: moniker-end +::: moniker range="< aspnetcore-5.0 >= aspnetcore-3.0" * [Kestrel endpoint configuration](xref:fundamentals/servers/kestrel#endpoint-configuration) (includes HTTPS configuration and SNI support) +::: moniker-end + +::: moniker range=">= aspnetcore-3.0" * * diff --git a/aspnetcore/mvc/models/file-uploads.md b/aspnetcore/mvc/models/file-uploads.md index 4aef6d4c11af..05b48a0a54da 100644 --- a/aspnetcore/mvc/models/file-uploads.md +++ b/aspnetcore/mvc/models/file-uploads.md @@ -634,7 +634,7 @@ public class BufferedSingleFileUploadPhysicalModel : PageModel ### Kestrel maximum request body size -For apps hosted by Kestrel, the default maximum request body size is 30,000,000 bytes, which is approximately 28.6 MB. Customize the limit using the [MaxRequestBodySize](xref:fundamentals/servers/kestrel#maximum-request-body-size) Kestrel server option: +For apps hosted by Kestrel, the default maximum request body size is 30,000,000 bytes, which is approximately 28.6 MB. Customize the limit using the [MaxRequestBodySize](xref:fundamentals/servers/kestrel/options#maximum-request-body-size) Kestrel server option: ```csharp public static IHostBuilder CreateHostBuilder(string[] args) => @@ -650,7 +650,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) => }); ``` - is used to set the [MaxRequestBodySize](xref:fundamentals/servers/kestrel#maximum-request-body-size) for a single page or action. + is used to set the [MaxRequestBodySize](xref:fundamentals/servers/kestrel/options#maximum-request-body-size) for a single page or action. In a Razor Pages app, apply the filter with a [convention](xref:razor-pages/razor-pages-conventions) in `Startup.ConfigureServices`: @@ -689,8 +689,8 @@ The `RequestSizeLimitAttribute` can also be applied using the [`@attribute`](xre Other Kestrel limits may apply for apps hosted by Kestrel: -* [Maximum client connections](xref:fundamentals/servers/kestrel#maximum-client-connections) -* [Request and response data rates](xref:fundamentals/servers/kestrel#minimum-request-body-data-rate) +* [Maximum client connections](xref:fundamentals/servers/kestrel/options#maximum-client-connections) +* [Request and response data rates](xref:fundamentals/servers/kestrel/options#minimum-request-body-data-rate) ### IIS @@ -2205,7 +2205,13 @@ The examples in this topic rely upon to hold the u ## Additional resources +::: moniker range="< aspnetcore-5.0" * [HTTP connection request draining](xref:fundamentals/servers/kestrel#http11-request-draining) +::: moniker-end +::: moniker range=">= aspnetcore-5.0" +* [HTTP connection request draining](xref:fundamentals/servers/kestrel/request-draining) +::: moniker-end + * [Unrestricted File Upload](https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload) * [Azure Security: Security Frame: Input Validation | Mitigations](/azure/security/azure-security-threat-modeling-tool-input-validation) * [Azure Cloud Design Patterns: Valet Key pattern](/azure/architecture/patterns/valet-key) diff --git a/aspnetcore/release-notes/aspnetcore-5.0.md b/aspnetcore/release-notes/aspnetcore-5.0.md index 2262b9fbf1f3..e0535ff8acf2 100644 --- a/aspnetcore/release-notes/aspnetcore-5.0.md +++ b/aspnetcore/release-notes/aspnetcore-5.0.md @@ -316,7 +316,7 @@ Server Name Indication (SNI) is a TLS extension to include a virtual domain as a ### HTTP/2 * Significant reductions in allocations in the HTTP/2 code path. -* Support for [HPack dynamic compression](https://tools.ietf.org/html/rfc7541) of HTTP/2 response headers in [Kestrel](xref:fundamentals/servers/kestrel). For more information, see [Header table size](xref:fundamentals/servers/kestrel#header-table-size) and [HPACK: the silent killer (feature) of HTTP/2](https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/). +* Support for [HPack dynamic compression](https://tools.ietf.org/html/rfc7541) of HTTP/2 response headers in [Kestrel](xref:fundamentals/servers/kestrel). For more information, see [Header table size](xref:fundamentals/servers/kestrel/options#header-table-size) and [HPACK: the silent killer (feature) of HTTP/2](https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/). * Sending HTTP/2 PING frames: HTTP/2 has a mechanism for sending PING frames to ensure an idle connection is still functional. Ensuring a viable connection is especially useful when working with long-lived streams that are often idle but only intermittently see activity, for example, gRPC streams. Apps can send periodic PING frames in [Kestrel](xref:fundamentals/servers/kestrel) by setting limits on : diff --git a/aspnetcore/security/authentication/certauth.md b/aspnetcore/security/authentication/certauth.md index e11f8d4b34a3..70789de2cb45 100644 --- a/aspnetcore/security/authentication/certauth.md +++ b/aspnetcore/security/authentication/certauth.md @@ -136,37 +136,37 @@ The handler has two events: * Determining if the certificate is known to your services. * Constructing your own principal. Consider the following example in `Startup.ConfigureServices`: -```csharp -services.AddAuthentication( - CertificateAuthenticationDefaults.AuthenticationScheme) - .AddCertificate(options => - { - options.Events = new CertificateAuthenticationEvents + ```csharp + services.AddAuthentication( + CertificateAuthenticationDefaults.AuthenticationScheme) + .AddCertificate(options => { - OnCertificateValidated = context => + options.Events = new CertificateAuthenticationEvents { - var claims = new[] + OnCertificateValidated = context => { - new Claim( - ClaimTypes.NameIdentifier, - context.ClientCertificate.Subject, - ClaimValueTypes.String, - context.Options.ClaimsIssuer), - new Claim(ClaimTypes.Name, - context.ClientCertificate.Subject, - ClaimValueTypes.String, - context.Options.ClaimsIssuer) - }; - - context.Principal = new ClaimsPrincipal( - new ClaimsIdentity(claims, context.Scheme.Name)); - context.Success(); - - return Task.CompletedTask; - } - }; - }); -``` + var claims = new[] + { + new Claim( + ClaimTypes.NameIdentifier, + context.ClientCertificate.Subject, + ClaimValueTypes.String, + context.Options.ClaimsIssuer), + new Claim(ClaimTypes.Name, + context.ClientCertificate.Subject, + ClaimValueTypes.String, + context.Options.ClaimsIssuer) + }; + + context.Principal = new ClaimsPrincipal( + new ClaimsIdentity(claims, context.Scheme.Name)); + context.Success(); + + return Task.CompletedTask; + } + }; + }); + ``` If you find the inbound certificate doesn't meet your extra validation, call `context.Fail("failure reason")` with a failure reason. @@ -285,7 +285,7 @@ public void ConfigureServices(IServiceCollection services) options.HeaderConverter = (headerValue) => { X509Certificate2 clientCertificate = null; - + if(!string.IsNullOrWhiteSpace(headerValue)) { byte[] bytes = StringToByteArray(headerValue); @@ -622,6 +622,24 @@ ASP.NET Core 5 preview 7 and later adds more convenient support for optional cli The following approach supports optional client certificates: +::: moniker range=">= aspnetcore-5.0" + +* Set up binding for the domain and subdomain: + * For example, set up bindings on `contoso.com` and `myClient.contoso.com`. The `contoso.com` host doesn't require a client certificate but `myClient.contoso.com` does. + * For more information, see: + * [Kestrel](/fundamentals/servers/kestrel): + * [ListenOptions.UseHttps](xref:fundamentals/servers/kestrel/endpoints#listenoptionsusehttps) + * + * Note Kestrel does not currently support multiple TLS configurations on one binding, you'll need two bindings with unique IPs or ports. See https://github.com/dotnet/runtime/issues/31097 + * IIS + * [Hosting IIS](xref:host-and-deploy/iis/index#create-the-iis-site) + * [Configure security on IIS](/iis/manage/configuring-security/how-to-set-up-ssl-on-iis#configure-ssl-settings-2) + * Http.Sys: [Configure Windows Server](xref:fundamentals/servers/httpsys#configure-windows-server) + +::: moniker-end + +::: moniker range="< aspnetcore-5.0" + * Set up binding for the domain and subdomain: * For example, set up bindings on `contoso.com` and `myClient.contoso.com`. The `contoso.com` host doesn't require a client certificate but `myClient.contoso.com` does. * For more information, see: @@ -633,6 +651,9 @@ The following approach supports optional client certificates: * [Hosting IIS](xref:host-and-deploy/iis/index#create-the-iis-site) * [Configure security on IIS](/iis/manage/configuring-security/how-to-set-up-ssl-on-iis#configure-ssl-settings-2) * Http.Sys: [Configure Windows Server](xref:fundamentals/servers/httpsys#configure-windows-server) + +::: moniker-end + * For requests to the web app that require a client certificate and don't have one: * Redirect to the same page using the client certificate protected subdomain. * For example, redirect to `myClient.contoso.com/requestedPage`. Because the request to `myClient.contoso.com/requestedPage` is a different hostname than `contoso.com/requestedPage`, the client establishes a different connection and the client certificate is provided. diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index ba51dc26e767..3baeaea4b473 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -972,8 +972,29 @@ displayName: deploy, publish uid: host-and-deploy/iis/protocols - name: Kestrel - uid: fundamentals/servers/kestrel displayName: deploy, publish, server + items: + - name: Overview + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel + - name: Endpoints + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/endpoints + - name: Options + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/options + - name: HTTP/2 + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/http2 + - name: When to use a reverse proxy + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/when-to-use-a-reverse-proxy + - name: Host filtering + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/host-filtering + - name: Request draining + displayName: deploy, publish, server + uid: fundamentals/servers/kestrel/request-draining - name: HTTP.sys displayName: deploy, publish, server uid: fundamentals/servers/httpsys