Implementación del servidor web HTTP.sys en ASP.NET Core

Por Tom Dykstra y Chris Ross

HTTP.sys es un servidor web de ASP.NET Core que solo se ejecuta en Windows. HTTP.sys supone una alternativa al servidor Kestrel y ofrece algunas características que Kestrel no facilita.

Importante

HTTP.sys no es compatible con el módulo ASP.NET Core y no se puede usar con IIS o IIS Express.

HTTP.sys admite las siguientes características:

  • Autenticación de Windows
  • Uso compartido de puertos
  • HTTPS con SNI
  • HTTP/2 a través de TLS (Windows 10 o posterior)
  • Transmisión directa de archivos
  • Almacenamiento en caché de respuestas
  • WebSockets (Windows 8 o posterior)

Versiones de Windows compatibles:

  • Windows 7 o posterior
  • Windows Server 2008 R2 o posterior

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

Cuándo usar HTTP.sys

HTTP.sys resulta útil para implementaciones en las que:

  • Es necesario exponer el servidor directamente a Internet sin usar IIS.

    HTTP.sys communicates directly with the Internet

  • Una implementación interna requiere una característica que no está disponible en Kestrel. Para obtener más información, vea Diferencias entre Kestrel y HTTP.sys.

    HTTP.sys communicates directly with the internal network

HTTP.sys es una tecnología consolidada que protege contra muchos tipos de ataques y que proporciona la solidez, la seguridad y la escalabilidad de un servidor web con todas las características. El propio IIS se ejecuta como agente de escucha de HTTP sobre HTTP.sys.

Compatibilidad con HTTP/2

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

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

HTTP/2 está habilitado de forma predeterminada. Si no se establece una conexión HTTP/2, la conexión vuelve a HTTP/1.1. En una futura versión de Windows, las marcas de configuración de HTTP/2 estarán disponibles, incluida la capacidad para deshabilitar HTTP/2 con HTTP.sys.

Compatibilidad con HTTP/3

HTTP/3 está habilitado para las aplicaciones de ASP.NET Core cuando se cumplen los siguientes requisitos básicos:

Es posible que en las versiones de la compilación de Windows 11 anteriores se necesario usar una compilación de Windows Insider.

HTTP/3 se detecta como una actualización de HTTP/1.1 o HTTP/2 por medio del encabezado alt-svc. Esto significa que la primera solicitud normalmente usará HTTP/1.1 o HTTP/2 antes de cambiar a HTTP/3. Http.Sys no agrega automáticamente el encabezado alt-svc; debe agregarlo la aplicación. El código siguiente es un ejemplo de middleware que agrega el encabezado de respuesta alt-svc.

app.Use((context, next) =>
{
    context.Response.Headers.AltSvc = "h3=\":443\"";
    return next(context);
});

Coloque el código anterior al principio de la canalización de solicitud.

Http.Sys también admite el envío de un mensaje de protocolo HTTP/2 AltSvc en lugar de un encabezado de respuesta para notificar al cliente que HTTP/3 está disponible. Vea la clave del Registro EnableAltSvc. Para esto se necesitan enlaces sslcert de netsh que usen nombres de host en lugar de direcciones IP.

Autenticación de modo kernel con Kerberos

HTTP.sys delega en la autenticación de modo kernel con el protocolo de autenticación de Kerberos. La autenticación de modo usuario no se admite con Kerberos y HTTP.sys. Se debe usar la cuenta de equipo para descifrar el token o el vale de Kerberos que se obtiene de Active Directory y que el cliente reenvía al servidor para autenticar al usuario. Registre el nombre de entidad de seguridad de servicio (SPN) para el host, no el usuario de la aplicación.

Compatibilidad con el almacenamiento en búfer de respuesta en modo kernel

En algunos escenarios, grandes volúmenes de escrituras pequeñas con latencia alta pueden causar un impacto significativo en el rendimiento de HTTP.sys. Este impacto se debe a la falta de un búfer de Pipe en la implementación de HTTP.sys. Para mejorar el rendimiento en estos escenarios, se ha agregado a HTTP.sys compatibilidad con el almacenamiento en búfer de respuesta. Habilite el almacenamiento en búfer estableciendo HttpSysOptions.EnableKernelResponseBuffering en true.

Una aplicación que realiza E/S sincrónica debe habilitar el almacenamiento en búfer de respuesta, o una que realiza E/S asincrónica, pero sin más de una escritura pendiente a la vez. En estos escenarios, el almacenamiento en búfer de respuesta puede mejorar significativamente el rendimiento en las conexiones de alta latencia.

Las aplicaciones que usan E/S asincrónica y que pueden tener más de una escritura pendiente a la vez no deben usar esta marca. Habilitar esta marca puede dar lugar a que HTTP.Sys use más CPU y memoria.

Cómo usar HTTP.sys

Configuración de la aplicación de ASP.NET Core para usar HTTP.sys

Llame al método de extensión UseHttpSys al compilar el host y especifique las opciones HttpSysOptions necesarias. En el siguiente ejemplo se establecen las opciones en sus valores predeterminados:

using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys(options =>
{
    options.AllowSynchronousIO = false;
    options.Authentication.Schemes = AuthenticationSchemes.None;
    options.Authentication.AllowAnonymous = true;
    options.MaxConnections = null;
    options.MaxRequestBodySize = 30_000_000;
    options.UrlPrefixes.Add("http://localhost:5005");
});

builder.Services.AddRazorPages();

var app = builder.Build();

La configuración adicional de HTTP.sys se controla a través de Configuración del Registro.

Para obtener más información acerca de las opciones de HTTP.sys, consulte HttpSysOptions.

MaxRequestBodySize

Tamaño máximo permitido de cualquier cuerpo de solicitud en bytes. Cuando se establece en null, el tamaño máximo del cuerpo de solicitud es ilimitado. Este límite no tiene ningún efecto en las conexiones actualizadas, que siempre son ilimitadas.

