Implémentation du serveur web HTTP.sys dans ASP.NET Core

Par Tom Dykstra et Chris Ross

HTTP.sys est un serveur web pour ASP.NET Core qui s’exécute uniquement sous Windows. HTTP.sys est une alternative à Kestrel serveur et offre certaines fonctionnalités que Kestrel ne fournissent pas.

Important

HTTP.sys est incompatible avec le Module ASP.NET Core et n’est pas utilisable avec IIS ni IIS Express.

HTTP.sys prend en charge les fonctionnalités suivantes :

  • Authentification Windows
  • Partage de port
  • HTTPS avec SNI
  • HTTP/2 sur TLS (Windows 10 et versions ultérieures)
  • Transmission de fichier directe
  • Mise en cache des réponses
  • WebSockets (Windows 8 et versions ultérieures)

Versions de Windows prises en charge :

  • Windows 7 ou version ultérieure
  • Windows Server 2008 R2 ou version ultérieure

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Quand utiliser HTTP.sys

HTTP.sys est utile pour les déploiements lorsque :

  • Il est nécessaire d’exposer directement le serveur à Internet sans passer par IIS.

    HTTP.sys communicates directly with the Internet

  • Un déploiement interne nécessite une fonctionnalité non disponible dans Kestrel. Pour plus d’informations, consultez Kestrel par rapport à HTTP.sys

    HTTP.sys communicates directly with the internal network

HTTP.sys est une technologie aboutie qui assure une protection contre de nombreux types d’attaques et offre la robustesse, la sécurité et l’extensibilité d’un serveur web haut de gamme. Pour sa part, IIS s’exécute en tant qu’écouteur HTTP sur HTTP.sys.

Assistance HTTP/2

HTTP/2 est activé pour les applications ASP.NET Core lorsque les exigences de base suivantes sont remplies :

Si une connexion HTTP/2 est établie, HttpRequest.Protocol retourne HTTP/2.

HTTP/2 est activé par défaut. Si une connexion HTTP/2 n’est pas établie, la connexion revient à HTTP/1.1. Dans une prochaine version de Windows, les indicateurs de configuration HTTP/2 seront disponibles, y compris la possibilité de désactivation de HTTP/2 avec HTTP.sys.

Prise en charge de HTTP/3

HTTP/3 est activé pour les applications ASP.NET Core si les conditions de base suivantes sont remplies :

  • Windows Server 2022/Windows 11 ou version ultérieure
  • Une liaison d’URL https est utilisée.
  • La clé de Registre EnableHttp3 est définie.

Les versions de build Windows 11 précédentes peuvent nécessiter l’utilisation d’une build Windows Insider.

HTTP/3 est découvert comme une mise à niveau à partir de HTTP/1.1 ou HTTP/2 via l’en-tête alt-svc. Cela signifie que la première requête utilise normalement HTTP/1.1 ou HTTP/2 avant de passer à HTTP/3. Http.Sys n’ajoute pas automatiquement l’en-tête alt-svc, il doit être ajouté par l’application. Le code suivant est un exemple d’intergiciel qui ajoute l’en-tête de réponse alt-svc.

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

Placez le code précédent au début du pipeline de requête.

Http.Sys prend également en charge l’envoi d’un message de protocole HTTP/2 AltSvc plutôt qu’un en-tête de réponse pour avertir le client que HTTP/3 est disponible. Consultez la clé de Registre EnableAltSvc. Cela nécessite des liaisons netsh sslcert qui utilisent des noms d’hôte plutôt que des adresses IP.

Authentification en mode noyau avec Kerberos

HTTP.sys délègue l’authentification en mode noyau avec le protocole d’authentification Kerberos. L’authentification en mode utilisateur n’est pas prise en charge avec Kerberos et HTTP.sys. Le compte d’ordinateur doit être utilisé pour déchiffrer le ticket/jeton Kerberos obtenu à partir d’Active Directory et transféré par le client au serveur afin d’authentifier l’utilisateur. Inscrivez le nom de principal du service (SPN) pour l’hôte, et non l’utilisateur de l’application.

Prise en charge de la mise en mémoire tampon des réponses en mode noyau

Dans certains scénarios, des volumes élevés d’écritures de petite taille avec une latence élevée peuvent avoir un impact significatif sur les performances de HTTP.sys. Cet impact est dû à l’absence d’une mémoire tampon Pipe dans l’implémentation HTTP.sys. Pour améliorer les performances dans ces scénarios, la prise en charge de la mise en mémoire tampon de réponse est incluse dans HTTP.sys. Activez la mise en mémoire tampon en définissant HttpSysOptions.EnableKernelResponseBuffering sur true.

La mise en mémoire tampon de réponse doit être activée par une application qui effectue des E/S synchrones ou des E/S asynchrones avec pas plus d’une écriture en attente à la fois. Dans ces scénarios, la mise en mémoire tampon de réponse peut améliorer considérablement le débit sur les connexions à latence élevée.

Les applications qui utilisent des E/S asynchrones et qui peuvent avoir plusieurs écritures en attente à la fois ne doivent pas utiliser cet indicateur. L’activation de cet indicateur peut entraîner une utilisation plus élevée du processeur et de la mémoire par HTTP.Sys.

Comment utiliser HTTP.sys

Configurer l’application ASP.NET Core afin d’utiliser HTTP.sys

Appelez la méthode d’extension UseHttpSys au moment de générer l’hôte, en spécifiant les options HttpSysOptions nécessaires. L’exemple suivant définit les options sur leurs valeurs par défaut :

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

Le reste de la configuration de HTTP.sys est géré par le biais des paramètres du Registre.

Pour plus d’informations sur les options HTTP.sys, consultez HttpSysOptions.

MaxRequestBodySize

Taille maximale autorisée pour le corps d’une demande, en octets. Lorsque la valeur est null, elle est illimitée. Cette limite est sans effet sur les connexions mises à niveau, qui sont illimitées.

