Servidor web Kestrel en ASP.NET Core

Por Tom Dykstra, Chris Ross y Stephen Halter

Kestrel es un servidor web Kestrel. Kestrel es el servidor recomendado para ASP.NET Core y se configura de forma predeterminada en las plantillas de proyecto de ASP.NET Core.

Las características de Kestrel incluyen:

  • Multiplataforma:Kestrel es un servidor web multiplataforma que se ejecuta en Windows, Linux y macOS.
  • Alto rendimiento:Kestrel está optimizado para controlar un gran número de conexiones simultáneas de forma eficaz.
  • Ligero: está optimizado para ejecutarse en entornos con restricción de recursos, como contenedores y dispositivos perimetrales.
  • Seguridad protegidaKestrel: admite HTTPS y está protegido frente a vulnerabilidades del servidor web.
  • Amplia compatibilidad con protocolos:Kestrel admite protocolos web comunes, entre los que se incluyen:
  • Integración con ASP.NET Core: integración perfecta con otros componentes de ASP.NET Core, como canalización de middleware, inserción de dependencias y sistema de configuración.
  • Cargas de trabajo flexibles: Kestrel admite muchas cargas de trabajo:
    • Marcos de aplicaciones ASP.NET, como API mínimas, MVC, páginas Razor, SignalR, Blazor y gRPC.
    • Creación de un proxy inverso con YARP.
  • Extensibilidad: personalice Kestrel a través de la configuración, el middleware y los transportes personalizados.
  • Diagnósticos de rendimiento:Kestrel proporciona características de diagnóstico de rendimiento integradas, como el registro y las métricas.

Introducción

Las plantillas de proyecto de ASP.NET Core usan Kestrel de forma predeterminada cuando no se hospedan con IIS. En la siguiente plantilla generada Program.cs, el método WebApplication.CreateBuilder llama internamente a UseKestrel:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Para más información sobre cómo configurar WebApplication y WebApplicationBuilder, consulte Referencia rápida de las API mínimas.

Certificados de cliente opcionales

Para obtener información sobre las aplicaciones que deben proteger un subconjunto de la aplicación con un certificado, vea Certificados de cliente opcionales.

Comportamiento con el depurador asociado

Los siguientes tiempos de espera y límites de velocidad no se aplican cuando hay un depurador asociado a un proceso Kestrel:

Recursos adicionales

Nota

Desde ASP.NET Core 5.0, el transporte de libuv de Kestrel está obsoleto. El transporte de libuv no recibe actualizaciones para admitir nuevas plataformas de sistema operativo, como Windows ARM64, y se eliminará en una versión futura. Quite todas las llamadas al método obsoleto UseLibuv y, en su lugar, use el transporte de sockets predeterminado de Kestrel.

Kestrel es un servidor web Kestrel. Kestrel es el servidor web que se incluye y habilita de forma predeterminada en las plantillas de proyecto de ASP.NET Core.

Kestrel admite las siguientes situaciones:

  • HTTPS
  • HTTP/2 (excepto en macOS†)
  • Actualización opaca para habilitar WebSockets
  • Sockets de Unix para alto rendimiento detrás de Nginx

†HTTP/2 se admitirá en macOS en una versión futura.

Kestrel admite todas las plataformas y versiones que sean compatibles con .NET Core.

Introducción

Las plantillas de proyecto de ASP.NET Core usan Kestrel de forma predeterminada cuando no se hospedan con IIS. En la siguiente plantilla generada Program.cs, el método WebApplication.CreateBuilder llama internamente a UseKestrel:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Para más información sobre cómo configurar WebApplication y WebApplicationBuilder, consulte Referencia rápida de las API mínimas.

Certificados de cliente opcionales

Para obtener información sobre las aplicaciones que deben proteger un subconjunto de la aplicación con un certificado, vea Certificados de cliente opcionales.

Comportamiento con el depurador asociado

Los siguientes tiempos de espera y límites de velocidad no se aplican cuando hay un depurador asociado a un proceso Kestrel:

Recursos adicionales

Nota

Desde ASP.NET Core 5.0, el transporte de libuv de Kestrel está obsoleto. El transporte de libuv no recibe actualizaciones para admitir nuevas plataformas de sistema operativo, como Windows ARM64, y se eliminará en una versión futura. Quite todas las llamadas al método obsoleto UseLibuv y, en su lugar, use el transporte de sockets predeterminado de Kestrel.

Kestrel es un servidor web Kestrel. Kestrel es el servidor web que se incluye y habilita de forma predeterminada en las plantillas de proyecto de ASP.NET Core.

Kestrel admite las siguientes situaciones:

  • HTTPS
  • HTTP/2 (excepto en macOS†)
  • Actualización opaca para habilitar WebSockets
  • Sockets de Unix para alto rendimiento detrás de Nginx

†HTTP/2 se admitirá en macOS en una versión futura.

Kestrel admite todas las plataformas y versiones que sean compatibles con .NET Core.

Vea o descargue el código de ejemplo (cómo descargarlo)

Introducción

Las plantillas de proyecto de ASP.NET Core usan Kestrel de forma predeterminada cuando no se hospedan con IIS. En Program.cs, el método ConfigureWebHostDefaults llama a UseKestrel:

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

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

Para más información sobre la creación del host, consulte las secciones Configuración de un host y Configuración predeterminada del compilador de Host genérico de .NET en ASP.NET Core.

Certificados de cliente opcionales

Para obtener información sobre las aplicaciones que deben proteger un subconjunto de la aplicación con un certificado, vea Certificados de cliente opcionales.