El método recomendado para reemplazar el límite de una aplicación de ASP.NET Core MVC para un solo objeto IActionResult consiste en usar el atributo RequestSizeLimitAttribute en un método de acción:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

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

Si la aplicación debe reemplazar MaxRequestBodySize por solicitud, use IHttpMaxRequestBodySizeFeature:

app.Use((context, next) =>
{
    context.Features.GetRequiredFeature<IHttpMaxRequestBodySizeFeature>()
                                             .MaxRequestBodySize = 10 * 1024;

    var server = context.RequestServices
        .GetRequiredService<IServer>();
    var serverAddressesFeature = server.Features
                                 .GetRequiredFeature<IServerAddressesFeature>();

    var addresses = string.Join(", ", serverAddressesFeature.Addresses);

    var loggerFactory = context.RequestServices
        .GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    logger.LogInformation("Addresses: {addresses}", addresses);

    return next(context);
});

If usa Visual Studio, asegúrese de que la aplicación no está configurada para ejecutar IIS o IIS Express.

En Visual Studio, el perfil de inicio predeterminado es para IIS Express. Para ejecutar el proyecto como aplicación de consola, cambie manualmente el perfil seleccionado, tal y como se muestra en la siguiente captura de pantalla:

Select console app profile

Configurar Windows Server

  1. Determine los puertos que se van a abrir para la aplicación y use el Firewall de Windows o el cmdlet New-NetFirewallRule de PowerShell para abrir los puertos del firewall y permitir que el tráfico llegue a HTTP.sys. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  2. Cuando realice una implementación en una máquina virtual de Azure, abra los puertos del grupo de seguridad de red. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  3. Si es necesario, obtenga e instale los certificados X.509.

    En Windows, puede crear certificados autofirmados con el cmdlet New-SelfSignedCertificate de PowerShell. Para obtener un ejemplo no compatible, vea UpdateIISExpressSSLForChrome.ps1.

    Instale certificados autofirmados o firmados por CA en el almacén Máquina local>Personal del servidor.

  4. Si la aplicación es una implementación dependiente del marco, instale .NET Core, .NET Framework o ambos (si se trata de una aplicación de .NET Core que tiene como destino .NET Framework).

    • .NET Core: si la aplicación requiere .NET Core, obtenga y ejecute el instalador de .NET Core Runtime en la página de descargas de .NET Core. No instale el SDK completo en el servidor.
    • .NET Framework: si la aplicación requiere .NET Framework, consulte la guía de instalación de .NET Framework. Instale la versión necesaria de .NET Framework. El instalador de la versión más reciente de .NET Framework está disponible en la página de descargas de .NET Core.

    Si la aplicación se basa en la implementación autocontenida, incluirá el entorno de ejecución en la implementación. No se requiere la instalación de ningún marco en el servidor.

  5. Configure los puertos y las direcciones URL en la aplicación.

    ASP.NET Core se enlaza a http://localhost:5000 de forma predeterminada. Para configurar los puertos y los prefijos de dirección URL, las opciones incluyen lo siguiente:

    • UseUrls
    • El argumento de la línea de comandos urls
    • La variable de entorno ASPNETCORE_URLS
    • UrlPrefixes

    En el código siguiente, se muestra cómo usar UrlPrefixescon la dirección IP local del servidor, 10.0.0.4, en el puerto 443:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.WebHost.UseHttpSys(options =>
    {
        options.UrlPrefixes.Add("https://10.0.0.4:443");
    });
    
    builder.Services.AddRazorPages();
    
    var app = builder.Build();
    

    Una ventaja de UrlPrefixes es que se genera inmediatamente un mensaje de error para prefijos con formato incorrecto.

    La configuración de UrlPrefixes invalida la configuración de UseUrls/urls/ASPNETCORE_URLS. Por lo tanto, la ventaja de UseUrls, urls y la variable de entorno ASPNETCORE_URLS es que resulta más fácil de cambiar entre Kestrel y HTTP.sys.

    HTTP.sys reconoce dos tipos de caracteres comodín en prefijos de dirección URL:

    • * es un enlacedébil, también conocido como enlace de reserva. Si el prefijo de dirección URL es http://*:5000y algo más está enlazado al puerto 5000, este enlace no se usará.
    • + es un enlace sólido. Si el prefijo de dirección URL es http://+:5000, este enlace se usará antes de otros enlaces de puerto 5000.

    Para obtener más información, vea Cadenas de urlPrefix

    Advertencia

    Los enlaces de carácter comodín de nivel superior (http://*:80/ y http://+:80) no se deben usar. Los enlaces de carácter comodín de nivel superior generan vulnerabilidades de seguridad en la aplicación. Esto se aplica tanto a los caracteres comodín fuertes como a los débiles. Use nombres de host explícitos o direcciones IP en lugar de caracteres comodín. Los enlaces de carácter comodín de subdominio (por ejemplo, *.mysub.com) no suponen ningún riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Sección 7.2: Host y :authority.

    A menudo, las aplicaciones y los contenedores solo reciben un puerto en el que escuchar, como el puerto 80, sin restricciones adicionales como el host o la ruta de acceso. HTTP_PORTS y HTTPS_PORTS son claves de configuración que especifican los puertos de escucha para los servidores HTTP.sys y Kestrel. Estas claves se pueden especificar como variables de entorno definidas con los prefijos DOTNET_ o ASPNETCORE_, o bien se especifican directamente mediante cualquier otra entrada de configuración, como appsettings.json. Cada una es una lista de valores de puerto delimitada por punto y coma, tal como se muestra en el ejemplo siguiente:

    ASPNETCORE_HTTP_PORTS=80;8080
    ASPNETCORE_HTTPS_PORTS=443;8081
    

    El ejemplo anterior es una forma abreviada de la siguiente configuración, que especifica el esquema (HTTP o HTTPS) y cualquier host o IP.

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

    Las claves de configuración de HTTP_PORTS y HTTPS_PORTS son de menor prioridad, y las direcciones URL o los valores proporcionados directamente en el código las anulan. Los certificados todavía deben configurarse por separado mediante mecanismos específicos del servidor para HTTPS.

    Estas claves de configuración son equivalentes a los enlaces de caracteres comodín de nivel superior. Son prácticos para escenarios de desarrollo y contenedor, pero evitan caracteres comodín cuando se ejecutan en una máquina que también puede hospedar otros servicios.

  6. Registre previamente los prefijos de URL en el servidor.

    La herramienta integrada para configurar HTTP.sys es netsh.exe. netsh.exe se usa para reservar prefijos de dirección URL y asignar certificados X.509. Esta herramienta requiere privilegios de administrador.

    Use la herramienta netsh.exe para registrar URL de la aplicación:

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL>: localizador uniforme de recursos (URL) completo especificado. No use ningún enlace de carácter comodín. Use un nombre de host válido o la dirección IP local. La dirección URL debe incluir una barra diagonal final.
    • <USER>: especifica el nombre del usuario o el grupo de usuarios.

    En el ejemplo siguiente, la dirección IP local del servidor es 10.0.0.4:

    netsh http add urlacl url=https://10.0.0.4:443/ user=Users
    

    Cuando se registra una dirección URL, la herramienta responde con URL reservation successfully added.

    Para eliminar una dirección URL registrada, use el comando delete urlacl:

    netsh http delete urlacl url=<URL>
    
  7. Registre certificados X.509 en el servidor.

    Use la herramienta netsh.exe para registrar certificados de la aplicación:

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP>: especifica la dirección IP local para el enlace. No use ningún enlace de carácter comodín. Use una dirección IP válida.
    • <PORT>: especifica el puerto para el enlace.
    • <THUMBPRINT>: huella digital del certificado X.509.
    • <GUID>: GUID generado por el desarrollador para representar la aplicación a efectos de información.

    A modo de referencia, almacene el GUID en la aplicación como etiqueta de paquete:

    • En Visual Studio:
      • Abra las propiedades del proyecto de la aplicación. Para ello, haga clic con el botón derecho en la aplicación, en el Explorador de soluciones, y seleccione Propiedades.
      • Seleccione la pestaña Paquete.
      • Escriba el GUID que creó en el campo Etiquetas.
    • Si no usa Visual Studio:
      • Abra el archivo de proyecto de la aplicación.

      • Agregue una propiedad <PackageTags> a un elemento <PropertyGroup> nuevo o existente con el GUID que creó:

        <PropertyGroup>
          <PackageTags>9412ee86-c21b-4eb8-bd89-f650fbf44931</PackageTags>
        </PropertyGroup>
        

    En el ejemplo siguiente:

    • La dirección IP local del servidor es 10.0.0.4.
    • Un generador de GUID aleatorios en línea proporciona el valor appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Cuando se registra un certificado, la herramienta responde con SSL Certificate successfully added.

    Para eliminar un registro de certificados, use el comando delete sslcert:

    netsh http delete sslcert ipport=<IP>:<PORT>
    

    Documentación de referencia de netsh.exe:

  8. Ejecutar la aplicación.

    No se necesitan privilegios de administrador para ejecutar la aplicación al enlazar a localhost mediante HTTP (no HTTPS) con un número de puerto mayor que 1024. Para otras configuraciones (por ejemplo, usar una dirección IP local o enlazar al puerto 443), ejecute la aplicación con privilegios de administrador.

    La aplicación responde a la dirección IP pública del servidor. En este ejemplo, el servidor está disponible en Internet mediante su dirección IP pública, 104.214.79.47.

    En este ejemplo, se usa un certificado de desarrollo. La página se carga de forma segura tras omitir la advertencia de que el certificado no es de confianza para el explorador.

    Browser window showing the app's Index page loaded

Escenarios de servidor proxy y equilibrador de carga

En el caso de las aplicaciones hospedadas por HTTP.sys que interactúan con las solicitudes de Internet o de una red corporativa, puede que sea necesario configurar más elementos si esas aplicaciones se hospedan detrás de servidores proxy y equilibradores de carga. Para más información, vea Configurar ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Obtención de información detallada de control del tiempo con IHttpSysRequestTimingFeature

IHttpSysRequestTimingFeature proporciona información detallada de control del tiempo para las solicitudes:

  • Las marcas de tiempo se obtienen con QueryPerformanceCounter.
  • La frecuencia de las marcas de tiempo se puede obtener con QueryPerformanceFrequency.
  • El índice de control del tiempo se puede convertir en HttpSysRequestTimingType para saber qué representa el control del tiempo.
  • El valor puede ser 0 si no está disponible el control del tiempo para la solicitud actual.
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys();

var app = builder.Build();

app.Use((context, next) =>
{
    var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();
    
    var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    var timestamps = feature.Timestamps;

    for (var i = 0; i < timestamps.Length; i++)
    {
        var timestamp = timestamps[i];
        var timingType = (HttpSysRequestTimingType)i;

        logger.LogInformation("Timestamp {timingType}: {timestamp}",
                                          timingType, timestamp);
    }

    return next(context);
});

app.MapGet("/", () => Results.Ok());

app.Run();

IHttpSysRequestTimingFeature.TryGetTimestamp recupera la marca de tiempo del tipo de control del tiempo proporcionado:

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys();

var app = builder.Build();

app.Use((context, next) =>
{
    var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();

    var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    var timingType = HttpSysRequestTimingType.RequestRoutingEnd;

    if (feature.TryGetTimestamp(timingType, out var timestamp))
    {
        logger.LogInformation("Timestamp {timingType}: {timestamp}",
                                          timingType, timestamp);
    }
    else
    {
        logger.LogInformation("Timestamp {timingType}: not available for the "
                                           + "current request",    timingType);
    }

    return next(context);
});

app.MapGet("/", () => Results.Ok());

app.Run();

IHttpSysRequestTimingFeature.TryGetElapsedTime indica el tiempo transcurrido entre dos marcas de tiempo especificadas:

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys();

var app = builder.Build();

app.Use((context, next) =>
{
    var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();

    var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    var startingTimingType = HttpSysRequestTimingType.RequestRoutingStart;
    var endingTimingType = HttpSysRequestTimingType.RequestRoutingEnd;

    if (feature.TryGetElapsedTime(startingTimingType, endingTimingType, out var elapsed))
    {
        logger.LogInformation(
            "Elapsed time {startingTimingType} to {endingTimingType}: {elapsed}",
            startingTimingType,
            endingTimingType,
            elapsed);
    }
    else
    {
        logger.LogInformation(
            "Elapsed time {startingTimingType} to {endingTimingType}:"
            + " not available for the current request.",
            startingTimingType,
            endingTimingType);
    }

    return next(context);
});

app.MapGet("/", () => Results.Ok());

app.Run();

Características avanzadas de HTTP/2 para admitir gRPC

Las características adicionales de HTTP/2 en HTTP.sys admiten gRPC, incluida la compatibilidad con los finalizadores de respuesta y el envío de marcos de restablecimiento.

Requisitos para ejecutar gRPC con HTTP.sys:

  • Windows 11, compilación 22000 o posterior, o Windows Server 2022, compilación 20348 o posterior.
  • Conexión con TLS 1.2 o posterior.

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.

Seguimiento

Para obtener información sobre cómo obtener seguimientos de HTTP.sys, consulte Escenarios de administración de HTTP.sys.

Recursos adicionales

HTTP.sys es un servidor web de ASP.NET Core que solo se ejecuta en Windows. HTTP.sys supone una alternativa al servidor Kestrel y ofrece algunas características que Kestrel no facilita.

Importante

HTTP.sys no es compatible con el módulo ASP.NET Core y no se puede usar con IIS o IIS Express.

HTTP.sys admite las siguientes características:

  • Autenticación de Windows
  • Uso compartido de puertos
  • HTTPS con SNI
  • HTTP/2 a través de TLS (Windows 10 o posterior)
  • Transmisión directa de archivos
  • Almacenamiento en caché de respuestas
  • WebSockets (Windows 8 o posterior)

Versiones de Windows compatibles:

  • Windows 7 o posterior
  • Windows Server 2008 R2 o posterior

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

Cuándo usar HTTP.sys

HTTP.sys resulta útil para implementaciones en las que:

  • Es necesario exponer el servidor directamente a Internet sin usar IIS.

    HTTP.sys communicates directly with the Internet

  • Una implementación interna requiere una característica que no está disponible en Kestrel. Para obtener más información, vea Diferencias entre Kestrel y HTTP.sys.

    HTTP.sys communicates directly with the internal network

HTTP.sys es una tecnología consolidada que protege contra muchos tipos de ataques y que proporciona la solidez, la seguridad y la escalabilidad de un servidor web con todas las características. El propio IIS se ejecuta como agente de escucha de HTTP sobre HTTP.sys.

Compatibilidad con HTTP/2

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

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

HTTP/2 está habilitado de forma predeterminada. Si no se establece una conexión HTTP/2, la conexión vuelve a HTTP/1.1. En una futura versión de Windows, las marcas de configuración de HTTP/2 estarán disponibles, incluida la capacidad para deshabilitar HTTP/2 con HTTP.sys.

Compatibilidad con HTTP/3

HTTP/3 está habilitado para las aplicaciones de ASP.NET Core cuando se cumplen los siguientes requisitos básicos:

Es posible que en las versiones de la compilación de Windows 11 anteriores se necesario usar una compilación de Windows Insider.

HTTP/3 se detecta como una actualización de HTTP/1.1 o HTTP/2 por medio del encabezado alt-svc. Esto significa que la primera solicitud normalmente usará HTTP/1.1 o HTTP/2 antes de cambiar a HTTP/3. Http.Sys no agrega automáticamente el encabezado alt-svc; debe agregarlo la aplicación. El código siguiente es un ejemplo de middleware que agrega el encabezado de respuesta alt-svc.

app.Use((context, next) =>
{
    context.Response.Headers.AltSvc = "h3=\":443\"";
    return next(context);
});

Coloque el código anterior al principio de la canalización de solicitud.

Http.Sys también admite el envío de un mensaje de protocolo HTTP/2 AltSvc en lugar de un encabezado de respuesta para notificar al cliente que HTTP/3 está disponible. Vea la clave del Registro EnableAltSvc. Para esto se necesitan enlaces sslcert de netsh que usen nombres de host en lugar de direcciones IP.

Autenticación de modo kernel con Kerberos

HTTP.sys delega en la autenticación de modo kernel con el protocolo de autenticación de Kerberos. La autenticación de modo usuario no se admite con Kerberos y HTTP.sys. Se debe usar la cuenta de equipo para descifrar el token o el vale de Kerberos que se obtiene de Active Directory y que el cliente reenvía al servidor para autenticar al usuario. Registre el nombre de entidad de seguridad de servicio (SPN) para el host, no el usuario de la aplicación.

Cómo usar HTTP.sys

Configuración de la aplicación de ASP.NET Core para usar HTTP.sys

Llame al método de extensión UseHttpSys al compilar el host y especifique las opciones HttpSysOptions necesarias. En el siguiente ejemplo se establecen las opciones en sus valores predeterminados:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseHttpSys(options =>
            {
                options.AllowSynchronousIO = false;
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;
                options.UrlPrefixes.Add("http://localhost:5005");
            });
            webBuilder.UseStartup<Startup>();
        });