Pour remplacer la limite d’un seul IActionResult dans une application MVC ASP.NET Core, nous vous recommandons d’utiliser l’attribut RequestSizeLimitAttribute sur une méthode d’action :

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Une exception est levée si l’application tente de configurer la limite sur une demande dont l’application a commencé la lecture. La propriété IsReadOnly indique si la propriété MaxRequestBodySize est en lecture seule, et donc s’il est trop tard pour configurer la limite.

Si l’application doit remplacer MaxRequestBodySize par requête, utilisez 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);
});

Si vous utilisez Visual Studio, vérifiez que l’application n’est pas configurée pour exécuter IIS ou IIS Express.

Dans Visual Studio, le profil de démarrage par défaut est destiné à IIS Express. Pour exécuter le projet en tant qu’application console, changez manuellement le profil sélectionné, comme dans la capture d’écran suivante :

Select console app profile

Configurer Windows Server

  1. Identifiez les ports à ouvrir pour l’application et utilisez le pare-feu Windows ou les applets de commande PowerShell New-NetFirewallRule pour ouvrir les ports du pare-feu et ainsi permettre au trafic d’atteindre HTTP.sys. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  2. Lors du déploiement sur une machine virtuelle Azure, ouvrez les ports dans le groupe de sécurité réseau. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  3. Obtenez et installez des certificats X.509, si nécessaire.

    Sous Windows, créez des certificats auto-signés à l’aide de la cmdlet PowerShell New-SelfSignedCertificate. Vous trouverez un exemple non pris en charge sur la page UpdateIISExpressSSLForChrome.ps1.

    Installez des certificats auto-signés ou signés par l’autorité de certification dans le magasin Ordinateur Local>Personnel du serveur.

  4. Si l’application est un déploiement dépendant de .NET Framework, installez .NET Core, .NET Framework ou les deux (si l’application est une application .NET Core ciblant .NET Framework).

    • .NET Core : si l’application nécessite .NET Core, obtenez et exécutez le programme d’installation Runtime .NET Core à partir de téléchargements .NET Core. N’installez pas le Kit SDK complet sur le serveur.
    • .NET Framework : si l’application nécessite .NET Framework, consultez le guide d’installation .NET Framework. Installez la version requise de .NET Framework. Le programme d’installation du .NET Framework le plus récent est disponible depuis la page Téléchargements .NET Core.

    Si l’application est un déploiement autonome, elle inclut le runtime dans son déploiement. Aucune installation de framework n’est requise sur le serveur.

  5. Configurez les ports et les URL de l’application.

    Par défaut, ASP.NET Core est lié à http://localhost:5000. Pour configurer les ports et les préfixes d’URL, il existe plusieurs possibilités :

    • UseUrls
    • Arguments de ligne de commande urls
    • ASPNETCORE_URLS variable d’environnement
    • UrlPrefixes

    L’exemple de code suivant montre comment utiliser UrlPrefixes avec l’adresse IP locale du serveur 10.0.0.4 sur le port 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();
    

    UrlPrefixes présente l’avantage de générer immédiatement un message d’erreur en cas de préfixe mal formé.

    Les paramètres de UrlPrefixes remplacent les paramètres UseUrls/urls/ASPNETCORE_URLS. Par conséquent, un avantage de UseUrls, urls et de la variable d’environnement ASPNETCORE_URLS est qu’il est plus facile de basculer entre Kestrel et HTTP.sys.

    HTTP.sys reconnaît deux types de cartes génériques dans les préfixes des URL :

    • * est une liaison faible, également appelée liaison de secours. Si le préfixe de l’URL est http://*:5000 et qu’autre chose est lié au port 5000, cette liaison ne va pas être utilisée.
    • + est une liaison forte. Si le préfixe de l’URL est http://+:5000, cette liaison est utilisée avant les autres liaisons au port 5000.

    Pour plus d’informations, consultez Chaînes UrlPrefix.

    Avertissement

    Les liaisons génériques de niveau supérieur (http://*:80/ et http://+:80) ne doivent pas être utilisées. Les liaisons génériques de niveau supérieur créent des failles de sécurité dans l’application. Cela s’applique aux caractères génériques forts et faibles. Utilisez des noms d’hôte ou des adresses IP explicites plutôt que des caractères génériques. Une liaison générique de sous-domaine (par exemple, *.mysub.com) ne constitue pas un risque de sécurité si vous contrôlez le domaine parent en entier (par opposition à *.com, qui est vulnérable). Pour plus d’informations, consultez RFC 9110 : Section 7.2 : Hôte et :authority.

    Les applications et les conteneurs ne reçoivent souvent qu’un port à écouter, comme le port 80, sans contraintes supplémentaires telles que l’hôte ou le chemin d’accès. HTTP_PORTS et HTTPS_PORTS sont des clés de configuration qui spécifient les ports d’écoute pour les serveurs Kestrel et HTTP.sys. Ces clés peuvent être spécifiées en tant que variables d’environnement définies avec les préfixes DOTNET_ ou ASPNETCORE_, ou spécifiées directement par le biais d’une autre entrée de configuration, telle que appsettings.json. Il s’agit d’une liste délimitée par des points-virgules de valeurs de port, comme illustré dans l’exemple suivant :

    ASPNETCORE_HTTP_PORTS=80;8080
    ASPNETCORE_HTTPS_PORTS=443;8081
    

    L’exemple précédent est abrégé pour la configuration suivante, qui spécifie le schéma (HTTP ou HTTPS) et tout hôte ou adresse IP.

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

    Les clés de configuration HTTP_PORTS et HTTPS_PORTS sont prioritaires et sont remplacées par des URL ou des valeurs fournies directement dans le code. Les certificats doivent toujours être configurés séparément via des mécanismes spécifiques au serveur pour HTTPS.

    Ces clés de configuration sont équivalentes aux liaisons génériques de niveau supérieur. Elles sont pratiques pour le développement et les scénarios de conteneur, mais évitent les caractères génériques lors de l’exécution sur un ordinateur qui peut également héberger d’autres services.

  6. Préenregistrez les préfixes d’URL sur le serveur.

    L’outil intégré pour configurer HTTP.sys est netsh.exe. netsh.exe permet de réserver des préfixes d’URL et d’assigner des certificats X.509. L’outil requiert des privilèges Administrateur.

    Utilisez l’outil netsh.exe pour enregistrer les URL pour l’application :

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL> : URL (Uniform Resource Locator) complet. N’utilisez pas une liaison de caractère générique. Utilisez un nom d’hôte ou une adresse IP locale valide. L’URL doit inclure une barre oblique de fin.
    • <USER> : spécifie le nom de l’utilisateur ou du groupe d’utilisateurs.

    Dans l’exemple suivant, l’adresse IP locale du serveur est 10.0.0.4 :

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

    Lorsqu’une URL est inscrite, l’outil répond avec URL reservation successfully added.

    Pour supprimer une URL inscrite, utilisez la commande delete urlacl :

    netsh http delete urlacl url=<URL>
    
  7. Inscrivez les certificats X.509 sur le serveur.

    Utilisez l’outil netsh.exe pour enregistrer les certificats pour l’application :

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP> : spécifie l’adresse IP locale de la liaison. N’utilisez pas une liaison de caractère générique. Utilisez une adresse IP valide.
    • <PORT> : spécifie le port de la liaison.
    • <THUMBPRINT> : empreinte numérique du certificat X.509.
    • <GUID> : GUID généré par le développeur pour représenter l’application à des fins d’information.

    À titre de référence, stockez le GUID dans l’application en tant que balise de package :

    • Dans Visual Studio :
      • Ouvrez les propriétés du projet de l’application en cliquant avec le bouton droit sur l’application dans l’Explorateur de solutions et en sélectionnant Propriétés.
      • Sélectionnez l’onglet Package.
      • Entrez le GUID que vous avez créé dans le champ Balises.
    • Si vous n’utilisez pas Visual Studio :
      • Ouvrez le chemin d’accès vers le fichier de projet de l’application.

      • Ajoutez une propriété <PackageTags> à un <PropertyGroup> nouveau ou existant avec le GUID que vous avez créé :

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

    Dans l’exemple suivant :

    • L’adresse IP locale du serveur est 10.0.0.4.
    • Un générateur de GUID aléatoire en ligne fournit la valeur appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Lorsqu’un certificat est inscrit, l’outil répond avec SSL Certificate successfully added.

    Pour supprimer l’inscription d’un certificat, utilisez la commande delete sslcert :

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

    Documentation de référence de netsh.exe :

  8. Exécutez l'application.

    Les privilèges administrateur ne sont pas requis pour exécuter l’application lors d’une liaison à localhost à l’aide de HTTP (pas HTTPS) avec un numéro de port supérieur à 1024. Pour les autres configurations (par exemple, l’utilisation d’une adresse IP locale ou la liaison au port 443), exécutez l’application avec des privilèges administrateur.

    L’application répond à l’adresse IP publique du serveur. Dans cet exemple, le serveur est contacté à partir d’Internet à son adresse IP publique 104.214.79.47.

    Un certificat de développement est utilisé dans cet exemple. La page est chargée en toute sécurité après le contournement de l’avertissement de certificat non approuvé du navigateur.

    Browser window showing the app's Index page loaded

Scénarios avec un serveur proxy et un équilibreur de charge

Pour les applications hébergées par HTTP.sys qui interagissent avec les demandes provenant d’Internet ou d’un réseau d’entreprise, une configuration supplémentaire peut être nécessaire en cas d’hébergement derrière des serveurs proxy et des équilibreurs de charge. Pour plus d’informations, consultez l’article Configurer ASP.NET Core pour l’utilisation de serveurs proxy et d’équilibreurs de charge.

Obtenir des informations détaillées sur le minutage avec IHttpSysRequestTimingFeature

IHttpSysRequestTimingFeature fournit des informations détaillées sur le minutage des demandes :

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 récupère l’horodatage pour le type de minutage fourni :

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 indique la durée calendaire entre deux minutages spécifiés :

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

Fonctionnalités HTTP/2 avancées pour prendre en charge gRPC

Des fonctionnalités HTTP/2 supplémentaires dans HTTP.sys prennent en charge gRPC, notamment la prise en charge des codes de fin de réponse et l’envoi de trames de réinitialisation.

Configuration requise pour exécuter gRPC avec HTTP.sys :

  • Windows 11 Build 22000 ou version ultérieure, Windows Server 2022 Build 20348 ou version ultérieure.
  • TLS 1.2 ou connexion ultérieure.

Bandes-annonce

Les codes de fin HTTP sont similaires aux en-têtes HTTP, sauf qu’ils sont envoyés après l’envoi du corps de la réponse. Pour IIS et HTTP.sys, seuls les codes de fin de réponse HTTP/2 sont pris en charge.

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

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

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

Dans l’exemple de code précédent :

  • SupportsTrailers garantit que les codes de fin sont pris en charge pour la réponse.
  • DeclareTrailer ajoute le nom de code de fin donné à l’en-tête de réponse Trailer. La déclaration des codes de fin d’une réponse est facultative, mais recommandée. Si DeclareTrailer est appelé, il doit être avant l’envoi des en-têtes de réponse.
  • AppendTrailer ajoute le code de fin.

Réinitialiser

La réinitialisation permet au serveur de réinitialiser une requête HTTP/2 avec un code d’erreur spécifié. Une requête de réinitialisation est considérée comme abandonnée.

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

Reset dans l’exemple de code précédent spécifie le code d’erreur INTERNAL_ERROR. Pour plus d’informations sur les codes d’erreur HTTP/2, consultez la section du code d’erreur de spécification HTTP/2 HTTP/2.

Traçage

Pour plus d’informations sur l’obtention de traces à partir de HTTP.sys, consultez Scénarios de gestion de HTTP.sys.

Ressources supplémentaires

HTTP.sys est un serveur web pour ASP.NET Core qui s’exécute uniquement sous Windows. HTTP.sys est une alternative à Kestrel serveur et offre certaines fonctionnalités que Kestrel ne fournissent pas.

Important

HTTP.sys est incompatible avec le Module ASP.NET Core et n’est pas utilisable avec IIS ni IIS Express.

HTTP.sys prend en charge les fonctionnalités suivantes :

  • Authentification Windows
  • Partage de port
  • HTTPS avec SNI
  • HTTP/2 sur TLS (Windows 10 et versions ultérieures)
  • Transmission de fichier directe
  • Mise en cache des réponses
  • WebSockets (Windows 8 et versions ultérieures)

Versions de Windows prises en charge :

  • Windows 7 ou version ultérieure
  • Windows Server 2008 R2 ou version ultérieure

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Quand utiliser HTTP.sys

HTTP.sys est utile pour les déploiements lorsque :

  • Il est nécessaire d’exposer directement le serveur à Internet sans passer par IIS.

    HTTP.sys communicates directly with the Internet

  • Un déploiement interne nécessite une fonctionnalité non disponible dans Kestrel. Pour plus d’informations, consultez Kestrel par rapport à HTTP.sys

    HTTP.sys communicates directly with the internal network

HTTP.sys est une technologie aboutie qui assure une protection contre de nombreux types d’attaques et offre la robustesse, la sécurité et l’extensibilité d’un serveur web haut de gamme. Pour sa part, IIS s’exécute en tant qu’écouteur HTTP sur HTTP.sys.

Assistance HTTP/2

HTTP/2 est activé pour les applications ASP.NET Core lorsque les exigences de base suivantes sont remplies :

Si une connexion HTTP/2 est établie, HttpRequest.Protocol retourne HTTP/2.

HTTP/2 est activé par défaut. Si une connexion HTTP/2 n’est pas établie, la connexion revient à HTTP/1.1. Dans une prochaine version de Windows, les indicateurs de configuration HTTP/2 seront disponibles, y compris la possibilité de désactivation de HTTP/2 avec HTTP.sys.

Prise en charge de HTTP/3

HTTP/3 est activé pour les applications ASP.NET Core si les conditions de base suivantes sont remplies :

  • Windows Server 2022/Windows 11 ou version ultérieure
  • Une liaison d’URL https est utilisée.
  • La clé de Registre EnableHttp3 est définie.

Les versions de build Windows 11 précédentes peuvent nécessiter l’utilisation d’une build Windows Insider.

HTTP/3 est découvert comme une mise à niveau à partir de HTTP/1.1 ou HTTP/2 via l’en-tête alt-svc. Cela signifie que la première requête utilise normalement HTTP/1.1 ou HTTP/2 avant de passer à HTTP/3. Http.Sys n’ajoute pas automatiquement l’en-tête alt-svc, il doit être ajouté par l’application. Le code suivant est un exemple d’intergiciel qui ajoute l’en-tête de réponse alt-svc.

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

Placez le code précédent au début du pipeline de requête.

Http.Sys prend également en charge l’envoi d’un message de protocole HTTP/2 AltSvc plutôt qu’un en-tête de réponse pour avertir le client que HTTP/3 est disponible. Consultez la clé de Registre EnableAltSvc. Cela nécessite des liaisons netsh sslcert qui utilisent des noms d’hôte plutôt que des adresses IP.

Authentification en mode noyau avec Kerberos

HTTP.sys délègue l’authentification en mode noyau avec le protocole d’authentification Kerberos. L’authentification en mode utilisateur n’est pas prise en charge avec Kerberos et HTTP.sys. Le compte d’ordinateur doit être utilisé pour déchiffrer le ticket/jeton Kerberos obtenu à partir d’Active Directory et transféré par le client au serveur afin d’authentifier l’utilisateur. Inscrivez le nom de principal du service (SPN) pour l’hôte, et non l’utilisateur de l’application.

Comment utiliser HTTP.sys

Configurer l’application ASP.NET Core afin d’utiliser HTTP.sys

Appelez la méthode d’extension UseHttpSys au moment de générer l’hôte, en spécifiant les options HttpSysOptions nécessaires. L’exemple suivant définit les options sur leurs valeurs par défaut :

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

Le reste de la configuration de HTTP.sys est géré par le biais des paramètres du Registre.

Pour plus d’informations sur les options HTTP.sys, consultez HttpSysOptions.

MaxRequestBodySize

Taille maximale autorisée pour le corps d’une demande, en octets. Lorsque la valeur est null, elle est illimitée. Cette limite est sans effet sur les connexions mises à niveau, qui sont illimitées.

Pour remplacer la limite d’un seul IActionResult dans une application MVC ASP.NET Core, nous vous recommandons d’utiliser l’attribut RequestSizeLimitAttribute sur une méthode d’action :

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Une exception est levée si l’application tente de configurer la limite sur une demande dont l’application a commencé la lecture. La propriété IsReadOnly indique si la propriété MaxRequestBodySize est en lecture seule, et donc s’il est trop tard pour configurer la limite.

Si l’application doit remplacer MaxRequestBodySize par requête, utilisez 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();
    });
}