Recursos adicionales

Nota

Desde ASP.NET Core 5.0, el transporte de libuv de Kestrel está obsoleto. El transporte de libuv no recibe actualizaciones para admitir nuevas plataformas de sistema operativo, como Windows ARM64, y se eliminará en una versión futura. Quite todas las llamadas al método obsoleto UseLibuv y, en su lugar, use el transporte de sockets predeterminado de Kestrel.

Kestrel es un servidor web Kestrel. Kestrel es el servidor web que se incluye de forma predeterminada en las plantillas de proyecto de ASP.NET Core.

Kestrel admite las siguientes situaciones:

  • HTTPS
  • Actualización opaca para habilitar WebSockets
  • Sockets de Unix para alto rendimiento detrás de Nginx
  • HTTP/2 (excepto en macOS†)

†HTTP/2 se admitirá en macOS en una versión futura.

Kestrel admite todas las plataformas y versiones que sean compatibles con .NET Core.

Vea o descargue el código de ejemplo (cómo descargarlo)

Compatibilidad con HTTP/2

HTTP/2 está disponible para las aplicaciones de ASP.NET Core si se cumplen los siguientes requisitos básicos:

  • Sistema operativo †
    • Windows Server 2016 o Windows 10 o posterior‡
    • Linux con OpenSSL 1.0.2 o posterior (por ejemplo, Ubuntu 16.04 o posterior)
  • Plataforma de destino: .NET Core 2.2 o posterior
  • Conexión con Application-Layer Protocol Negotiation (ALPN)
  • Conexión con TLS 1.2 o una versión posterior

†HTTP/2 se admitirá en macOS en una versión futura. ‡Kestrel tiene compatibilidad limitada con HTTP/2 en Windows Server 2012 R2 y Windows 8.1. La compatibilidad es limitada porque la lista de conjuntos de cifrado TLS admitidos y disponibles en estos sistemas operativos está limitada. Se puede requerir un certificado generado mediante Elliptic Curve Digital Signature Algorithm (ECDSA) para proteger las conexiones TLS.

Si se establece una conexión HTTP/2, HttpRequest.Protocol notifica HTTP/2.

A partir de .NET Core 3.0, HTTP/2 está habilitado de forma predeterminada. Para obtener más información sobre la configuración, consulte las secciones Opciones de Kestrel y ListenOptions.Protocols.

Casos en los que se puede usar Kestrel con un proxy inverso

Kestrel puede usarse por sí solo o con un servidor proxy inverso. Un servidor proxy inverso recibe las solicitudes HTTP de la red y las reenvía a Kestrel. Entre los ejemplos de un servidor proxy inverso, se incluyen los siguientes:

Kestrel empleado como servidor web perimetral (accesible desde Internet):

Kestrel communicates directly with the Internet without a reverse proxy server

Kestrel empleado en una configuración de proxy inverso:

Kestrel communicates indirectly with the Internet through a reverse proxy server, such as IIS, Nginx, or Apache

Cualquiera de las configuraciones, con o sin servidor proxy inverso, es una configuración de hospedaje admitida.

Kestrel, utilizado como un servidor perimetral sin un servidor proxy inverso, no permite compartir la misma dirección IP y el mismo puerto entre varios procesos. Si Kestrel se configura para escuchar en un puerto, Kestrel controla todo el tráfico de ese puerto, independientemente de los encabezados Host de las solicitudes. Un proxy inverso que puede compartir puertos es capaz de reenviar solicitudes a Kestrel en una única dirección IP y puerto.

Aunque no sea necesario un servidor proxy inverso, su uso puede ser útil.

Un proxy inverso puede hacer lo siguiente:

  • Limitar el área expuesta públicamente de las aplicaciones que hospeda.
  • Proporcionar una capa extra de configuración y defensa.
  • Posiblemente, integrarse mejor con la infraestructura existente.
  • Simplificar el equilibrio de carga y la configuración de una comunicación segura (HTTPS). Solamente el servidor proxy inverso necesita un certificado X.509 y dicho servidor se puede comunicar con los servidores de la aplicación en la red interna por medio de HTTP sin formato.

Advertencia

El hospedaje en una configuración de proxy inverso requiere la configuración del Middleware de encabezados reenviados.

Kestrel en aplicaciones ASP.NET Core

Las plantillas de proyecto de ASP.NET Core usan Kestrel de forma predeterminada. En Program.cs, el método ConfigureWebHostDefaults llama a UseKestrel:

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

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

Para más información sobre la creación del host, consulte las secciones Configuración de un host y Configuración predeterminada del compilador de Host genérico de .NET en ASP.NET Core.

Para proporcionar configuración adicional después de llamar a ConfigureWebHostDefaults, use ConfigureKestrel:

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

Opciones de Kestrel

El servidor web Kestrel tiene opciones de configuración de restricción que son especialmente útiles en las implementaciones con conexión a Internet.

Establezca restricciones en la propiedad Limits de la clase KestrelServerOptions. La propiedad Limits contiene una instancia de la clase KestrelServerLimits.

En los ejemplos siguientes se usa el espacio de nombres Microsoft.AspNetCore.Server.Kestrel.Core:

using Microsoft.AspNetCore.Server.Kestrel.Core;

En los ejemplos que se muestran más adelante en este artículo, las opciones de Kestrel se configuran en código de C#. Las opciones de Kestrel también se pueden establecer mediante un Kestrel. Por ejemplo, el proveedor de configuración de archivo puede cargar la configuración de Kestrel desde un archivo appsettings.json o appsettings.{Environment}.json:

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

