Vous devez couper TLS 1.3 sur IIS (Windows Server 2022) car l’authentification par certificat client dysfonctionne ? Voici une procédure fiable, scriptable (PowerShell/GPO), ses impacts, les vérifications et les alternatives par application (Kestrel).
Problème
« Windows 2022 : comment désactiver TLS 1.3 sur un site IIS par script (PowerShell, ligne de commande, etc.) ? Ce nouveau protocole provoque des problèmes avec l’authentification par certificat client. »
Réponse courte
On ne peut pas désactiver TLS 1.3 “par site” dans IIS. La négociation TLS est assurée par Schannel, le fournisseur TLS du système. Toute modification s’applique globalement à l’OS et donc à toutes les applications (IIS, WinHTTP, .NET Framework, etc.). La solution consiste à désactiver TLS 1.3 côté serveur au niveau du Registre, puis à redémarrer pour prise d’effet.
Pourquoi TLS 1.3 peut casser l’authentification par certificat client (mTLS)
Dans TLS 1.2, la demande de certificat client intervient durant la négociation initiale et peut impliquer une renégociation. TLS 1.3 supprime la renégociation et déplace ce mécanisme via la post‑handshake authentication (PHA). Or, selon les piles TLS des clients ou de certains middleboxes (proxy SSL, IDS/IPS, balanceurs), cette différence peut provoquer :
- une incapacité du client à fournir un certificat au bon moment,
- des erreurs de type handshake failure, no_certificate ou des réinitialisations de connexion,
- des incompatibilités avec des équipements ou bibliothèques n’implémentant pas la PHA correctement.
Quand vous devez restaurer rapidement la compatibilité mTLS pour un parc hétérogène, l’option la plus pragmatique consiste à revenir à TLS 1.2 sur le serveur, le temps de corriger/mettre à jour les clients.
Ce qu’on peut (et ne peut pas) faire avec IIS + Schannel
- Pas de réglage par site : ni dans le site binding, ni via un module IIS. Les protocoles activés/désactivés se règlent au niveau OS.
- Réglage global : via le Registre Windows, sous la ruche
SCHANNEL\Protocols
. - Alternative applicative : si vous hébergez des apps .NET sur Kestrel (derrière IIS en reverse proxy), vous pouvez brider les protocoles par application.
Solution opérationnelle (Registre + PowerShell)
Le bloc suivant désactive complètement TLS 1.3 côté serveur (Server) sur Windows Server 2022. Exécutez‑le en administrateur.
Script PowerShell prêt à l’emploi
# Exécuter en tant qu’administrateur
$base = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
# Crée les clés nécessaires si elles n'existent pas
New-Item -Path $base -Name 'TLS 1.3' -Force | Out-Null
New-Item -Path "$base\TLS 1.3" -Name Server -Force | Out-Null
# Désactive TLS 1.3 côté serveur
New-ItemProperty -Path "$base\TLS 1.3\Server" -Name 'Enabled' -PropertyType DWord -Value 0 -Force | Out-Null
New-ItemProperty -Path "$base\TLS 1.3\Server" -Name 'DisabledByDefault' -PropertyType DWord -Value 1 -Force | Out-Null
Write-Host "TLS 1.3 (Server) désactivé dans Schannel. Redémarrez le serveur pour appliquer."
Exécution automatisée : exportez ce code dans Disable-TLS13.ps1
et lancez :
powershell -ExecutionPolicy Bypass -File .\Disable-TLS13.ps1
Retour arrière
Deux options : supprimer les valeurs ou les réactiver.
# Option A : suppression des valeurs
Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'Enabled' -ErrorAction SilentlyContinue
Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'DisabledByDefault' -ErrorAction SilentlyContinue
# Option B : réactivation explicite
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'Enabled' -PropertyType DWord -Value 1 -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'DisabledByDefault' -PropertyType DWord -Value 0 -Force | Out-Null
Variante ligne de commande (CMD)
Si vous ne pouvez pas utiliser PowerShell (décalage de politique d’exécution, bastion très restrictif, etc.), voici l’équivalent reg.exe
:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server" /v Enabled /t REG_DWORD /d 0 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server" /v DisabledByDefault /t REG_DWORD /d 1 /f
Modèle .reg (GPO Préférences ou import manuel)
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
Redémarrage : que faut‑il relancer exactement ?
Les changements Schannel sont lus très tôt par le système. En pratique, le moyen le plus fiable est de redémarrer le serveur dans une fenêtre de maintenance. Certaines équipes observent une prise d’effet après redémarrage des services HTTP/IIS, mais ceci n’est pas garanti.
- Recommandé : reboot complet.
- Au minimum : tenter
iisreset
puis (si possible) unRestart-Service HTTP
. Selon la charge et les dépendances,HTTP
(http.sys) peut refuser l’arrêt ; ne forcez pas au risque d’impacter d’autres rôles.
# Redémarrage IIS (sans garantie pour Schannel)
iisreset
# Tentative de redémarrage du service HTTP (peut échouer selon dépendances)
Try { Restart-Service -Name 'HTTP' -Force -ErrorAction Stop } Catch { Write-Warning $_.Exception.Message }
Vérifier que TLS 1.3 n’est plus proposé
Réalisez une double vérification : depuis le serveur (vue “locale”) et depuis un client (vue “réseau”).
Depuis le serveur
[Net.ServicePointManager]::SecurityProtocol
La sortie doit lister Tls, Tls11, Tls12
uniquement (selon votre configuration locale, TLS 1.0/1.1 peuvent déjà être désactivés par ailleurs). L’absence de Tls13
confirme qu’il n’est pas proposé par la pile .NET/Schannel au processus courant.
Depuis un client
- nmap :
nmap --script ssl-enum-ciphers -p 443 <nom_ou_ip_du_serveur>
Le rapport ne doit plus afficher de section TLSv1.3.
- OpenSSL :
# Tente une connexion explicite en TLS 1.3 : doit échouer
openssl s_client -tls1_3 -connect <serveur>:443
# Tente une connexion en TLS 1.2 : doit réussir
openssl s_client -tls1_2 -connect :443
Résumé décisionnel
Approche | Portée | Avantages | Limites | Quand l’utiliser |
---|---|---|---|---|
Désactiver TLS 1.3 via Schannel (Registre) | Globale (OS) | Rapide, scriptable, immédiat pour toutes les apps | Impacte tout l’hôte, perte du 0‑RTT et des gains de perf TLS 1.3 | Remédiation urgente d’un incident mTLS ou compat client |
Limiter par application (Kestrel) | Par app | Granularité fine, coexistence TLS 1.2/1.3 selon besoin | Ne s’applique pas au moteur IIS natif | Apps .NET derrières IIS/Reverse proxy |
Automatisation à l’échelle (GPO, Ansible, Chef)
- GPO Préférences > Registre : poussez les deux valeurs
Enabled=0
etDisabledByDefault=1
sous...Schannel\Protocols\TLS 1.3\Server
. - Ansible : module
win_regedit
avecstate: present
pour chaque valeur. - Chef : ressource
windows_registry
déclarant les mêmes chemins/valeurs.
Ajoutez systématiquement une étape de compliance : un job planifié qui scanne les hôtes appliquant la GPO mais qui n’ont pas encore redémarré.
Bonnes pratiques si vous retombez sur TLS 1.2
Revenir à TLS 1.2 n’implique pas d’accepter des suites obsolètes. Windows Server 2022 propose des suites modernes par défaut ; vérifiez néanmoins que vous n’avez pas “traîné” d’anciens réglages. Recommandations :
- Activer uniquement des suites AES‑GCM basées sur ECDHE : par ex.
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
etTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
. - Désactiver RC4, 3DES, AES‑CBC, suites statiques non‑PFS.
- Certificats serveur : préférez RSA 2048/3072 ou ECDSA (P‑256) selon compatibilité client.
Si vous avez déjà personnalisé l’ordre des suites via le Registre (Cryptography\Configuration\SSL\00010002
), revérifiez la liste : toute suite non GCM devrait être écartée.
Alternative par application : Kestrel derrière IIS
Pour une application ASP.NET Core hébergée derrière IIS (reverse proxy), vous pouvez imposer TLS 1.2 au seul processus Kestrel, sans toucher aux autres sites.
appsettings.json
{
"Kestrel": {
"Endpoints": {
"Https": {
"Protocols": "Tls12"
}
}
}
}
Configuration C# (si vous préférez le code)
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(https =>
{
https.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
});
});
var app = builder.Build();
app.MapGet("/", () => "Hello");
app.Run();
Limite : cette méthode ne concerne que l’application Kestrel. Elle ne permet pas de forcer les protocoles du moteur IIS natif ni des autres apps hébergées sur le même serveur.
Contrôles de santé post‑changement
Objectif | Commande | Résultat attendu |
---|---|---|
Vérifier la pile .NET locale | [Net.ServicePointManager]::SecurityProtocol | Liste sans Tls13 |
Scanner l’offre de protocoles | nmap --script ssl-enum-ciphers -p 443 <serveur> | Pas de bloc TLSv1.3 |
Test mTLS depuis un client | curl --cert client.pfx:m0tDePasse https://<serveur>/ | Réponse HTTP 200 (ou 401/403 selon votre logique), pas d’échec TLS |
Conséquences techniques à connaître
- Globale : toutes les apps sur l’hôte négocieront au maximum TLS 1.2.
- Expérience utilisateur : les navigateurs modernes retombent silencieusement en TLS 1.2, sans alerte de sécurité.
- Performance : légère hausse de latence (handshake à 2 allers‑retours, pas de 0‑RTT).
- Journalisation : pensez à tracer la version TLS côté proxy/load balancer ou dans vos logs pour objectiver la bascule.
FAQ
Peut‑on forcer TLS 1.3 pour quelques sites et le désactiver pour d’autres ?
Non avec IIS natif. Schannel n’expose pas un réglage par site binding. C’est tout le serveur ou rien.
Dois‑je aussi désactiver TLS 1.3 côté “Client” dans Schannel ?
Uniquement si l’hôte agit comme client TLS (ex. appels sortants via WinHTTP/WinINET) et que vous voulez garantir TLS 1.2 pour ces appels. Dans ce cas, dupliquez les valeurs sous ...Protocols\TLS 1.3\Client
.
Est‑ce que iisreset
suffit ?
Parfois oui, souvent non. Les modifications de protocole TLS sont chargées tôt ; un redémarrage complet reste la méthode la plus sûre.
Pourquoi mon scanner voit encore TLS 1.3 après la modif ?
- Vous scannez peut‑être un reverse proxy/WAF/ALB en amont qui, lui, continue d’offrir TLS 1.3.
- L’hôte n’a pas redémarré depuis l’application de la GPO.
- Vous testez une autre IP/VM que celle où la modification a été faite.
Quels risques de sécurité en revenant à TLS 1.2 ?
TLS 1.2 reste sûr si vous limitez les suites à ECDHE + AES‑GCM et si vous désactivez TLS 1.0/1.1. Vous perdez le 0‑RTT et quelques optimisations, mais pas la confidentialité ni l’intégrité.
Checklist exécutable
- Planifier un créneau de maintenance.
- Appliquer le script PowerShell (ou GPO/Ansible/Chef) qui écrit :
HKLM\...\SCHANNEL\Protocols\TLS 1.3\Server\Enabled=0
etDisabledByDefault=1
. - Redémarrer le serveur.
- Contrôler localement
ServicePointManager.SecurityProtocol
. - Scanner depuis un client (
nmap
,openssl
). - Valider la chaîne mTLS (certificat client) sur un chemin applicatif.
- Surveiller la latence et les métriques d’erreurs HTTP/TLS les 24 heures suivantes.
Réponse initiale & valeur ajoutée de ce guide
La réponse initiale renvoyait simplement vers un forum généraliste sans fournir de solution. Ce guide condense tout ce qu’il faut pour agir vite : le pourquoi (différences TLS 1.2/1.3 côté mTLS), le comment (scripts prêts à l’emploi), le contrôle (vérifications concrètes) et les alternatives (Kestrel par application).
Annexe : script complet de durcissement TLS 1.2 (optionnel)
Si votre politique impose TLS 1.2, vous pouvez, en complément, désactiver TLS 1.0/1.1 et vérifier quelques suites faibles. Adaptez aux exigences de votre organisation.
# Désactiver TLS 1.0 et 1.1 côté serveur (optionnel mais recommandé)
$proto = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
foreach ($v in @('TLS 1.0','TLS 1.1')) {
New-Item -Path (Join-Path $proto $v) -ErrorAction SilentlyContinue | Out-Null
New-Item -Path (Join-Path $proto "$v\Server") -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -Path (Join-Path $proto "$v\Server") -Name 'Enabled' -PropertyType DWord -Value 0 -Force | Out-Null
New-ItemProperty -Path (Join-Path $proto "$v\Server") -Name 'DisabledByDefault' -PropertyType DWord -Value 1 -Force | Out-Null
}
# Vérifier l'état résultant
'Résumé Schannel (Server) :'
Get-ChildItem -Path "$proto" |
Where-Object { $*.Name -match 'TLS' } |
ForEach-Object {
$serverKey = Join-Path $*.PsPath 'Server'
if (Test-Path $serverKey) {
$p = Get-ItemProperty -Path $serverKey -ErrorAction SilentlyContinue
[PSCustomObject]@{
Protocol = Split-Path $_.Name -Leaf
Enabled = $p.Enabled
DisabledByDefault = $p.DisabledByDefault
}
}
} | Format-Table -AutoSize
Conclusion
Pour éliminer les erreurs mTLS liées à TLS 1.3 sur Windows Server 2022/IIS, la voie fiable est de désactiver TLS 1.3 globalement dans Schannel, redémarrer, puis vérifier côté serveur et côté client. Si vous avez besoin de granularité, adoptez l’approche Kestrel pour les seules applications concernées. Cette stratégie vous rend la main immédiatement, tout en vous laissant la possibilité de réintroduire TLS 1.3 une fois votre écosystème client pleinement compatible.
Fiches rapides
Bloc PowerShell minimal
$base = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
New-Item -Path $base -Name 'TLS 1.3' -Force | Out-Null
New-Item -Path "$base\TLS 1.3" -Name Server -Force | Out-Null
New-ItemProperty -Path "$base\TLS 1.3\Server" -Name 'Enabled' -PropertyType DWord -Value 0 -Force | Out-Null
New-ItemProperty -Path "$base\TLS 1.3\Server" -Name 'DisabledByDefault' -PropertyType DWord -Value 1 -Force | Out-Null
Commandes de vérification
# Local
[Net.ServicePointManager]::SecurityProtocol
# Distant
nmap --script ssl-enum-ciphers -p 443
openssl s_client -tls1_3 -connect :443
openssl s_client -tls1_2 -connect :443
Alternative Kestrel (appsettings.json)
{
"Kestrel": {
"Endpoints": {
"Https": {
"Protocols": "Tls12"
}
}
}
}
Synthèse
- Pas de désactivation par site IIS : c’est tout le serveur ou rien.
- Méthode recommandée : Registre Schannel + redémarrage.
- Automatisation : script PowerShell, GPO, outils de config management.
- Vérifications : commandes locales et scans réseau pour confirmer l’absence de TLS 1.3.