Si vous utilisez Visual Studio, vérifiez que l’application n’est pas configurée pour exécuter IIS ou IIS Express.

Dans Visual Studio, le profil de démarrage par défaut est destiné à IIS Express. Pour exécuter le projet en tant qu’application console, changez manuellement le profil sélectionné, comme dans la capture d’écran suivante :

Select console app profile

Configurer Windows Server

  1. Identifiez les ports à ouvrir pour l’application et utilisez le pare-feu Windows ou les applets de commande PowerShell New-NetFirewallRule pour ouvrir les ports du pare-feu et ainsi permettre au trafic d’atteindre HTTP.sys. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  2. Lors du déploiement sur une machine virtuelle Azure, ouvrez les ports dans le groupe de sécurité réseau. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  3. Obtenez et installez des certificats X.509, si nécessaire.

    Sous Windows, créez des certificats auto-signés à l’aide de la cmdlet PowerShell New-SelfSignedCertificate. Vous trouverez un exemple non pris en charge sur la page UpdateIISExpressSSLForChrome.ps1.

    Installez des certificats auto-signés ou signés par l’autorité de certification dans le magasin Ordinateur Local>Personnel du serveur.

  4. Si l’application est un déploiement dépendant de .NET Framework, installez .NET Core, .NET Framework ou les deux (si l’application est une application .NET Core ciblant .NET Framework).

    • .NET Core : si l’application nécessite .NET Core, obtenez et exécutez le programme d’installation Runtime .NET Core à partir de téléchargements .NET Core. N’installez pas le Kit SDK complet sur le serveur.
    • .NET Framework : si l’application nécessite .NET Framework, consultez le guide d’installation .NET Framework. Installez la version requise de .NET Framework. Le programme d’installation du .NET Framework le plus récent est disponible depuis la page Téléchargements .NET Core.

    Si l’application est un déploiement autonome, elle inclut le runtime dans son déploiement. Aucune installation de framework n’est requise sur le serveur.

  5. Configurez les ports et les URL de l’application.

    Par défaut, ASP.NET Core est lié à http://localhost:5000. Pour configurer les ports et les préfixes d’URL, il existe plusieurs possibilités :

    • UseUrls
    • Arguments de ligne de commande urls
    • ASPNETCORE_URLS variable d’environnement
    • UrlPrefixes

    L’exemple de code suivant montre comment utiliser UrlPrefixes avec l’adresse IP locale du serveur 10.0.0.4 sur le port 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>();
            });
    

    UrlPrefixes présente l’avantage de générer immédiatement un message d’erreur en cas de préfixe mal formé.

    Les paramètres de UrlPrefixes remplacent les paramètres UseUrls/urls/ASPNETCORE_URLS. Par conséquent, un avantage de UseUrls, urls et de la variable d’environnement ASPNETCORE_URLS est qu’il est plus facile de basculer entre Kestrel et HTTP.sys.

    HTTP.sys utilise les formats de chaîne UrlPrefix de l’API de serveur HTTP.

    Avertissement

    Les liaisons génériques de niveau supérieur (http://*:80/ et http://+:80) ne doivent pas être utilisées. Les liaisons génériques de niveau supérieur créent des failles de sécurité dans l’application. Cela s’applique aux caractères génériques forts et faibles. Utilisez des noms d’hôte ou des adresses IP explicites plutôt que des caractères génériques. Une liaison générique de sous-domaine (par exemple, *.mysub.com) ne constitue pas un risque de sécurité si vous contrôlez le domaine parent en entier (par opposition à *.com, qui est vulnérable). Pour plus d’informations, consultez RFC 9110 : Section 7.2 : Hôte et :authority.

  6. Préenregistrez les préfixes d’URL sur le serveur.

    L’outil intégré pour configurer HTTP.sys est netsh.exe. netsh.exe permet de réserver des préfixes d’URL et d’assigner des certificats X.509. L’outil requiert des privilèges Administrateur.

    Utilisez l’outil netsh.exe pour enregistrer les URL pour l’application :

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL> : URL (Uniform Resource Locator) complet. N’utilisez pas une liaison de caractère générique. Utilisez un nom d’hôte ou une adresse IP locale valide. L’URL doit inclure une barre oblique de fin.
    • <USER> : spécifie le nom de l’utilisateur ou du groupe d’utilisateurs.

    Dans l’exemple suivant, l’adresse IP locale du serveur est 10.0.0.4 :

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

    Lorsqu’une URL est inscrite, l’outil répond avec URL reservation successfully added.

    Pour supprimer une URL inscrite, utilisez la commande delete urlacl :

    netsh http delete urlacl url=<URL>
    
  7. Inscrivez les certificats X.509 sur le serveur.

    Utilisez l’outil netsh.exe pour enregistrer les certificats pour l’application :

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP> : spécifie l’adresse IP locale de la liaison. N’utilisez pas une liaison de caractère générique. Utilisez une adresse IP valide.
    • <PORT> : spécifie le port de la liaison.
    • <THUMBPRINT> : empreinte numérique du certificat X.509.
    • <GUID> : GUID généré par le développeur pour représenter l’application à des fins d’information.

    À titre de référence, stockez le GUID dans l’application en tant que balise de package :

    • Dans Visual Studio :
      • Ouvrez les propriétés du projet de l’application en cliquant avec le bouton droit sur l’application dans l’Explorateur de solutions et en sélectionnant Propriétés.
      • Sélectionnez l’onglet Package.
      • Entrez le GUID que vous avez créé dans le champ Balises.
    • Si vous n’utilisez pas Visual Studio :
      • Ouvrez le chemin d’accès vers le fichier de projet de l’application.

      • Ajoutez une propriété <PackageTags> à un <PropertyGroup> nouveau ou existant avec le GUID que vous avez créé :

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

    Dans l’exemple suivant :

    • L’adresse IP locale du serveur est 10.0.0.4.
    • Un générateur de GUID aléatoire en ligne fournit la valeur appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Lorsqu’un certificat est inscrit, l’outil répond avec SSL Certificate successfully added.

    Pour supprimer l’inscription d’un certificat, utilisez la commande delete sslcert :

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

    Documentation de référence de netsh.exe :

  8. Exécutez l'application.

    Les privilèges administrateur ne sont pas requis pour exécuter l’application lors d’une liaison à localhost à l’aide de HTTP (pas HTTPS) avec un numéro de port supérieur à 1024. Pour les autres configurations (par exemple, l’utilisation d’une adresse IP locale ou la liaison au port 443), exécutez l’application avec des privilèges administrateur.

    L’application répond à l’adresse IP publique du serveur. Dans cet exemple, le serveur est contacté à partir d’Internet à son adresse IP publique 104.214.79.47.

    Un certificat de développement est utilisé dans cet exemple. La page est chargée en toute sécurité après le contournement de l’avertissement de certificat non approuvé du navigateur.

    Browser window showing the app's Index page loaded

Scénarios avec un serveur proxy et un équilibreur de charge

Pour les applications hébergées par HTTP.sys qui interagissent avec les demandes provenant d’Internet ou d’un réseau d’entreprise, une configuration supplémentaire peut être nécessaire en cas d’hébergement derrière des serveurs proxy et des équilibreurs de charge. Pour plus d’informations, consultez l’article Configurer ASP.NET Core pour l’utilisation de serveurs proxy et d’équilibreurs de charge.

Fonctionnalités HTTP/2 avancées pour prendre en charge gRPC

Des fonctionnalités HTTP/2 supplémentaires dans HTTP.sys prennent en charge gRPC, notamment la prise en charge des codes de fin de réponse et l’envoi de trames de réinitialisation.

Configuration requise pour exécuter gRPC avec HTTP.sys :

  • Windows 11 Build 22000 ou version ultérieure, Windows Server 2022 Build 20348 ou version ultérieure.
  • TLS 1.2 ou connexion ultérieure.

Bandes-annonce

Les codes de fin HTTP sont similaires aux en-têtes HTTP, sauf qu’ils sont envoyés après l’envoi du corps de la réponse. Pour IIS et HTTP.sys, seuls les codes de fin de réponse HTTP/2 sont pris en charge.

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

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

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

Dans l’exemple de code précédent :

  • SupportsTrailers garantit que les codes de fin sont pris en charge pour la réponse.
  • DeclareTrailer ajoute le nom de code de fin donné à l’en-tête de réponse Trailer. La déclaration des codes de fin d’une réponse est facultative, mais recommandée. Si DeclareTrailer est appelé, il doit être avant l’envoi des en-têtes de réponse.
  • AppendTrailer ajoute le code de fin.

Réinitialiser

La réinitialisation permet au serveur de réinitialiser une requête HTTP/2 avec un code d’erreur spécifié. Une requête de réinitialisation est considérée comme abandonnée.

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

Reset dans l’exemple de code précédent spécifie le code d’erreur INTERNAL_ERROR. Pour plus d’informations sur les codes d’erreur HTTP/2, consultez la section du code d’erreur de spécification HTTP/2 HTTP/2.

Ressources supplémentaires

HTTP.sys est un serveur web pour ASP.NET Core qui s’exécute uniquement sous Windows. HTTP.sys est une alternative à Kestrel serveur et offre certaines fonctionnalités que Kestrel ne fournissent pas.

Important

HTTP.sys est incompatible avec le Module ASP.NET Core et n’est pas utilisable avec IIS ni IIS Express.

HTTP.sys prend en charge les fonctionnalités suivantes :

  • Authentification Windows
  • Partage de port
  • HTTPS avec SNI
  • HTTP/2 sur TLS (Windows 10 et versions ultérieures)
  • Transmission de fichier directe
  • Mise en cache des réponses
  • WebSockets (Windows 8 et versions ultérieures)

Versions de Windows prises en charge :

  • Windows 7 ou version ultérieure
  • Windows Server 2008 R2 ou version ultérieure

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Quand utiliser HTTP.sys

HTTP.sys est utile pour les déploiements lorsque :

  • Il est nécessaire d’exposer directement le serveur à Internet sans passer par IIS.

    HTTP.sys communicates directly with the Internet

  • Un déploiement interne nécessite une fonctionnalité non disponible dans Kestrel. Pour plus d’informations, consultez Kestrel par rapport à HTTP.sys

    HTTP.sys communicates directly with the internal network

HTTP.sys est une technologie aboutie qui assure une protection contre de nombreux types d’attaques et offre la robustesse, la sécurité et l’extensibilité d’un serveur web haut de gamme. Pour sa part, IIS s’exécute en tant qu’écouteur HTTP sur HTTP.sys.

Assistance HTTP/2

HTTP/2 est activé pour les applications ASP.NET Core si les conditions de base suivantes sont remplies :

Si une connexion HTTP/2 est établie, HttpRequest.Protocol retourne HTTP/2.

HTTP/2 est activé par défaut. Si une connexion HTTP/2 n’est pas établie, la connexion revient à HTTP/1.1. Dans une prochaine version de Windows, les indicateurs de configuration HTTP/2 seront disponibles, y compris la possibilité de désactivation de HTTP/2 avec HTTP.sys.

Authentification en mode noyau avec Kerberos

HTTP.sys délègue l’authentification en mode noyau avec le protocole d’authentification Kerberos. L’authentification en mode utilisateur n’est pas prise en charge avec Kerberos et HTTP.sys. Le compte d’ordinateur doit être utilisé pour déchiffrer le ticket/jeton Kerberos obtenu à partir d’Active Directory et transféré par le client au serveur afin d’authentifier l’utilisateur. Inscrivez le nom de principal du service (SPN) pour l’hôte, et non l’utilisateur de l’application.

Comment utiliser HTTP.sys

Configurer l’application ASP.NET Core afin d’utiliser HTTP.sys

Appelez la méthode d’extension UseHttpSys au moment de générer l’hôte, en spécifiant les options HttpSysOptions nécessaires. L’exemple suivant définit les options sur leurs valeurs par défaut :

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

Le reste de la configuration de HTTP.sys est géré par le biais des paramètres du Registre.

Options HTTP.sys

Propriété Description Default
AllowSynchronousIO Contrôle si l’entrée/sortie synchrone est autorisée pour le HttpContext.Request.Body et le HttpContext.Response.Body. false
Authentication.AllowAnonymous Autorise les requêtes anonymes. true
Authentication.Schemes Spécifie les schémas d’authentification autorisés. Peut être modifié à tout moment avant la suppression de l’écouteur. Les valeurs sont fournies par l’enum AuthenticationSchemes : Basic, Kerberos, Negotiate, None et NTLM. None
EnableResponseCaching Tente la mise en cache en mode noyau pour les réponses comportant un en-tête compatible. La réponse peut ne pas inclure d’en-tête Set-Cookie, Vary ou Pragma. Elle doit comporter un en-tête Cache-Controlpublic et soit une valeur shared-max-age ou max-age, soit un en-tête Expires. true
Http503Verbosity Comportement HTTP.sys lors du rejet des requêtes en raison de conditions de limitation. Http503VerbosityLevel.
De base
MaxAccepts Nombre maximal d'acceptations simultanées. 5 × environnement .
ProcessorCount
MaxConnections Nombre maximum de connexions simultanées à accepter. Utilisez -1 pour signifier l’infini, et null pour utiliser le paramètre du Registre qui s’applique à l’ordinateur dans son ensemble. null
(paramètre à l’échelle
de l’ordinateur)
MaxRequestBodySize Consultez la section MaxRequestBodySize. 30 000 000 octets
(env. 28,6 Mo)
RequestQueueLimit Nombre maximal de demandes pouvant être placées en file d'attente. 1 000
RequestQueueMode Cela indique si le serveur est responsable de la création et de la configuration de la file d’attente de requêtes, ou s’il doit s’attacher à une file d’attente existante.
La plupart des options de configuration existantes ne s’appliquent pas lors de l’attachement à une file d’attente existante.
RequestQueueMode.Create
RequestQueueName Nom de la file d’attente de requêtes HTTP.sys. null (File d’attente anonyme)
ThrowWriteExceptions Indique si les écritures dans le corps de la réponse qui échouent en raison d’une déconnexion du client doivent lever des exceptions ou se terminer normalement. false
(se terminer normalement)
Timeouts Expose la configuration TimeoutManager de HTTP.sys, également paramétrable dans le Registre. Suivez les liens de l’API pour en savoir plus sur chaque paramètre, y compris les valeurs par défaut :
UrlPrefixes Spécifiez UrlPrefixCollection à inscrire auprès de HTTP.sys. Le plus utile est UrlPrefixCollection.Add, qui est utilisé pour ajouter un préfixe à la collection. Ces choix peuvent être modifiés à tout moment avant la suppression de l’écouteur.

MaxRequestBodySize

Taille maximale autorisée pour le corps d’une demande, en octets. Lorsque la valeur est null, elle est illimitée. Cette limite est sans effet sur les connexions mises à niveau, qui sont illimitées.

Pour remplacer la limite d’un seul IActionResult dans une application MVC ASP.NET Core, nous vous recommandons d’utiliser l’attribut RequestSizeLimitAttribute sur une méthode d’action :

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Une exception est levée si l’application tente de configurer la limite sur une demande dont l’application a commencé la lecture. La propriété IsReadOnly indique si la propriété MaxRequestBodySize est en lecture seule, et donc s’il est trop tard pour configurer la limite.

Si l’application doit remplacer MaxRequestBodySize par requête, utilisez 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();
    });
}