Nota:

KestrelServerOptions y la KestrelServerOptions se pueden establecer a partir de proveedores de configuración. El resto de la configuración de Kestrel debe establecerse en código de C#.

Siga uno de estos procedimientos:

  • Configure Kestrel en Startup.ConfigureServices:

    1. Inserte una instancia de IConfiguration en la clase Startup. En el ejemplo siguiente se da por supuesto que la configuración insertada está asignada a la propiedad Configuration.

    2. En Startup.ConfigureServices, cargue la sección de configuración Kestrel en la configuración de Kestrel:

      using Microsoft.Extensions.Configuration
      
      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          public IConfiguration Configuration { get; }
      
          public void ConfigureServices(IServiceCollection services)
          {
              services.Configure<KestrelServerOptions>(
                  Configuration.GetSection("Kestrel"));
          }
      
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              ...
          }
      }
      
  • Configure Kestrel al compilar el host:

    En Program.cs, cargue la sección de configuración Kestrel en la configuración de Kestrel:

    // using Microsoft.Extensions.DependencyInjection;
    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.Configure<KestrelServerOptions>(
                    context.Configuration.GetSection("Kestrel"));
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    

Los dos procedimientos anteriores funcionan con cualquier proveedor de configuración.

Tiempo de expiración de la conexión persistente

KeepAliveTimeout

Obtiene o establece el tiempo de expiración de la conexión persistente. El valor predeterminado es de 2 minutos.

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

Las conexiones máximas de cliente

MaxConcurrentConnections MaxConcurrentUpgradedConnections

El número máximo de conexiones de TCP abiertas simultáneas que se pueden establecer para toda la aplicación con este código:

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

Hay un límite independiente para las conexiones que se han actualizado desde HTTP o HTTPS a otro protocolo (por ejemplo, en una solicitud de WebSockets). Cuando se actualiza una conexión, no se cuenta con respecto al límite de MaxConcurrentConnections.

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

El número máximo de conexiones es ilimitado de forma predeterminada (null).

El tamaño máximo del cuerpo de solicitud

MaxRequestBodySize

El tamaño máximo predeterminado del cuerpo de solicitud es 30 000 000 bytes, que son aproximadamente 28,6 MB.

El método recomendado para invalidar el límite de una aplicación ASP.NET Core MVC es usar el atributo RequestSizeLimitAttribute en un método de acción:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Este es un ejemplo que muestra cómo configurar la restricción en la aplicación y todas las solicitudes:

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

Invalide la configuración en una solicitud específica de middleware:

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

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

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

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

Se inicia una excepción si la aplicación configura el límite de una solicitud después de que la aplicación haya empezado a leer la solicitud. Hay una propiedad IsReadOnly que señala si la propiedad MaxRequestBodySize tiene el estado de solo lectura, lo que significa que es demasiado tarde para configurar el límite.

Cuando se ejecuta una aplicación fuera de proceso detrás del módulo de ASP.NET Core, el límite de tamaño del cuerpo de la solicitud de Kestrel se deshabilita porque IIS ya establece el límite.

La velocidad mínima de los datos del cuerpo de solicitud.

MinRequestBodyDataRate MinResponseDataRate

Kestrel comprueba cada segundo si los datos entran a la velocidad especificada en bytes por segundo. Si la velocidad está por debajo del mínimo, se agota el tiempo de espera de la conexión. El período de gracia es la cantidad de tiempo que Kestrel da al cliente para aumentar su velocidad de envío hasta el mínimo; no se comprueba la velocidad durante ese tiempo. Este período de gracia permite evitar que se interrumpan las conexiones que inicialmente están enviando datos a una velocidad lenta debido a un inicio lento de TCP.

La velocidad mínima predeterminada es 240 bytes por segundo, con un período de gracia de cinco segundos.

También se aplica una velocidad mínima a la respuesta. El código para establecer el límite de solicitudes y el límite de respuestas es el mismo, salvo que tienen RequestBody o Response en los nombres de propiedad y de interfaz.

Este es un ejemplo que muestra cómo configurar las velocidades de datos mínimas en Program.cs:

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

Invalide los límites de velocidad mínima por solicitud en el middleware:

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

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

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

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

La característica IHttpMinResponseDataRateFeature a la que se hace referencia en el ejemplo anterior no está presente en HttpContext.Features para las solicitudes HTTP/2, porque generalmente no se permite modificar los límites de velocidad por solicitud debido a la compatibilidad del protocolo con la multiplexación de solicitudes. Sin embargo, IHttpMinRequestBodyDataRateFeature sigue estando presente en HttpContext.Features para las solicitudes HTTP/2, ya que el límite de velocidad de lectura aún puede estar completamente deshabilitado por solicitud estableciendo IHttpMinRequestBodyDataRateFeature.MinDataRate en null incluso para una solicitud HTTP/2. Si se intenta leer IHttpMinRequestBodyDataRateFeature.MinDataRate o se intenta su establecimiento en un valor distinto de null, se obtendrá una excepción NotSupportedException con una solicitud HTTP/2 dada.

Se siguen aplicando límites de velocidad en todo el servidor configurados con KestrelServerOptions.Limits a las conexiones HTTP/1.x y HTTP/2.

Tiempo de expiración de los encabezados de solicitud

RequestHeadersTimeout

Obtiene o establece la cantidad máxima de tiempo que el servidor pasa recibiendo las cabeceras de las solicitudes. El valor predeterminado es 30 segundos.

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