La configuración adicional de HTTP.sys se controla a través de Configuración del Registro.

Para obtener más información acerca de las opciones de HTTP.sys, consulte HttpSysOptions.

MaxRequestBodySize

Tamaño máximo permitido de cualquier cuerpo de solicitud en bytes. Cuando se establece en null, el tamaño máximo del cuerpo de solicitud es ilimitado. Este límite no tiene ningún efecto en las conexiones actualizadas, que siempre son ilimitadas.

El método recomendado para reemplazar el límite de una aplicación de ASP.NET Core MVC para un solo objeto IActionResult consiste en usar el atributo RequestSizeLimitAttribute en un método de acción:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

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

Si la aplicación debe reemplazar MaxRequestBodySize por solicitud, use IHttpMaxRequestBodySizeFeature:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
    ILogger<Startup> logger, IServer server)
{
    app.Use(async (context, next) =>
    {
        context.Features.Get<IHttpMaxRequestBodySizeFeature>()
            .MaxRequestBodySize = 10 * 1024;

        var serverAddressesFeature = 
            app.ServerFeatures.Get<IServerAddressesFeature>();
        var addresses = string.Join(", ", serverAddressesFeature?.Addresses);

        logger.LogInformation("Addresses: {Addresses}", addresses);

        await next.Invoke();
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

If usa Visual Studio, asegúrese de que la aplicación no está configurada para ejecutar IIS o IIS Express.

En Visual Studio, el perfil de inicio predeterminado es para IIS Express. Para ejecutar el proyecto como aplicación de consola, cambie manualmente el perfil seleccionado, tal y como se muestra en la siguiente captura de pantalla:

Select console app profile

Configurar Windows Server

  1. Determine los puertos que se van a abrir para la aplicación y use el Firewall de Windows o el cmdlet New-NetFirewallRule de PowerShell para abrir los puertos del firewall y permitir que el tráfico llegue a HTTP.sys. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  2. Cuando realice una implementación en una máquina virtual de Azure, abra los puertos del grupo de seguridad de red. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  3. Si es necesario, obtenga e instale los certificados X.509.

    En Windows, puede crear certificados autofirmados con el cmdlet New-SelfSignedCertificate de PowerShell. Para obtener un ejemplo no compatible, vea UpdateIISExpressSSLForChrome.ps1.

    Instale certificados autofirmados o firmados por CA en el almacén Máquina local>Personal del servidor.

  4. Si la aplicación es una implementación dependiente del marco, instale .NET Core, .NET Framework o ambos (si se trata de una aplicación de .NET Core que tiene como destino .NET Framework).

    • .NET Core: si la aplicación requiere .NET Core, obtenga y ejecute el instalador de .NET Core Runtime en la página de descargas de .NET Core. No instale el SDK completo en el servidor.
    • .NET Framework: si la aplicación requiere .NET Framework, consulte la guía de instalación de .NET Framework. Instale la versión necesaria de .NET Framework. El instalador de la versión más reciente de .NET Framework está disponible en la página de descargas de .NET Core.

    Si la aplicación se basa en la implementación autocontenida, incluirá el entorno de ejecución en la implementación. No se requiere la instalación de ningún marco en el servidor.

  5. Configure los puertos y las direcciones URL en la aplicación.

    ASP.NET Core se enlaza a http://localhost:5000 de forma predeterminada. Para configurar los puertos y los prefijos de dirección URL, las opciones incluyen lo siguiente:

    • UseUrls
    • El argumento de la línea de comandos urls
    • La variable de entorno ASPNETCORE_URLS
    • UrlPrefixes

    En el código siguiente, se muestra cómo usar UrlPrefixescon la dirección IP local del servidor, 10.0.0.4, en el puerto 443:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseHttpSys(options =>
                {
                    options.UrlPrefixes.Add("https://10.0.0.4:443");
                });
                webBuilder.UseStartup<Startup>();
            });
    

    Una ventaja de UrlPrefixes es que se genera inmediatamente un mensaje de error para prefijos con formato incorrecto.

    La configuración de UrlPrefixes invalida la configuración de UseUrls/urls/ASPNETCORE_URLS. Por lo tanto, la ventaja de UseUrls, urls y la variable de entorno ASPNETCORE_URLS es que resulta más fácil de cambiar entre Kestrel y HTTP.sys.

    HTTP.sys usa los formatos de cadena UrlPrefix de la API HTTP Server.

    Advertencia

    Los enlaces de carácter comodín de nivel superior (http://*:80/ y http://+:80) no se deben usar. Los enlaces de carácter comodín de nivel superior generan vulnerabilidades de seguridad en la aplicación. Esto se aplica tanto a los caracteres comodín fuertes como a los débiles. Use nombres de host explícitos o direcciones IP en lugar de caracteres comodín. Los enlaces de carácter comodín de subdominio (por ejemplo, *.mysub.com) no suponen ningún riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Sección 7.2: Host y :authority.

  6. Registre previamente los prefijos de URL en el servidor.

    La herramienta integrada para configurar HTTP.sys es netsh.exe. netsh.exe se usa para reservar prefijos de dirección URL y asignar certificados X.509. Esta herramienta requiere privilegios de administrador.

    Use la herramienta netsh.exe para registrar URL de la aplicación:

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL>: localizador uniforme de recursos (URL) completo especificado. No use ningún enlace de carácter comodín. Use un nombre de host válido o la dirección IP local. La dirección URL debe incluir una barra diagonal final.
    • <USER>: especifica el nombre del usuario o el grupo de usuarios.

    En el ejemplo siguiente, la dirección IP local del servidor es 10.0.0.4:

    netsh http add urlacl url=https://10.0.0.4:443/ user=Users
    

    Cuando se registra una dirección URL, la herramienta responde con URL reservation successfully added.

    Para eliminar una dirección URL registrada, use el comando delete urlacl:

    netsh http delete urlacl url=<URL>
    
  7. Registre certificados X.509 en el servidor.

    Use la herramienta netsh.exe para registrar certificados de la aplicación:

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP>: especifica la dirección IP local para el enlace. No use ningún enlace de carácter comodín. Use una dirección IP válida.
    • <PORT>: especifica el puerto para el enlace.
    • <THUMBPRINT>: huella digital del certificado X.509.
    • <GUID>: GUID generado por el desarrollador para representar la aplicación a efectos de información.

    A modo de referencia, almacene el GUID en la aplicación como etiqueta de paquete:

    • En Visual Studio:
      • Abra las propiedades del proyecto de la aplicación. Para ello, haga clic con el botón derecho en la aplicación, en el Explorador de soluciones, y seleccione Propiedades.
      • Seleccione la pestaña Paquete.
      • Escriba el GUID que creó en el campo Etiquetas.
    • Si no usa Visual Studio:
      • Abra el archivo de proyecto de la aplicación.

      • Agregue una propiedad <PackageTags> a un elemento <PropertyGroup> nuevo o existente con el GUID que creó:

        <PropertyGroup>
          <PackageTags>9412ee86-c21b-4eb8-bd89-f650fbf44931</PackageTags>
        </PropertyGroup>
        

    En el ejemplo siguiente:

    • La dirección IP local del servidor es 10.0.0.4.
    • Un generador de GUID aleatorios en línea proporciona el valor appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Cuando se registra un certificado, la herramienta responde con SSL Certificate successfully added.

    Para eliminar un registro de certificados, use el comando delete sslcert:

    netsh http delete sslcert ipport=<IP>:<PORT>
    

    Documentación de referencia de netsh.exe:

  8. Ejecutar la aplicación.

    No se necesitan privilegios de administrador para ejecutar la aplicación al enlazar a localhost mediante HTTP (no HTTPS) con un número de puerto mayor que 1024. Para otras configuraciones (por ejemplo, usar una dirección IP local o enlazar al puerto 443), ejecute la aplicación con privilegios de administrador.

    La aplicación responde a la dirección IP pública del servidor. En este ejemplo, el servidor está disponible en Internet mediante su dirección IP pública, 104.214.79.47.

    En este ejemplo, se usa un certificado de desarrollo. La página se carga de forma segura tras omitir la advertencia de que el certificado no es de confianza para el explorador.

    Browser window showing the app's Index page loaded

Escenarios de servidor proxy y equilibrador de carga

En el caso de las aplicaciones hospedadas por HTTP.sys que interactúan con las solicitudes de Internet o de una red corporativa, puede que sea necesario configurar más elementos si esas aplicaciones se hospedan detrás de servidores proxy y equilibradores de carga. Para más información, vea Configurar ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Características avanzadas de HTTP/2 para admitir gRPC

Las características adicionales de HTTP/2 en HTTP.sys admiten gRPC, incluida la compatibilidad con los finalizadores de respuesta y el envío de marcos de restablecimiento.

Requisitos para ejecutar gRPC con HTTP.sys:

  • Windows 11, compilación 22000 o posterior, o Windows Server 2022, compilación 20348 o posterior.
  • Conexión con TLS 1.2 o posterior.

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.

Recursos adicionales

HTTP.sys es un servidor web de ASP.NET Core que solo se ejecuta en Windows. HTTP.sys supone una alternativa al servidor Kestrel y ofrece algunas características que Kestrel no facilita.

Importante

HTTP.sys no es compatible con el módulo ASP.NET Core y no se puede usar con IIS o IIS Express.

HTTP.sys admite las siguientes características:

  • Autenticación de Windows
  • Uso compartido de puertos
  • HTTPS con SNI
  • HTTP/2 a través de TLS (Windows 10 o posterior)
  • Transmisión directa de archivos
  • Almacenamiento en caché de respuestas
  • WebSockets (Windows 8 o posterior)

Versiones de Windows compatibles:

  • Windows 7 o posterior
  • Windows Server 2008 R2 o posterior

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

Cuándo usar HTTP.sys

HTTP.sys resulta útil para implementaciones en las que:

  • Es necesario exponer el servidor directamente a Internet sin usar IIS.

    HTTP.sys communicates directly with the Internet

  • Una implementación interna requiere una característica que no está disponible en Kestrel. Para obtener más información, vea Diferencias entre Kestrel y HTTP.sys.

    HTTP.sys communicates directly with the internal network

HTTP.sys es una tecnología consolidada que protege contra muchos tipos de ataques y que proporciona la solidez, la seguridad y la escalabilidad de un servidor web con todas las características. El propio IIS se ejecuta como agente de escucha de HTTP sobre HTTP.sys.

Compatibilidad con HTTP/2

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

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

HTTP/2 está habilitado de forma predeterminada. Si no se establece una conexión HTTP/2, la conexión vuelve a HTTP/1.1. En una futura versión de Windows, las marcas de configuración de HTTP/2 estarán disponibles, incluida la capacidad para deshabilitar HTTP/2 con HTTP.sys.

Autenticación de modo kernel con Kerberos

HTTP.sys delega en la autenticación de modo kernel con el protocolo de autenticación de Kerberos. La autenticación de modo usuario no se admite con Kerberos y HTTP.sys. Se debe usar la cuenta de equipo para descifrar el token o el vale de Kerberos que se obtiene de Active Directory y que el cliente reenvía al servidor para autenticar al usuario. Registre el nombre de entidad de seguridad de servicio (SPN) para el host, no el usuario de la aplicación.

Cómo usar HTTP.sys

Configuración de la aplicación de ASP.NET Core para usar HTTP.sys

Llame al método de extensión UseHttpSys al compilar el host y especifique las opciones HttpSysOptions necesarias. En el siguiente ejemplo se establecen las opciones en sus valores predeterminados:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseHttpSys(options =>
            {
                options.AllowSynchronousIO = false;
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;
                options.UrlPrefixes.Add("http://localhost:5005");
            });
            webBuilder.UseStartup<Startup>();
        });

