Votre ferme RDS affiche des alertes de sécurité liées aux certificats ? Ce guide pas‑à‑pas explique pourquoi le message apparaît (SAN, redirections, auto‑signés), comment affecter et imposer le bon certificat à chaque rôle (Gateway, Web, Broker, Session Host) et comment valider la correction côté client et serveur.
Vue d’ensemble de la situation
Dans une ferme Remote Desktop Services (RDS) répartie sur trois serveurs, les clients reçoivent systématiquement un avertissement :
- Un certificat auto‑signé est présenté, ou bien le nom déclaré par le certificat ne correspond pas au FQDN réellement utilisé.
- Pourtant, le certificat importé contient plusieurs SAN :
server1.contoso.com
,*.contoso.com
,*.subdomain.contoso.com
, etc. - Malgré l’import du
.pfx
via Server Manager et dans le magasin Ordinateur local \ Personnel, les hôtes RDS continuent à présenter un certificat non valide.
La cause la plus fréquente : le bon certificat existe quelque part sur les serveurs, mais il n’est pas lié au bon rôle, pas séléctionné par RDP‑Tcp, ou bien le nom réellement composé par le client ne figure pas dans les SAN. À cela s’ajoutent des certificats auto‑signés résiduels que Windows choisit parfois “par défaut”.
Ce qui se passe réellement pendant une connexion RDP
Comprendre le cheminement aide à corriger rapidement :
- Un utilisateur lance
mstsc
versfarm.subdomain.contoso.com
(ou clique un fichier.rdp
). - Le client contacte le RD Gateway (si configuré) en HTTPS :443 ; le nom appelé doit correspondre à un SAN du certificat Gateway.
- Le RD Connection Broker redirige alors la session vers un RD Session Host. Le client établit une seconde négociation TLS en RDP :3389 avec cet hôte et vérifie de nouveau le nom : s’il ne matche pas un SAN du certificat présenté par le Session Host, un avertissement s’affiche.
Conséquence : il ne suffit pas d’installer un PFX « quelque part ». Il faut lier le certificat à chaque rôle et forcer le Session Host à l’utiliser. Enfin, il faut que le FQDN que voit le client soit présent dans les SAN (ou couvert par un wildcard valide).
Plan de remédiation en 6 étapes (résumé opérationnel)
Étape | Action | Détails pratiques |
---|---|---|
1. Affecter le certificat à chaque rôle RDS | Server Manager → Remote Desktop Services → Overview → Deployment Properties → Certificates | Importer le même .pfx pour RD Connection Broker (Publishing + SSO), RD Web Access et RD Gateway, puis redémarrer les services concernés. |
2. Forcer l’usage du certificat sur chaque Session Host | a) Importer le PFX dans Ordinateur\Personnel (avec clé privée) ; b) Copier l’empreinte SHA‑1 (sans espaces, sans caractères invisibles) ; c) Écrire l’empreinte dans RDP‑Tcp\SSLCertificateSHA1Hash ;d) Redémarrer TermService (ou le serveur). | Empêche Windows de générer / présenter un auto‑signé. |
3. Vérifier l’adéquation Nom ↔ Certificat | Le FQDN réellement composé doit exister dans les SAN, ou être couvert par un wildcard. | Ex. farm.subdomain.contoso.com doit correspondre à *.subdomain.contoso.com ou être listé explicitement. |
4. Supprimer les auto‑signés résiduels | certlm.msc → Ordinateur local \ Personnel et Remote Desktop → supprimer « RDP Self‑Signed … » | Évite qu’un certificat interne soit choisi par erreur. |
5. Propager automatiquement le certificat | PowerShell RDS : Set‑RDCertificate ; GPO : Configuration ordinateur → Paramètres Windows → Paramètres de sécurité → Clés publiques | Assure la cohérence quand de nouveaux hôtes rejoignent la ferme. |
6. Contrôles supplémentaires | Chaîne complète, EKU = Server Authentication, RSA ≥ 2048 / SHA‑256, clients RDP à jour | Certains anciens clients gèrent mal les SAN multiples et les jokers. |
Cartographie des rôles RDS et de leur certificat
Rôle | Port / protocole | Où est lié le certificat ? | Noms attendus (SAN) |
---|---|---|---|
RD Gateway | 443 / TLS (HTTP.SYS) | Assistant RDS (Deployment Properties) alimente la liaison HTTP.SYS. Vérifier avec netsh http show sslcert . | Nom public d’accès (ex. rdgw.contoso.com ) |
RD Web Access | 443 / IIS | Assistant RDS ou Bindings IIS. Le même PFX peut être réutilisé. | URL d’accès Web (ex. rdweb.contoso.com ) |
RD Connection Broker | 443 / service Broker (Publishing + SSO) | Set‑RDCertificate -Role RDPublishing/RDRedirector cible le Broker. | Nom d’équilibrage/HA (ex. rds.contoso.com ) |
RD Session Host | 3389 / TLS (RDP‑Tcp) | Clé de registre SSLCertificateSHA1Hash (ou WMI) pour imposer le certificat à RDP‑Tcp. | Nom vers lequel le client est redirigé (ex. rdsh01.contoso.com ), ou un wildcard couvrant le niveau. |
Étape 1 — Affecter le certificat aux rôles RDS via l’assistant (et vérifier)
Dans Server Manager → Remote Desktop Services → Overview → Deployment Properties → Certificates :
- Sélectionnez chaque rôle (RD Web Access, RD Gateway, RD Connection Broker – Publishing, RD Connection Broker – SSO).
- Choisissez « Select an existing certificate », importez le même
.pfx
(avec sa clé privée), entrez le mot de passe, cochez « Allow the certificate to be added to the certificate store ». - Appliquez, puis redémarrez TS Gateway / IIS si demandé.
Équivalent PowerShell (utile pour l’automatisation et la répétabilité) :
Import-Module RemoteDesktop
# Paramètres
$PfxPath = 'C:\Secure\rds-unifie.pfx'
$PfxPwd = Read-Host 'Mot de passe du PFX' -AsSecureString
$CB = 'rdcb.contoso.com' # FQDN du Broker (HA si applicable)
# RD Web Access
Set-RDCertificate -Role RDWebAccess -ImportPath $PfxPath -Password $PfxPwd -Force
# RD Gateway
Set-RDCertificate -Role RDGateway -ImportPath $PfxPath -Password $PfxPwd -Force
# RD Connection Broker (Publishing + Redirector)
Set-RDCertificate -Role RDPublishing -ConnectionBroker $CB -ImportPath $PfxPath -Password $PfxPwd -Force
Set-RDCertificate -Role RDRedirector -ConnectionBroker $CB -ImportPath $PfxPath -Password $PfxPwd -Force
# Vérification
Get-RDCertificate | Format-Table Role, Subject, Thumbprint, ExpirationDate
Étape 2 — Imposer le certificat côté RD Session Host (éviter l’auto‑signé)
La liaison du certificat à RDP‑Tcp se fait au niveau de chaque hôte. Méthode recommandée (WMI) :
# 1) Récupérer l'empreinte du bon certificat (sans espaces)
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {
$_.HasPrivateKey -and $_.FriendlyName -like '*RDS*'
} | Sort-Object NotAfter -Descending | Select-Object -First 1
$thumb = ($cert.Thumbprint).Replace(' ', '')
# 2) Appliquer à RDP-Tcp via WMI (évite les erreurs de type REG_BINARY)
$ts = Get-WmiObject -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'"
$null = $ts.SetSSLCertificateSHA1Hash($thumb)
# 3) Redémarrer le service RDP (interrompt les connexions en cours)
Restart-Service TermService -Force
Déploiement en masse sur tous les Session Hosts :
$Hosts = @('rdsh01.contoso.com','rdsh02.contoso.com','rdsh03.contoso.com')
Invoke-Command -ComputerName $Hosts -ScriptBlock {
param($Thumb)
$ts = Get-WmiObject -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'"
$null = $ts.SetSSLCertificateSHA1Hash($Thumb)
Restart-Service TermService -Force
} -ArgumentList $thumb
Pièges courants : l’empreinte SHA‑1 copiée depuis la console contient parfois des caractères invisibles (LRM/RLM). Passez‑la dans $thumb.Replace(' ', '')
et préférez la méthode WMI plutôt que la clé de registre manuelle SSLCertificateSHA1Hash
pour éviter les erreurs binaires.
Étape 3 — Faire correspondre les noms (SAN) au FQDN réellement composé
- Le client compare le nom demandé (ce qui est saisi, ou le
full address:s:
du.rdp
) avec les SAN du certificat reçu. - Les wildcards ne couvrent qu’un niveau :
*.contoso.com
couvrehost.contoso.com
, mais pasfarm.sub.contoso.com
. Pour ce dernier, utiliser*.sub.contoso.com
ou lister le FQDN exact. - En présence de Broker HA, le nom d’équilibrage (ex.
rds.contoso.com
) doit être dans les SAN, tout comme les FQDN vers lesquels le client est redirigé (ex.rdsh01.contoso.com
), ou bien couverts par un wildcard approprié.
Exemple de SAN robuste :
rds.contoso.com
rdweb.contoso.com
rdgw.contoso.com
*.contoso.com
*.subdomain.contoso.com
Étape 4 — Éliminer les certificats auto‑signés résiduels
Retirez tous les « RDP Self‑Signed » des magasins Ordinateur\Personnel et Ordinateur\Remote Desktop ; sinon, RDP‑Tcp peut les privilégier.
# Supprimer les RDP Self-Signed dans les magasins pertinents
Get-ChildItem Cert:\LocalMachine\RemoteDesktop, Cert:\LocalMachine\My |
Where-Object { $_.Issuer -eq $_.Subject -and $_.Subject -like '*RDP*' } |
Remove-Item -Force
Vérifiez ensuite qu’il ne reste qu’un certificat « serveur » valide avec clé privée et l’empreinte attendue.
Étape 5 — Propager automatiquement (PowerShell & GPO)
Avec PowerShell (ferme existante et nouveaux hôtes)
Import-Module RemoteDesktop
# Variables
$PfxPath = '\files\PKI\rds-unifie.pfx'
$PfxPwd = Read-Host 'Mot de passe du PFX' -AsSecureString
$CB = 'rdcb.contoso.com'
# Appliquer aux rôles "contrôlés" par l'assistant
Set-RDCertificate -Role RDGateway -ImportPath $PfxPath -Password $PfxPwd -Force
Set-RDCertificate -Role RDWebAccess -ImportPath $PfxPath -Password $PfxPwd -Force
Set-RDCertificate -Role RDPublishing -ConnectionBroker $CB -ImportPath $PfxPath -Password $PfxPwd -Force
Set-RDCertificate -Role RDRedirector -ConnectionBroker $CB -ImportPath $PfxPath -Password $PfxPwd -Force
# Propager aux Session Hosts (liaison RDP-Tcp)
$thumb = ((Get-PfxCertificate $PfxPath).Thumbprint).Replace(' ','')
$RDSH = (Get-RDServer -Role RDS-RD-SERVER).Server
Invoke-Command -ComputerName $RDSH -ScriptBlock {
param($Thumb)
$ts = Get-WmiObject -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'"
$null = $ts.SetSSLCertificateSHA1Hash($Thumb)
Restart-Service TermService -Force
} -ArgumentList $thumb
Avec GPO (PKI interne)
- Activez l’auto‑inscription pour l’ordinateur : Configuration ordinateur → Stratégies → Paramètres Windows → Paramètres de sécurité → Stratégies de clés publiques → Client de services de certificats – Inscription automatique.
- Distribuez la chaîne complète (racine + intermédiaire) dans Autorités de certification racines de confiance et Autorités de certification intermédiaires sur les clients et serveurs.
- Option : script de démarrage GPO qui applique l’empreinte au
RDP‑Tcp
(méthode WMI ci‑dessus).
Étape 6 — Contrôles techniques indispensables
Propriété | Pourquoi | Comment vérifier |
---|---|---|
Chaîne complète (serveur + intermédiaires + racine) | Sans intermédiaire, certains clients “ne voient” pas la racine, d’où alerte. | openssl s_client -connect rdgw.contoso.com:443 -showcerts ou certutil -verify |
EKU = Server Authentication (OID 1.3.6.1.5.5.7.3.1) | Un EKU inadapté peut faire rejeter le certificat par Schannel. | Onglet « Détails » du certificat (ou Get-ChildItem Cert:\ -EKU ) |
Clé RSA ≥ 2048, signature SHA‑256 | Conformité moderne, élimine des avertissements sur anciens clients. | openssl x509 -text -noout -in cert.cer |
Clients RDP à jour (v10+) | Vieilles versions gèrent mal SAN/jokers. | Mettre à jour via Windows Update / client MSTSC récent. |
Validation : voir et tester le certificat réellement présenté
Depuis un poste client
- MSTSC :
mstsc /v:farm.subdomain.contoso.com
→ à l’alerte, cliquer « Afficher le certificat » et vérifier Sujet, SAN, émetteur, validité. - OpenSSL : vérifier Session Host directement :
openssl s_client -connect rdsh01.contoso.com:3389 -tls1_2 -servername rdsh01.contoso.com
- RD Gateway :
openssl s_client -connect rdgw.contoso.com:443 -tls1_2 -servername rdgw.contoso.com
Depuis le serveur
- HTTP.SYS (Gateway / Web) :
netsh http show sslcert
→ vérifier que le Hash correspond à l’empreinte attendue. - Événements Schannel : Observateur d’événements → Journaux Windows → Système → 36882/36885/36874 indiquent un problème de certificat ou de chaîne.
- RDP‑Tcp (Session Host) : confirmer l’empreinte via WMI :
Get-WmiObject -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'" \| Select SSLCertificateSHA1Hash
Scénarios fréquents et corrections rapides
- Nom d’équilibrage ≠ nom dans le RDP : Le fichier
.rdp
contientfull address:s:server1.contoso.com
alors que l’utilisateur se connecte àrds.contoso.com
. Corriger le.rdp
pour qu’il référencerds.contoso.com
(ou ajouter ce FQDN dans les SAN). - Wildcard trop court :
*.contoso.com
ne couvre pasfarm.eu.sub.contoso.com
. Utiliser*.sub.contoso.com
ou le FQDN explicite. - PFX sans clé privée : Apparent dans la console : “vous disposez d’une clé privée correspondant à ce certificat” absent. Régénérer l’export
.pfx
avec clé. - Chaîne incomplète côté client : Importez les certificats d’AC intermédiaires/racine dans les magasins « Autorités de certification » des clients.
- Redirection vers FQDN non couvert : Le Broker envoie
rdsh02.internal.local
alors que le certificat couvre*.contoso.com
. Uniformiser les suffixes DNS (ou élargir les SAN), et ajuster les Connection Broker settings.
Renouvellement sans interruption (roll‑over maîtrisé)
- T‑15 jours : Générer le nouveau certificat (nouvelle clé), PFX + chaîne complète.
- T‑14 : Importer le PFX sur tous les serveurs (magasin Ordinateur\Personnel). Ne pas supprimer l’ancien.
- T‑13 : Appliquer le nouveau PFX via
Set‑RDCertificate
(Gateway, Web, Broker). Vérifiernetsh http show sslcert
etGet‑RDCertificate
. - T‑12 : Lier l’empreinte sur chaque Session Host (WMI) et redémarrer
TermService
en dehors des heures de pointe. - T‑11 : Tests clients (MSTSC/OpenSSL), double vérification des SAN.
- J‑0 : Supprimer l’ancien certificat une fois la bascule confirmée.
Script complet (idempotent) pour uniformiser la ferme
# Uniformisation du certificat RDS sur toute la ferme
param(
[Parameter(Mandatory=$true)] [string]$PfxPath,
[Parameter(Mandatory=$true)] [securestring]$PfxPassword,
[Parameter(Mandatory=$true)] [string]$ConnectionBroker
)
Import-Module RemoteDesktop
# 1) Import local si nécessaire
if (-not (Get-PfxCertificate $PfxPath)) {
Import-PfxCertificate -FilePath $PfxPath -CertStoreLocation Cert:\LocalMachine\My -Password $PfxPassword | Out-Null
}
# 2) Affecter aux rôles Gateway/Web/Broker
Set-RDCertificate -Role RDGateway -ImportPath $PfxPath -Password $PfxPassword -Force
Set-RDCertificate -Role RDWebAccess -ImportPath $PfxPath -Password $PfxPassword -Force
Set-RDCertificate -Role RDPublishing -ConnectionBroker $ConnectionBroker -ImportPath $PfxPath -Password $PfxPassword -Force
Set-RDCertificate -Role RDRedirector -ConnectionBroker $ConnectionBroker -ImportPath $PfxPath -Password $PfxPassword -Force
# 3) Lier à RDP-Tcp sur tous les Session Hosts
$thumb = ((Get-PfxCertificate $PfxPath).Thumbprint).Replace(' ','')
$rdsh = (Get-RDServer -Role RDS-RD-SERVER).Server
Invoke-Command -ComputerName $rdsh -ScriptBlock {
param($Thumb,$PfxPath,$PfxPassword)
if (-not (Get-PfxCertificate $PfxPath)) {
Import-PfxCertificate -FilePath $PfxPath -CertStoreLocation Cert:\LocalMachine\My -Password $PfxPassword | Out-Null
}
$ts = Get-WmiObject -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'"
$null = $ts.SetSSLCertificateSHA1Hash($Thumb)
Restart-Service TermService -Force
} -ArgumentList $thumb,$PfxPath,$PfxPassword
# 4) Nettoyage des auto-signés (optionnel)
Get-ChildItem Cert:\LocalMachine\RemoteDesktop, Cert:\LocalMachine\My |
Where-Object { $*.Issuer -eq $*.Subject -and $_.Subject -like '*RDP*' } |
Remove-Item -Force
FAQ express
Peut‑on utiliser un seul certificat pour toute la ferme ?
Oui, c’est la pratique la plus simple : un unique PFX dont les SAN couvrent tous les FQDN utilisés (nom d’accès Web, nom de Gateway, nom d’équilibrage Broker, et FQDN des Session Hosts ou wildcards par niveau).
Un wildcard suffit‑il ?
Un wildcard par niveau suffit souvent (*.contoso.com
et *.subdomain.contoso.com
). Il ne couvre pas les sous‑sous‑domaines.
Pourquoi vois‑je encore un auto‑signé ?
Parce qu’il reste dans un magasin (Remote Desktop ou Personnel) et que RDP‑Tcp le choisit par défaut si la valeur SSLCertificateSHA1Hash
n’est pas définie. Imposer l’empreinte via WMI et supprimer les auto‑signés résiduels.
Let’s Encrypt convient‑il à RDS ?
Oui, tant que la chaîne est complète et que les SAN correspondent. Automatisez le renouvellement et le Set‑RDCertificate + la mise à jour RDP‑Tcp.
Faut‑il redémarrer le serveur ?
Pas pour Gateway / Web / Broker (un recyclage de service suffit). Pour la liaison RDP‑Tcp, le redémarrage de TermService
interrompt les sessions actives ; planifiez le changement.
Informations complémentaires utiles
- Certificat unique par ferme — Sur Windows Server 2012/2016/2019/2022, un seul certificat couvrant tous les noms réellement utilisés (ou des wildcards restreints) évite les incohérences.
- DNS & Load Balancing — Le nom inscrit dans le fichier
.rdp
doit pointer vers l’équilibrage prévu (ou la Gateway). Un alias inattendu suffit à faire échouer la validation. - Documentation Microsoft — Recherchez « Using certificates in Remote Desktop Services » sur Microsoft Learn pour la procédure avec l’assistant, les cmdlets PowerShell et la gestion du Broker en haute disponibilité.
- Dépannage rapide —
mstsc /v:<nom>
puis « Afficher le certificat » ; ou interrogez le port 3389 :openssl s_client -connect <nom>:3389 -servername <nom>
.
Checklist finale
- Le même PFX (clé privée + chaîne complète) est présent sur tous les serveurs.
- RD Gateway / RD Web / Broker : affectation confirmée par
Set‑RDCertificate
etGet‑RDCertificate
. - Session Host :
SSLCertificateSHA1Hash
impose l’empreinte,TermService
redémarré. - Nom appelé = nom dans SAN (ou wildcard adéquat, un seul niveau).
- Plus aucun « RDP Self‑Signed » dans les magasins Remote Desktop et Personnel.
- Chaîne complète déployée sur serveurs et clients (racine + intermédiaires).
- Vérification pratique côté client (MSTSC / OpenSSL) et côté serveur (HTTP.SYS / Schannel).
Conclusion
En appliquant rigoureusement ces six étapes — affectation par rôle, binding explicite sur chaque Session Host, suppression des auto‑signés, propagation automatisée et contrôles de conformité — votre ferme RDS présentera systématiquement le bon certificat. Les avertissements disparaîtront pour de bon, et vos utilisateurs bénéficieront d’une expérience de connexion RDP propre, prévisible et sécurisée.