Secuencias máximas por conexión

Http2.MaxStreamsPerConnection limita el número de secuencias de solicitudes simultáneas por conexión HTTP/2. Se rechazarán las secuencias en exceso.

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

El valor predeterminado es 100.

Tamaño de la tabla de encabezado

El descodificador HPACK descomprime los encabezados HTTP para las conexiones HTTP/2. Http2.HeaderTableSize limita el tamaño de la tabla de compresión de encabezado que usa el descodificador HPACK. El valor se proporciona en octetos y debe ser mayor que cero (0).

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

El valor predeterminado es 4096.

Tamaño máximo de marco

Http2.MaxFrameSize indica el tamaño máximo permitido de una carga de marco de conexión HTTP/2 recibida o enviada por el servidor. El valor se proporciona en octetos y debe estar comprendido entre 2^14 (16 384) y 2^24-1 (16 777 215).

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

El valor predeterminado es 2^14 (16 384).

Tamaño máximo del encabezado de solicitud

Http2.MaxRequestHeaderFieldSize indica el tamaño máximo permitido (en octetos) de los valores de los encabezados de solicitud. Este límite se aplica al nombre y al valor en sus representaciones comprimidas y no comprimidas. El valor debe ser mayor que cero (0).

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

El valor predeterminado es 8192.

Tamaño inicial de la ventana de conexión

Http2.InitialConnectionWindowSize indica la cantidad máxima de datos del cuerpo de solicitud (en bytes) que el servidor almacena en búfer a la vez de forma agregada en todas las solicitudes (transmisiones) por conexión. Las solicitudes también están limitadas por Http2.InitialStreamWindowSize. El valor debe ser igual o mayor que 65 535 y menor que 2^31 (2 147 483 648).

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

El valor predeterminado es 128 KB (131 072).

Tamaño inicial de la ventana de transmisión

Http2.InitialStreamWindowSize indica la cantidad máxima de datos del cuerpo de solicitud (en bytes) que el servidor almacena en búfer a la vez por solicitud (transmisión). Las solicitudes también están limitadas por Http2.InitialConnectionWindowSize. El valor debe ser igual o mayor que 65 535 y menor que 2^31 (2 147 483 648).

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

El valor predeterminado es 96 KB (98 304).

Clips finales

Los finalizadores HTTP son similares a los encabezados HTTP, salvo que se envían después de enviar el cuerpo de la respuesta. Para IIS y HTTP.sys, solo se admiten los finalizadores de respuesta HTTP/2.

if (httpContext.Response.SupportsTrailers())
{
    httpContext.Response.DeclareTrailer("trailername");	

    // Write body
    httpContext.Response.WriteAsync("Hello world");

    httpContext.Response.AppendTrailer("trailername", "TrailerValue");
}

En el código de ejemplo anterior:

  • SupportsTrailers garantiza que los finalizadores se admitan para la respuesta.
  • DeclareTrailer agrega el nombre del finalizador dado al encabezado de respuesta Trailer. Declarar los finalizadores de una respuesta es opcional, pero se recomienda. Si se llama a DeclareTrailer, debe ser antes de que se envíen los encabezados de respuesta.
  • AppendTrailer anexa el finalizador.

Reset

Un restablecimiento permite que el servidor restablezca una solicitud HTTP/2 con un código de error especificado. Una solicitud de restablecimiento se considera una anulación.

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

En el ejemplo de código anterior, Reset especifica el código de error de INTERNAL_ERROR. Para obtener más información sobre los códigos de error HTTP/2, visite la sección de código de error de especificación de HTTP/2.

E/S síncrona

AllowSynchronousIO controla si se permite la E/S sincrónica para la solicitud y la respuesta. El valor predeterminado es false.

Advertencia

Un gran número de operaciones de E/S sincrónicas de bloqueo puede dar lugar al colapso del grupo de subprocesos, lo que hace que la aplicación no responda. Habilite solo AllowSynchronousIO al usar una biblioteca que no admite la E/S asincrónica.

En el ejemplo siguiente se habilita la E/S sincrónica:

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

Para más información sobre otras opciones y límites de Kestrel, vea:

Configuración de punto de conexión

ASP.NET Core enlaza de forma predeterminada a:

  • http://localhost:5000
  • https://localhost:5001 (cuando hay presente un certificado de desarrollo local)

Especifique direcciones URL mediante los siguientes elementos:

  • La variable de entorno ASPNETCORE_URLS.
  • El argumento de la línea de comandos --urls.
  • La clave de configuración de host urls.
  • El método de extensión UseUrls.

El valor que estos métodos suministran puede ser uno o más puntos de conexión HTTP y HTTPS (este último, si hay disponible un certificado predeterminado). Configure el valor como una lista separada por punto y coma (por ejemplo, "Urls": "http://localhost:8000;http://localhost:8001").

Para más información sobre estos enfoques, consulte Direcciones URL del servidor e Invalidar la configuración.

Un certificado de desarrollo se crea:

Algunos exploradores necesitan que se conceda permiso explícito para confiar en el certificado de desarrollo local.

Las plantillas de proyecto configuran aplicaciones para que se ejecuten en HTTPS de forma predeterminada e incluyen redirección de HTTPS y compatibilidad con HSTS.

Llame a los métodos Listen o ListenUnixSocket de KestrelServerOptions para configurar los puertos y los prefijos de dirección URL para Kestrel.