La configuración adicional de HTTP.sys se controla a través de Configuración del Registro.

Opciones de HTTP.sys

Propiedad. Descripción Default
AllowSynchronousIO Controlar si se permite la entrada/salida sincrónica de los objetos HttpContext.Request.Body y HttpContext.Response.Body. false
Authentication.AllowAnonymous Permitir solicitudes anónimas. true
Authentication.Schemes Especificar los esquemas de autenticación permitidos. Puede modificarse en cualquier momento antes de eliminar el agente de escucha. Los valores se proporcionan con la enumeración AuthenticationSchemes: Basic, Kerberos, Negotiate, None y NTLM. None
EnableResponseCaching Intentar el almacenamiento en memoria caché en modo kernel de las respuestas con encabezados elegibles. Es posible que la respuesta no incluya encabezados Set-Cookie, Vary o Pragma. Debe incluir un encabezado Cache-Control que sea public y un valor shared-max-age o max-age, o un encabezado Expires. true
Http503Verbosity El comportamiento de HTTP.sys al rechazar solicitudes debido a las condiciones de limitación. Http503VerbosityLevel.
Basic
MaxAccepts Número máximo de aceptaciones simultáneas. 5 × Entorno.
ProcessorCount
MaxConnections Establecer el número máximo de conexiones simultáneas que se aceptan. Use -1 para infinito. Use null para usar la configuración de la máquina del Registro. null
(configuración en toda la
máquina)
MaxRequestBodySize Vea la sección MaxRequestBodySize. 30 000 000 bytes
(~28,6 MB)
RequestQueueLimit Número máximo de solicitudes que se pueden poner en cola. 1000
RequestQueueMode Indica si el servidor es responsable de la creación y configuración de la cola de solicitudes o si se debe adjuntar a una cola existente.
La mayoría de las opciones de configuración existentes no se aplican al adjuntarse a una cola existente.
RequestQueueMode.Create
RequestQueueName El nombre de la cola de solicitud de HTTP.sys. null (Cola anónima)
ThrowWriteExceptions Indicar si las escrituras del cuerpo de respuesta que no se producen debido a desconexiones del cliente deben iniciar excepciones o finalizar con normalidad. false
(finalizar con normalidad)
Timeouts Exponer la configuración de TimeoutManager de HTTP.sys, que también puede configurarse en el Registro. Siga los vínculos de API para obtener más información sobre cada configuración, incluidos los valores predeterminados:
UrlPrefixes Especifique UrlPrefixCollection para registrarse con HTTP.sys. El más útil es UrlPrefixCollection.Add, que se usa para agregar un prefijo a la colección. Pueden modificarse en cualquier momento antes de eliminar el agente de escucha.