Si vous utilisez Visual Studio, vérifiez que l’application n’est pas configurée pour exécuter IIS ou IIS Express.

Dans Visual Studio, le profil de démarrage par défaut est destiné à IIS Express. Pour exécuter le projet en tant qu’application console, changez manuellement le profil sélectionné, comme dans la capture d’écran suivante :

Select console app profile

Configurer Windows Server

  1. Identifiez les ports à ouvrir pour l’application et utilisez le pare-feu Windows ou les applets de commande PowerShell New-NetFirewallRule pour ouvrir les ports du pare-feu et ainsi permettre au trafic d’atteindre HTTP.sys. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  2. Lors du déploiement sur une machine virtuelle Azure, ouvrez les ports dans le groupe de sécurité réseau. Dans les commandes et la configuration de l’application suivantes, le port 443 est utilisé.

  3. Obtenez et installez des certificats X.509, si nécessaire.

    Sous Windows, créez des certificats auto-signés à l’aide de la cmdlet PowerShell New-SelfSignedCertificate. Vous trouverez un exemple non pris en charge sur la page UpdateIISExpressSSLForChrome.ps1.

    Installez des certificats auto-signés ou signés par l’autorité de certification dans le magasin Ordinateur Local>Personnel du serveur.

  4. Si l’application est un déploiement dépendant de .NET Framework, installez .NET Core, .NET Framework ou les deux (si l’application est une application .NET Core ciblant .NET Framework).

    • .NET Core : si l’application nécessite .NET Core, obtenez et exécutez le programme d’installation Runtime .NET Core à partir de téléchargements .NET Core. N’installez pas le Kit SDK complet sur le serveur.
    • .NET Framework : si l’application nécessite .NET Framework, consultez le guide d’installation .NET Framework. Installez la version requise de .NET Framework. Le programme d’installation du .NET Framework le plus récent est disponible depuis la page Téléchargements .NET Core.

    Si l’application est un déploiement autonome, elle inclut le runtime dans son déploiement. Aucune installation de framework n’est requise sur le serveur.

  5. Configurez les ports et les URL de l’application.

    Par défaut, ASP.NET Core est lié à http://localhost:5000. Pour configurer les ports et les préfixes d’URL, il existe plusieurs possibilités :

    • UseUrls
    • Arguments de ligne de commande urls
    • ASPNETCORE_URLS variable d’environnement
    • UrlPrefixes

    L’exemple de code suivant montre comment utiliser UrlPrefixes avec l’adresse IP locale du serveur 10.0.0.4 sur le port 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>();
            });
    

    UrlPrefixes présente l’avantage de générer immédiatement un message d’erreur en cas de préfixe mal formé.

    Les paramètres de UrlPrefixes remplacent les paramètres UseUrls/urls/ASPNETCORE_URLS. Par conséquent, un avantage de UseUrls, urls et de la variable d’environnement ASPNETCORE_URLS est qu’il est plus facile de basculer entre Kestrel et HTTP.sys.

    HTTP.sys utilise les formats de chaîne UrlPrefix de l’API de serveur HTTP.

    Avertissement

    Les liaisons génériques de niveau supérieur (http://*:80/ et http://+:80) ne doivent pas être utilisées. Les liaisons génériques de niveau supérieur créent des failles de sécurité dans l’application. Cela s’applique aux caractères génériques forts et faibles. Utilisez des noms d’hôte ou des adresses IP explicites plutôt que des caractères génériques. Une liaison générique de sous-domaine (par exemple, *.mysub.com) ne constitue pas un risque de sécurité si vous contrôlez le domaine parent en entier (par opposition à *.com, qui est vulnérable). Pour plus d’informations, consultez RFC 9110 : Section 7.2 : Hôte et :authority.

  6. Préenregistrez les préfixes d’URL sur le serveur.

    L’outil intégré pour configurer HTTP.sys est netsh.exe. netsh.exe permet de réserver des préfixes d’URL et d’assigner des certificats X.509. L’outil requiert des privilèges Administrateur.

    Utilisez l’outil netsh.exe pour enregistrer les URL pour l’application :

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL> : URL (Uniform Resource Locator) complet. N’utilisez pas une liaison de caractère générique. Utilisez un nom d’hôte ou une adresse IP locale valide. L’URL doit inclure une barre oblique de fin.
    • <USER> : spécifie le nom de l’utilisateur ou du groupe d’utilisateurs.

    Dans l’exemple suivant, l’adresse IP locale du serveur est 10.0.0.4 :

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

    Lorsqu’une URL est inscrite, l’outil répond avec URL reservation successfully added.

    Pour supprimer une URL inscrite, utilisez la commande delete urlacl :

    netsh http delete urlacl url=<URL>
    
  7. Inscrivez les certificats X.509 sur le serveur.

    Utilisez l’outil netsh.exe pour enregistrer les certificats pour l’application :

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP> : spécifie l’adresse IP locale de la liaison. N’utilisez pas une liaison de caractère générique. Utilisez une adresse IP valide.
    • <PORT> : spécifie le port de la liaison.
    • <THUMBPRINT> : empreinte numérique du certificat X.509.
    • <GUID> : GUID généré par le développeur pour représenter l’application à des fins d’information.

    À titre de référence, stockez le GUID dans l’application en tant que balise de package :

    • Dans Visual Studio :
      • Ouvrez les propriétés du projet de l’application en cliquant avec le bouton droit sur l’application dans l’Explorateur de solutions et en sélectionnant Propriétés.
      • Sélectionnez l’onglet Package.
      • Entrez le GUID que vous avez créé dans le champ Balises.
    • Si vous n’utilisez pas Visual Studio :
      • Ouvrez le chemin d’accès vers le fichier de projet de l’application.

      • Ajoutez une propriété <PackageTags> à un <PropertyGroup> nouveau ou existant avec le GUID que vous avez créé :

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

    Dans l’exemple suivant :

    • L’adresse IP locale du serveur est 10.0.0.4.
    • Un générateur de GUID aléatoire en ligne fournit la valeur appid.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    Lorsqu’un certificat est inscrit, l’outil répond avec SSL Certificate successfully added.

    Pour supprimer l’inscription d’un certificat, utilisez la commande delete sslcert :

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

    Documentation de référence de netsh.exe :

  8. Exécutez l'application.

    Les privilèges administrateur ne sont pas requis pour exécuter l’application lors d’une liaison à localhost à l’aide de HTTP (pas HTTPS) avec un numéro de port supérieur à 1024. Pour les autres configurations (par exemple, l’utilisation d’une adresse IP locale ou la liaison au port 443), exécutez l’application avec des privilèges administrateur.

    L’application répond à l’adresse IP publique du serveur. Dans cet exemple, le serveur est contacté à partir d’Internet à son adresse IP publique 104.214.79.47.

    Un certificat de développement est utilisé dans cet exemple. La page est chargée en toute sécurité après le contournement de l’avertissement de certificat non approuvé du navigateur.

    Browser window showing the app's Index page loaded

Scénarios avec un serveur proxy et un équilibreur de charge

Pour les applications hébergées par HTTP.sys qui interagissent avec les demandes provenant d’Internet ou d’un réseau d’entreprise, une configuration supplémentaire peut être nécessaire en cas d’hébergement derrière des serveurs proxy et des équilibreurs de charge. Pour plus d’informations, consultez l’article Configurer ASP.NET Core pour l’utilisation de serveurs proxy et d’équilibreurs de charge.

Fonctionnalités HTTP/2 avancées pour prendre en charge gRPC

Des fonctionnalités HTTP/2 supplémentaires dans HTTP.sys prennent en charge gRPC, notamment la prise en charge des codes de fin de réponse et l’envoi de trames de réinitialisation.

Configuration requise pour exécuter gRPC avec HTTP.sys :

  • Windows 10, build du système d’exploitation 19041.508 ou version ultérieure
  • TLS 1.2 ou connexion ultérieure

Bandes-annonce

Les codes de fin HTTP sont similaires aux en-têtes HTTP, sauf qu’ils sont envoyés après l’envoi du corps de la réponse. Pour IIS et HTTP.sys, seuls les codes de fin de réponse HTTP/2 sont pris en charge.

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

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

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

Dans l’exemple de code précédent :

  • SupportsTrailers garantit que les codes de fin sont pris en charge pour la réponse.
  • DeclareTrailer ajoute le nom de code de fin donné à l’en-tête de réponse Trailer. La déclaration des codes de fin d’une réponse est facultative, mais recommandée. Si DeclareTrailer est appelé, il doit être avant l’envoi des en-têtes de réponse.
  • AppendTrailer ajoute le code de fin.

Réinitialiser

La réinitialisation permet au serveur de réinitialiser une requête HTTP/2 avec un code d’erreur spécifié. Une requête de réinitialisation est considérée comme abandonnée.

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

Reset dans l’exemple de code précédent spécifie le code d’erreur INTERNAL_ERROR. Pour plus d’informations sur les codes d’erreur HTTP/2, consultez la section du code d’erreur de spécification HTTP/2 HTTP/2.

Ressources supplémentaires