UseUrls, el argumento de línea de comandos --urls, la clave de configuración de host urls y la variable de entorno ASPNETCORE_URLS también funcionan, pero tienen las limitaciones que se indican más adelante en esta sección (debe haber disponible un certificado predeterminado para la configuración de puntos de conexión HTTPS).

Configuración de KestrelServerOptions:

ConfigureEndpointDefaults(Action<ListenOptions>)

Especifica una Action de configuración para que se ejecute con cada punto de conexión especificado. Al llamar a ConfigureEndpointDefaults varias veces, se reemplazan las Action anteriores por la última Action especificada.

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

Nota

Los puntos de conexión que se crean mediante una llamada a ListenListen de llamar a ConfigureEndpointDefaults no tendrán aplicados los valores predeterminados.

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

Especifica una Action de configuración para que se ejecute con cada punto de conexión HTTPS. Al llamar a ConfigureHttpsDefaults varias veces, se reemplazan las Action anteriores por la última Action especificada.

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

Nota

Los puntos de conexión que se crean mediante una llamada a Listenantes de llamar a ConfigureHttpsDefaults no tendrán aplicados los valores predeterminados.

Configure(IConfiguration)

Crea un cargador de configuración para configurar Kestrel que toma IConfiguration como entrada. El ámbito de la configuración debe corresponderse con la sección de configuración de Kestrel.

ListenOptions.UseHttps

Configure Kestrel para que use HTTPS.

Extensiones de ListenOptions.UseHttps:

  • UseHttps: configure Kestrel para que use HTTPS con el certificado predeterminado. Produce una excepción si no hay ningún certificado predeterminado configurado.
  • UseHttps(string fileName)
  • UseHttps(string fileName, string password)
  • UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(StoreName storeName, string subject)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(X509Certificate2 serverCertificate)
  • UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)

Parámetros de ListenOptions.UseHttps:

  • filename es la ruta de acceso y el nombre de archivo de un archivo de certificado correspondiente al directorio donde están los archivos de contenido de la aplicación.
  • password es la contraseña necesaria para obtener acceso a los datos del certificado X.509.
  • configureOptions es una Action para configurar HttpsConnectionAdapterOptions. Devuelve ListenOptions.
  • storeName es el almacén de certificados desde el que se carga el certificado.
  • subject es el nombre del sujeto del certificado.
  • allowInvalid indica si se deben tener en cuenta los certificados no válidos, como los certificados autofirmados.
  • location es la ubicación del almacén desde el que se carga el certificado.
  • serverCertificate es el certificado X.509.

En un entorno de producción, HTTPS se debe configurar explícitamente. Como mínimo, debe existir un certificado predeterminado.

Estas son las configuraciones compatibles:

  • Sin configuración
  • Reemplazar el certificado predeterminado de configuración
  • Cambiar los valores predeterminados en el código

Sin configuración

Kestrel escucha en http://localhost:5000 y en https://localhost:5001 (si hay disponible un certificado predeterminado).

Reemplazar el certificado predeterminado de configuración

CreateDefaultBuilder llama a Configure(context.Configuration.GetSection("Kestrel")) de forma predeterminada para cargar la configuración de Kestrel. Hay disponible un esquema de configuración de aplicación HTTPS predeterminado para Kestrel. Configure varios puntos de conexión (incluidas las direcciones URL y los certificados que va a usar) desde un archivo en disco o desde un almacén de certificados.

En el ejemplo appsettings.json siguiente:

  • Establezca AllowInvalid en true para permitir el uso de certificados no válidos (por ejemplo, certificados autofirmados).
  • Cualquier punto de conexión HTTPS que no especifique un certificado (HttpsDefaultCert en el siguiente ejemplo) revierte al certificado definido en Certificados>Predeterminado o al certificado de desarrollo.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5003"
      },
      "Https": {
        "Url": "https://*:5004",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "<certificate password>"
      }
    }
  }
}

Una alternativa al uso de Path y Password en cualquier nodo de certificado consiste en especificar el certificado por medio de campos del almacén de certificados. Por ejemplo, el certificado en Certificados>Predeterminado se puede especificar así:

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

Notas sobre el esquema:

  • En los nombres de los puntos de conexión se distingue entre mayúsculas y minúsculas. Por ejemplo, HTTPS y Https son válidos.
  • El parámetro Url es necesario en cada punto de conexión. El formato de este parámetro es el mismo que el del parámetro de configuración Urls de nivel superior, excepto por el hecho de que está limitado a un único valor.
  • En vez de agregarse, estos puntos de conexión reemplazan a los que están definidos en la configuración Urls de nivel superior. Los puntos de conexión definidos en el código a través de Listen son acumulativos con respecto a los puntos de conexión definidos en la sección de configuración.
  • La sección Certificate es opcional. Si la sección Certificate no se especifica, se usan los valores predeterminados definidos en escenarios anteriores. Si no hay valores predeterminados disponibles, el servidor produce una excepción y no se inicia.
  • La sección Certificate admite tanto certificados CertificatePassword como SubjectStore.
  • Se puede definir el número de puntos de conexión que se quiera de esta manera, siempre y cuando no produzcan conflictos de puerto.
  • options.Configure(context.Configuration.GetSection("{SECTION}")) devuelve un KestrelConfigurationLoader con un método .Endpoint(string name, listenOptions => { }) que se puede usar para complementar la configuración de un punto de conexión configurado:
webBuilder.UseKestrel((context, serverOptions) =>
{
    serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
        .Endpoint("HTTPS", listenOptions =>
        {
            listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
        });
});