MaxRequestBodySize

Tamaño máximo permitido de cualquier cuerpo de solicitud en bytes. Cuando se establece en null, el tamaño máximo del cuerpo de solicitud es ilimitado. Este límite no tiene ningún efecto en las conexiones actualizadas, que siempre son ilimitadas.

El método recomendado para reemplazar el límite de una aplicación de ASP.NET Core MVC para un solo objeto IActionResult consiste en usar el atributo RequestSizeLimitAttribute en un método de acción:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

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

Si la aplicación debe reemplazar MaxRequestBodySize por solicitud, use IHttpMaxRequestBodySizeFeature:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
    ILogger<Startup> logger, IServer server)
{
    app.Use(async (context, next) =>
    {
        context.Features.Get<IHttpMaxRequestBodySizeFeature>()
            .MaxRequestBodySize = 10 * 1024;

        var serverAddressesFeature = 
            app.ServerFeatures.Get<IServerAddressesFeature>();
        var addresses = string.Join(", ", serverAddressesFeature?.Addresses);

        logger.LogInformation("Addresses: {Addresses}", addresses);

        await next.Invoke();
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

If usa Visual Studio, asegúrese de que la aplicación no está configurada para ejecutar IIS o IIS Express.

En Visual Studio, el perfil de inicio predeterminado es para IIS Express. Para ejecutar el proyecto como aplicación de consola, cambie manualmente el perfil seleccionado, tal y como se muestra en la siguiente captura de pantalla:

Select console app profile

Configurar Windows Server

  1. Determine los puertos que se van a abrir para la aplicación y use el Firewall de Windows o el cmdlet New-NetFirewallRule de PowerShell para abrir los puertos del firewall y permitir que el tráfico llegue a HTTP.sys. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  2. Cuando realice una implementación en una máquina virtual de Azure, abra los puertos del grupo de seguridad de red. En los comandos y la configuración de la aplicación siguientes, se usa el puerto 443.

  3. Si es necesario, obtenga e instale los certificados X.509.

    En Windows, puede crear certificados autofirmados con el cmdlet New-SelfSignedCertificate de PowerShell. Para obtener un ejemplo no compatible, vea UpdateIISExpressSSLForChrome.ps1.

    Instale certificados autofirmados o firmados por CA en el almacén Máquina local>Personal del servidor.

  4. Si la aplicación es una implementación dependiente del marco, instale .NET Core, .NET Framework o ambos (si se trata de una aplicación de .NET Core que tiene como destino .NET Framework).

    • .NET Core: si la aplicación requiere .NET Core, obtenga y ejecute el instalador de .NET Core Runtime en la página de descargas de .NET Core. No instale el SDK completo en el servidor.
    • .NET Framework: si la aplicación requiere .NET Framework, consulte la guía de instalación de .NET Framework. Instale la versión necesaria de .NET Framework. El instalador de la versión más reciente de .NET Framework está disponible en la página de descargas de .NET Core.

    Si la aplicación se basa en la implementación autocontenida, incluirá el entorno de ejecución en la implementación. No se requiere la instalación de ningún marco en el servidor.

  5. Configure los puertos y las direcciones URL en la aplicación.

    ASP.NET Core se enlaza a http://localhost:5000 de forma predeterminada. Para configurar los puertos y los prefijos de dirección URL, las opciones incluyen lo siguiente:

    • UseUrls
    • El argumento de la línea de comandos urls
    • La variable de entorno ASPNETCORE_URLS
    • UrlPrefixes

    En el código siguiente, se muestra cómo usar UrlPrefixescon la dirección IP local del servidor, 10.0.0.4, en el puerto 443:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseHttpSys(options =>
                {
                    options.UrlPrefixes.Add("https://10.0.0.4:443");
                });
                webBuilder.UseStartup<Startup>();
            });
    

    Una ventaja de UrlPrefixes es que se genera inmediatamente un mensaje de error para prefijos con formato incorrecto.

    La configuración de UrlPrefixes invalida la configuración de UseUrls/urls/ASPNETCORE_URLS. Por lo tanto, la ventaja de UseUrls, urls y la variable de entorno ASPNETCORE_URLS es que resulta más fácil de cambiar entre Kestrel y HTTP.sys.

    HTTP.sys usa los formatos de cadena UrlPrefix de la API HTTP Server.

    Advertencia

    Los enlaces de carácter comodín de nivel superior (http://*:80/ y http://+:80) no se deben usar. Los enlaces de carácter comodín de nivel superior generan vulnerabilidades de seguridad en la aplicación. Esto se aplica tanto a los caracteres comodín fuertes como a los débiles. Use nombres de host explícitos o direcciones IP en lugar de caracteres comodín. Los enlaces de carácter comodín de subdominio (por ejemplo, *.mysub.com) no suponen ningún riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Sección 7.2: Host y :authority.

  6. Registre previamente los prefijos de URL en el servidor.

    La herramienta integrada para configurar HTTP.sys es netsh.exe. netsh.exe se usa para reservar prefijos de dirección URL y asignar certificados X.509. Esta herramienta requiere privilegios de administrador.

    Use la herramienta netsh.exe para registrar URL de la aplicación:

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL>: localizador uniforme de recursos (URL) completo especificado. No use ningún enlace de carácter comodín. Use un nombre de host válido o la dirección IP local. La dirección URL debe incluir una barra diagonal final.
    • <USER>: especifica el nombre del usuario o el grupo de usuarios.

    En el ejemplo siguiente, la dirección IP local del servidor es 10.0.0.4:

    netsh http add urlacl url=https://10.0.0.4:443/ user=Users
    

    Cuando se registra una dirección URL, la herramienta responde con URL reservation successfully added.

    Para eliminar una dirección URL registrada, use el comando delete urlacl:

    netsh http delete urlacl url=<URL>
    
  7. Registre certificados X.509 en el servidor.

    Use la herramienta netsh.exe para registrar certificados de la aplicación:

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP>: especifica la dirección IP local para el enlace. No use ningún enlace de carácter comodín. Use una dirección IP válida.
    • <PORT>: especifica el puerto para el enlace.
    • <THUMBPRINT>: huella digital del certificado X.509.
    • <GUID>: GUID generado por el desarrollador para representar la aplicación a efectos de información.

    A modo de referencia, almacene el GUID en la aplicación como etiqueta de paquete:

    • En Visual Studio:
      • Abra las propiedades del proyecto de la aplicación. Para ello, haga clic con el botón derecho en la aplicación, en el Explorador de soluciones, y seleccione Propiedades.
      • Seleccione la pestaña Paquete.
      • Escriba el GUID que creó en el campo Etiquetas.
    • Si no usa Visual Studio:
      • Abra el archivo de proyecto de la aplicación.

      • Agregue una propiedad <PackageTags> a un elemento <PropertyGroup> nuevo o existente con el GUID que creó:

        <PropertyGroup>
          <PackageTags>9412ee86-c21b-4eb8-bd89-f650fbf44931</PackageTags>
        </PropertyGroup>
        

    En el ejemplo siguiente:

    • La dirección IP local del servidor es 10.0.0.4.
    • Un generador de GUID aleatorios en línea proporciona el valor appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Cuando se registra un certificado, la herramienta responde con SSL Certificate successfully added.

    Para eliminar un registro de certificados, use el comando delete sslcert:

    netsh http delete sslcert ipport=<IP>:<PORT>
    

    Documentación de referencia de netsh.exe:

  8. Ejecutar la aplicación.

    No se necesitan privilegios de administrador para ejecutar la aplicación al enlazar a localhost mediante HTTP (no HTTPS) con un número de puerto mayor que 1024. Para otras configuraciones (por ejemplo, usar una dirección IP local o enlazar al puerto 443), ejecute la aplicación con privilegios de administrador.

    La aplicación responde a la dirección IP pública del servidor. En este ejemplo, el servidor está disponible en Internet mediante su dirección IP pública, 104.214.79.47.

    En este ejemplo, se usa un certificado de desarrollo. La página se carga de forma segura tras omitir la advertencia de que el certificado no es de confianza para el explorador.

    Browser window showing the app's Index page loaded

Escenarios de servidor proxy y equilibrador de carga

En el caso de las aplicaciones hospedadas por HTTP.sys que interactúan con las solicitudes de Internet o de una red corporativa, puede que sea necesario configurar más elementos si esas aplicaciones se hospedan detrás de servidores proxy y equilibradores de carga. Para más información, vea Configurar ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Características avanzadas de HTTP/2 para admitir gRPC

Las características adicionales de HTTP/2 en HTTP.sys admiten gRPC, incluida la compatibilidad con los finalizadores de respuesta y el envío de marcos de restablecimiento.

Requisitos para ejecutar gRPC con HTTP.sys:

  • Windows 10, compilación del sistema operativo 19041.508 o posterior
  • Conexión con TLS 1.2 o una versión posterior

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.

Recursos adicionales