Se puede acceder directamente a KestrelServerOptions.ConfigurationLoader para seguir con la iteración en el cargador existente, como el proporcionado por CreateDefaultBuilder.

  • La sección de configuración de cada punto de conexión está disponible en las opciones del método Endpoint para que se pueda leer la configuración personalizada.
  • Se pueden cargar varias configuraciones volviendo a llamar a options.Configure(context.Configuration.GetSection("{SECTION}")) con otra sección. Se usa la última configuración, a menos que se llame explícitamente a Load en instancias anteriores. El metapaquete no llama a Load, con lo cual su sección de configuración predeterminada se puede reemplazar.
  • KestrelConfigurationLoader refleja la familia Listen de API de KestrelServerOptions como sobrecargas de Endpoint, por lo que los puntos de conexión de configuración y código se pueden configurar en el mismo lugar. En estas sobrecargas no se usan nombres y solo consumen valores predeterminados de la configuración.

Cambiar los valores predeterminados en el código

ConfigureEndpointDefaults y ConfigureHttpsDefaults se pueden usar para cambiar la configuración predeterminada de ListenOptions y HttpsConnectionAdapterOptions, incluido sustituir el certificado predeterminado especificado en el escenario anterior. Se debe llamar a ConfigureEndpointDefaults y a ConfigureHttpsDefaults antes de que se configure algún punto de conexión.

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

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

Compatibilidad de Kestrel con SNI

Indicación de nombre de servidor (SNI) se puede usar para hospedar varios dominios en la misma dirección IP y puerto. Para que SNI funcione, el cliente envía el nombre de host de la sesión segura al servidor durante el protocolo de enlace TLS para que, de este modo, el servidor pueda proporcionar el certificado correcto. El cliente usa el certificado proporcionado para la comunicación cifrada con el servidor durante la sesión segura que sigue al protocolo de enlace TLS.

Kestrel admite SNI a través de la devolución de llamada ServerCertificateSelector. La devolución de llamada se invoca una vez por conexión para permitir que la aplicación inspeccione el nombre de host y seleccione el certificado adecuado.

La compatibilidad con SNI requiere lo siguiente:

  • Ejecutarse en el marco de destino netcoreapp2.1 o posterior. En net461 o posterior, se invoca la devolución de llamada, pero name siempre es null. name también será null si el cliente no proporciona el parámetro de nombre de host en el protocolo de enlace TLS.
  • Todos los sitios web deben ejecutarse en la misma instancia de Kestrel. Kestrel no admite el uso compartido de una dirección IP y un puerto entre varias instancias sin un proxy inverso.
webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenAnyIP(5005, listenOptions =>
    {
        listenOptions.UseHttps(httpsOptions =>
        {
            var localhostCert = CertificateLoader.LoadFromStoreCert(
                "localhost", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var exampleCert = CertificateLoader.LoadFromStoreCert(
                "example.com", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var subExampleCert = CertificateLoader.LoadFromStoreCert(
                "sub.example.com", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var certs = new Dictionary<string, X509Certificate2>(
                StringComparer.OrdinalIgnoreCase);
            certs["localhost"] = localhostCert;
            certs["example.com"] = exampleCert;
            certs["sub.example.com"] = subExampleCert;

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

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

Registro de conexiones

Llame a UseConnectionLogging para emitir registros de nivel de depuración para la comunicación a nivel de bytes en una conexión. El registro de conexiones es útil para solucionar problemas en la comunicación de bajo nivel, como durante el cifrado TLS y detrás de los servidores proxy. Si UseConnectionLogging se coloca antes de UseHttps, se registra el tráfico cifrado. Si UseConnectionLogging se coloca después de UseHttps, se registra el tráfico descifrado.

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

Enlazar a un socket TCP

El método Listen se enlaza a un socket TCP y una expresión lambda de opciones permite configurar un certificado X.509:

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

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

En el ejemplo se configura HTTPS para un punto de conexión con ListenOptions. Use la misma API para configurar otras opciones de Kestrel para puntos de conexión específicos.

En Windows, pueden crearse certificados autofirmados con el New-SelfSignedCertificatecmdlet de PowerShell. Para ver un ejemplo no admitido, consulte UpdateIISExpressSSLForChrome.ps1.

En macOS, Linux y Windows, pueden crearse certificados con OpenSSL.

Enlazar a un socket de Unix

Escuche en un socket de Unix con ListenUnixSocket para mejorar el rendimiento con Nginx, tal como se muestra en este ejemplo:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testpassword");
        });
})
  • En el archivo de configuración de Nginx, establezca la entrada server>location>proxy_pass en http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} es el nombre del socket proporcionado para ListenUnixSocket (por ejemplo, kestrel-test.sock en el ejemplo anterior).
  • Asegúrese de que el socket es grabable por Nginx (por ejemplo, chmod go+w /tmp/kestrel-test.sock).

Puerto 0

Cuando se especifica el número de puerto 0, Kestrel se enlaza de forma dinámica a un puerto disponible. En el siguiente ejemplo se muestra cómo averiguar qué puerto Kestrel está realmente enlazado a un entorno de ejecución:

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

    app.UseStaticFiles();

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

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

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

Cuando la aplicación se ejecuta, la salida de la ventana de consola indica el puerto dinámico en el que se puede tener acceso a la aplicación:

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

Limitaciones

Configure puntos de conexión con los siguientes métodos:

  • UseUrls
  • El argumento de la línea de comandos --urls
  • La clave de configuración de host urls
  • La variable de entorno ASPNETCORE_URLS

Estos métodos son útiles para que el código funcione con servidores que no sean de Kestrel. Sin embargo, tenga en cuenta las siguientes limitaciones:

  • HTTPS no se puede usar con estos métodos, a menos que se proporcione un certificado predeterminado en la configuración del punto de conexión HTTPS (por ejemplo, por medio de la configuración KestrelServerOptions o de un archivo de configuración, tal y como se explicó anteriormente en este tema).
  • Cuando los métodos Listen y UseUrls se usan al mismo tiempo, los puntos de conexión de Listen sustituyen a los de UseUrls.

Configuración de puntos de conexión IIS

Cuando se usa IIS, los enlaces de direcciones URL de IIS reemplazan a los enlaces que se hayan establecido por medio de Listen o de UseUrls. Para más información, vea el tema Módulo ASP.NET Core.

ListenOptions.Protocols

La propiedad Protocols establece los protocolos HTTP (HttpProtocols) habilitados en un punto de conexión o para el servidor. Asigne un valor a la propiedad Protocols desde el valor de enumeración HttpProtocols.

Valor de enumeración HttpProtocols Protocolo de conexión permitido
Http1 HTTP/1.1 solo. Puede usarse con o sin TLS.
Http2 HTTP/2 solo. Se pueden utilizar sin TLS solo si el cliente admite un modo de conocimientos previos.
Http1AndHttp2 HTTP/1.1 y HTTP/2. HTTP/2 necesita que el cliente seleccione HTTP/2 en el protocolo de enlace Negociación de protocolo de nivel de aplicación (ALPN) de TLS; en caso contrario, el valor predeterminado de la conexión es HTTP/1.1.

El valor ListenOptions.Protocols predeterminado de cualquier punto de conexión es HttpProtocols.Http1AndHttp2.

Restricciones de TLS para HTTP/2:

  • TLS 1.2 o versiones posteriores
  • Renegociación deshabilitada
  • Compresión deshabilitada
  • Tamaños de intercambio de claves efímeras mínimos:
    • Curva elíptica Diffie-Hellman (ECDHE) [RFC4492]: 224 bits como mínimo
    • Campo finito Diffie-Hellman (DHE) (DHE) [TLS12]: 2048 bits como mínimo
  • Conjunto de cifrado no prohibido.

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] con la curva elíptica P-256 [FIPS186] se admite de forma predeterminada.

El siguiente ejemplo permite conexiones HTTP/1.1 y HTTP/2 en el puerto 8000. Las conexiones se protegen mediante TLS con un certificado proporcionado:

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

Si es necesario, use el middleware de conexión para filtrar los protocolos de enlace TLS por conexión en el caso de cifrados específicos:

En el ejemplo siguiente se produce una excepción NotSupportedException con cualquier algoritmo de cifrado que no admita la aplicación. Como alternativa, defina y compare ITlsHandshakeFeature.CipherAlgorithm con una lista de conjuntos de cifrado aceptables.

No se usa ningún cifrado con un algoritmo de cifrado CipherAlgorithmType.Null .

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

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

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

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

                return next();
            });
        }
    }
}

El filtrado de conexiones también puede configurarse mediante una función lambda IConnectionBuilder:

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

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

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

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

En Linux, se puede usar CipherSuitesPolicy para filtrar los protocolos de enlace TLS por conexión:

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

Defina el protocolo a partir de la configuración

CreateDefaultBuilder llama a serverOptions.Configure(context.Configuration.GetSection("Kestrel")) de forma predeterminada para cargar la configuración de Kestrel.

En el siguiente ejemplo de appsettings.json , se establece HTTP/1.1 como el protocolo de conexión predeterminado para todos los puntos de conexión:

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

En el siguiente ejemplo de appsettings.json se establece el protocolo de conexión HTTP/1.1 para un punto de conexión específico:

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

Los protocolos especificados en el código invalidan los valores establecidos por la configuración.

Prefijos de URL

Al usar UseUrls, el argumento de línea de comandos --urls, la clave de configuración de host urls o una variable de entorno ASPNETCORE_URLS, los prefijos de dirección URL pueden tener cualquiera de estos formatos.

Solo son válidos los prefijos de dirección URL HTTP. Kestrel no admite HTTPS al configurar enlaces de dirección URL con UseUrls.

  • Dirección IPv4 con número de puerto

    http://65.55.39.10:80/
    

    0.0.0.0 es un caso especial que enlaza a todas las direcciones IPv4.

  • Dirección IPv6 con número de puerto

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

    [::] es el equivalente en IPv6 de 0.0.0.0 en IPv4.

  • Nombre de host con número de puerto

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

    Los nombres de host, * y + no son especiales. Todo lo que no se identifique como una dirección IP o un localhost válido se enlaza a todas las direcciones IP de IPv6 e IPv4. Para enlazar distintos nombres de host a distintas aplicaciones ASP.NET Core en el mismo puerto, use HTTP.sys o un servidor proxy inverso, como IIS, Nginx o Apache.

    Advertencia

    El hospedaje en una configuración de proxy inverso requiere la configuración del Middleware de encabezados reenviados.

  • Nombre localhost del host con el número de puerto o la IP de bucle invertido con el número de puerto

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

    Cuando se especifica localhost, Kestrel intenta enlazar a las interfaces de bucle invertido de IPv4 e IPv6. Si el puerto solicitado lo está usando otro servicio en cualquier interfaz de bucle invertido, Kestrel no se puede iniciar. Si ninguna de estas interfaces de bucle invertido está disponible por cualquier otra razón (normalmente porque no se admite IPv6), Kestrel registra una advertencia.

Filtrado de hosts

Si bien Kestrel admite una configuración basada en prefijos como http://example.com:5000, Kestrel pasa por alto completamente el nombre de host. El host localhost es un caso especial que se usa para enlazar a direcciones de bucle invertido. Cualquier otro host que no sea una dirección IP explícita se enlaza a todas las direcciones IP públicas. Los encabezados Host no están validados.

Como solución alternativa, use el Middleware de filtrado de hosts. El middleware de filtrado de host lo proporciona el paquete Microsoft.AspNetCore.HostFiltering, que se proporciona implícitamente para aplicaciones ASP.NET Core. El middleware se agrega por medio de CreateDefaultBuilder, que llama a AddHostFiltering:

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

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

El Middleware de filtrado de hosts está deshabilitado de forma predeterminada. Para habilitarlo, defina una clave AllowedHosts en appsettings.json/appsettings.{Environment}.json. El valor es una lista delimitada por punto y coma de nombres de host sin los números de puerto:

appsettings.json:

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

Nota:

Middleware de encabezados reenviados también tiene una opción AllowedHosts. El Middleware de encabezados reenviados y el Middleware de filtrado de hosts tienen una funcionalidad similar en diferentes escenarios. Establecer AllowedHosts con el Middleware de encabezados reenviados es adecuado cuando el encabezado Host no se conserva mientras se reenvían solicitudes con un servidor proxy inverso o un equilibrador de carga. Establecer AllowedHosts con el Middleware de filtrado de hosts es adecuado cuando se usa Kestrel como un servidor perimetral de acceso público o cuando el encabezado Host se reenvía directamente.

Para más información sobre el Middleware de encabezados reenviados, vea Configurar ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Configuración de transporte de Libuv

Para los proyectos que necesitan el uso de Libuv (UseLibuv):

  • Agregue una dependencia para el paquete Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv al archivo del proyecto de la aplicación:

    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv"
                      Version="{VERSION}" />
    
  • Llame a UseLibuv en IWebHostBuilder:

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

Vaciado de solicitudes HTTP/1.1

La apertura de conexiones HTTP lleva mucho tiempo. En HTTPS, además consume muchos recursos. Por lo tanto, Kestrel intenta reutilizar las conexiones conforme al protocolo HTTP/1.1. El cuerpo de una solicitud debe usarse por completo para que se vuelva a usar la conexión. La aplicación no siempre consume el cuerpo de la solicitud, por ejemplo, POST solicita dónde devuelve un redireccionamiento o una respuesta 404 el servidor. En el caso de un redireccionamiento POST:

  • Es posible que el cliente ya haya enviado parte de los datos de POST.
  • El servidor escribe la respuesta 301.
  • La conexión no se puede usar para una nueva solicitud hasta que los datos de POST del cuerpo de la solicitud anterior se han leído en su totalidad.
  • Kestrel intenta vaciar el cuerpo de la solicitud. El vaciado del cuerpo de la solicitud significa leer y descartar los datos sin procesarlos.

El proceso de vaciado llega a un equilibrio entre permitir que se vuelva a usar la conexión y el tiempo que se tarda en vaciar los datos restantes:

  • El vaciado tiene un tiempo de espera de cinco segundos que no se puede configurar.
  • Si no se han leído todos los datos especificados por el encabezado Content-Length o Transfer-Encoding antes de que se agote el tiempo de espera, se cierra la conexión.

A veces, puede que quiera finalizar la solicitud inmediatamente, antes o después de escribir la respuesta. Por ejemplo, los clientes pueden tener límites de datos restrictivos, así que limitar los datos cargados podría ser una prioridad. En tales casos, para finalizar una solicitud, llame a HttpContext.Abort desde un controlador, una página de Razor o un middleware.

Hay advertencias respecto a la llamada a Abort:

  • La creación de nuevas conexiones puede ser lenta y costosa.
  • No hay ninguna garantía de que el cliente haya leído la respuesta antes de que se cierre la conexión.
  • La llamada a Abort debe ser poco frecuente y reservada para casos de error graves, no comunes.
    • Llame a Abort solo cuando sea necesario resolver un problema concreto. Por ejemplo, llame a Abort si hay clientes malintencionados intentando aplicar POST a los datos o si hay un error en el código del cliente que produce muchas solicitudes o de gran tamaño.
    • No llame a Abort para situaciones de error comunes, como HTTP 404 (No encontrado).

La llamada a HttpResponse.CompleteAsync antes de llamar a Abort garantiza que el servidor haya terminado de escribir la respuesta. Pero el comportamiento del cliente no es predecible y es posible que no lea la respuesta antes de que se anule la conexión.

Este proceso es diferente para HTTP/2, ya que el protocolo admite la anulación de flujos de solicitud individuales sin cerrar la conexión. El tiempo de espera de vaciado de cinco segundos no se aplica. Si hay datos del cuerpo de la solicitud sin leer después de completar una respuesta, el servidor envía un marco RST HTTP/2. Se omiten los marcos de datos del cuerpo de la solicitud adicionales.

Si es posible, es mejor que los clientes usen el encabezado de solicitud Expect: 100-continue y esperen a que el servidor responda para empezar a enviar el cuerpo de la solicitud. Esto proporciona al cliente la oportunidad de examinar la respuesta y anular antes de enviar datos innecesarios.

Recursos adicionales