Su alcuni server Windows Server 2022 “storici” la connessione RDP si chiude subito dopo l’autenticazione con “Your Remote Desktop Services session has ended…”. Qui trovi un playbook completo, pronto all’uso, per isolare e risolvere in modo sistematico la causa.
Panoramica del problema
In molte infrastrutture miste, i server Windows Server 2022 più datati (migrazioni o upgrade in-place) possono rifiutare le connessioni Remote Desktop Protocol (RDP) pur consentendo il log‑on locale alla console. I server 2022 implementati più recentemente, invece, non presentano l’anomalia. Questo comportamento indirizza verso cause tipiche: listener RDP non sano, porta modificata o bloccata, certificato del servizio scaduto o non assegnato, criteri di sicurezza più restrittivi (NLA, TLS, ciphers) o regole firewall/ACL incoerenti.
Soluzioni e verifiche suggerite (vista rapida)
Passo | Obiettivo | Comandi/azioni |
---|---|---|
Test di loopback | Stabilire se il problema è di rete o interno al server. | Dal desktop locale del server aprire un RDP verso localhost . Se funziona ▶︎ problema di rete/firewall. Se fallisce ▶︎ problema sul server. |
Verifica porta 3389 | Assicurarsi che la porta RDP sia aperta. | Firewall di Windows e appliance di rete; Security Group/NACL se VM in cloud. |
Controllo listener RDP | Verificare che il servizio accetti connessioni. | qwinsta ▶︎ la voce rdp‑tcp deve essere in stato Listen. |
Controllo porta in Registro | Escludere che la porta sia stata cambiata. | HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\Rdp‑Tcp\PortNumber = 3389 (decimale). |
Certificato RDS | Certificato self‑signed scaduto o mancante blocca la sessione. | Rigenerare/riassociare il certificato via Server Manager ► Remote Desktop Services ► Collections ► Certificates o via PowerShell. |
Guida Microsoft | Procedura completa di diagnostica. | Seguire “General Remote Desktop connection troubleshooting – Windows Server”. |
Approccio diagnostico: come isolare la causa in pochi minuti
Esegui il test di loopback (sul server interessato)
Accedi alla console (fisica, KVM, iLO/DRAC o Hyper‑V/VMware console) e lancia una connessione RDP verso localhost
, 127.0.0.1
o nome_server
:
mstsc /v:localhost
- Se la sessione funziona: il problema è esterno (rete, NAT, NSG, firewall, bilanciatori, VPN, inspection, IDS/IPS).
- Se la sessione non funziona o si chiude subito: la causa è sul server (listener, porta, certificato, NLA, GPO, Schannel).
Controlla la porta 3389
Verifica che il servizio stia realmente ascoltando e che il firewall locale consenta il traffico:
netstat -ano | findstr 3389
oppure, in PowerShell
Test-NetConnection -ComputerName localhost -Port 3389
Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Format-Table DisplayName,Enabled,Direction,Action
Le regole “Remote Desktop – User Mode (TCP-In)” e “Remote Desktop – User Mode (UDP-In)” devono essere abilitate. Se la tua organizzazione blocca l’UDP per policy, lasciare solo TCP è sufficiente, ma assicurati che le regole siano coerenti su tutti i profili (Domain/Private/Public).
Verifica lo stato del listener RDP
Il listener rdp-tcp deve trovarsi in stato Listen:
qwinsta
sinonimo:
query session
Se non vedi rdp-tcp
oppure risulta “Down”, riavvia il servizio e ricontrolla:
Get-Service TermService, UmRdpService | Format-Table Name,Status,StartType
Restart-Service TermService -Force
Conferma il numero di porta nel Registro
Una modifica non documentata della porta RDP è una causa ricorrente. Controlla e, se necessario, ripristina:
# Lettura
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name PortNumber
Impostazione (3389)
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name PortNumber -Value 3389
Restart-Service TermService -Force
Nota: il valore è un DWORD; la visualizzazione nel Registro di sistema può apparire in esadecimale, ma il numero effettivo deve essere 3389 (decimale), salvo esigenze specifiche.
Ripara il certificato del servizio RDS
Su installazioni “storiche” è frequente che il certificato usato dal listener sia scaduto, mancante o non accessibile (permessi sulla chiave privata). Il sintomo classico è la chiusura immediata della sessione subito dopo l’autenticazione.
- Apri certlm.msc (Certificati – Computer locale) e verifica in Personal o Remote Desktop che esista un certificato adatto all’uso “Server Authentication”.
- Controlla che il certificato abbia la chiave privata (“You have a private key that corresponds to this certificate”).
- Se non c’è o è scaduto, rigenerane uno self‑signed e assegnalo al listener.
PowerShell (procedura standard compatibile con Windows Server 2022):
# 1) Rigenera un certificato self-signed per RDP
$cert = New-SelfSignedCertificate `
-DnsName $env:COMPUTERNAME `
-CertStoreLocation "Cert:\LocalMachine\RemoteDesktop" `
-KeyAlgorithm RSA -KeyLength 2048
2) Applica l'associazione al listener RDP (chiave di Registro SSLCertificateSHA1Hash)
$thumb = ($cert.Thumbprint).Replace(" ","")
[byte[]]$hash = for ($i=0; $i -lt $thumb.Length; $i+=2) { [Convert]::ToByte($thumb.Substring($i,2),16) }
Set-ItemProperty ` -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"`
-Name "SSLCertificateSHA1Hash" -Value $hash
3) Riavvia il servizio
Restart-Service TermService -Force
4) Verifica
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
-Name SSLCertificateSHA1Hash | Format-List
Se usi un certificato pubblico/aziendale, importa il certificato con chiave privata nel computer locale e sostituisci la variabile $cert
con la selezione del certificato desiderato (Get-ChildItem Cert:\LocalMachine\My | Out-GridView -PassThru
), quindi ripeti l’associazione.
Temporaneamente disabilita NLA per escludere problemi di autenticazione
La Network Level Authentication (NLA) protegge il server, ma se esistono incongruenze su Kerberos/NTLM, canali sicuri o credenziali, può interrompere la sessione. Disabilitala temporaneamente solo per diagnosticare, poi riattivala.
GUI: SystemPropertiesRemote.exe ► “Consenti le connessioni dai computer che eseguono qualsiasi versione di Desktop remoto (meno sicuro)”.
Registro/GPO:
# Disabilita NLA (temporaneo)
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
-Name UserAuthentication -Value 0
Restart-Service TermService -Force
(Riab. dopo i test)
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp" `
-Name UserAuthentication -Value 1
Restart-Service TermService -Force
GPO: Computer Configuration ► Administrative Templates ► Windows Components ► Remote Desktop Services ► Remote Desktop Session Host ► Security ► “Require user authentication for remote connections by using NLA”.
Controlla i servizi e la policy di abilitazione RDP
Oltre a TermService
e UmRdpService
, verifica che la funzionalità RDP non sia esplicitamente negata da GPO (fDenyTSConnections
):
# Abilitazione RDP (equivalente di "Allow remote connections")
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 0
Audit GPO effettive
gpresult /h C:\Temp\gp.html
Event Viewer: dove guardare
I log più utili sono in Applications and Services Logs ► Microsoft ► Windows ► TerminalServices-LocalSessionManager, TerminalServices-RemoteConnectionManager, TerminalServices-RDPClient (Operational). Cerca messaggi relativi a:
- Errore nello stream del protocollo o handshake TLS (spesso riconducibile a certificato o ciphers).
- Autenticazione NLA fallita (Kerberos/NTLM, canale sicuro, SPN).
- Sessione terminata immediatamente dopo l’accesso (listener non sano o token ridiretto con policy incompatibili).
Controlla anche il Registro di sicurezza per eventuali 4625 (logon falliti) e l’Event Log System per eventi Schannel che indicano problemi TLS.
Patch e aggiornamenti
Assicurati che il server esegua l’ultima cumulative update di Windows Server 2022. Alcune build intermedie hanno corretto regressioni che impattavano la stabilità del canale RDP‑TCP. Dopo l’aggiornamento, riesegui i test di loopback e una connessione da una postazione esterna.
Ambienti Cloud / Azure
Se la macchina è una VM in cloud (Azure, AWS, GCP):
- Security Group / NSG / NACL: consenti TCP 3389 in ingresso solo dagli IP amministrativi (meglio se con JIT/privileged access) e verifica che non ci siano regole prioritarie di deny.
- Port scanning esterno: se non hai accesso console, usa un test da Internet (o dal tuo jump host) per verificare l’apertura della porta.
- Serial Console / Run Command (se disponibili): reimposta NLA, rigenera il certificato e riavvia
TermService
direttamente dal piano di controllo quando la VM è irraggiungibile. - Bilanciatori/Firewall layer‑7: disattiva temporaneamente ispezioni TLS o “RDP proxy” per escludere interferenze nel handshake.
Playbook operativo dettagliato
Checklist rapida (da spuntare)
- [ ] Loopback RDP da console (
mstsc /v:localhost
). - [ ]
rdp-tcp
in stato Listen (qwinsta
). - [ ] Porta nel Registro = 3389 e in ascolto (
netstat
,Test-NetConnection
). - [ ] Regole firewall “Remote Desktop” abilitate (TCP e, opzionale, UDP).
- [ ] Certificato RDS valido e assegnato (
SSLCertificateSHA1Hash
). - [ ] NLA disabilitata solo per test (poi riabilitata).
- [ ] Event Viewer controllato (TS LSM/RCM, Schannel, Security).
- [ ] Ultime cumulative installate e riavvio pianificato.
Script PowerShell “sanity check” end‑to‑end
Questo script non modifica nulla: raccoglie informazioni chiave e ti dice cosa non quadra. Eseguilo alla console del server interessato.
$report = [ordered]@{}
Servizi RDP
$svc = Get-Service TermService, UmRdpService -ErrorAction SilentlyContinue
$report["TermService"] = $svc | Where-Object Name -eq "TermService" | Select-Object -ExpandProperty Status
$report["UmRdpService"] = $svc | Where-Object Name -eq "UmRdpService" | Select-Object -ExpandProperty Status
Porta in Registro
$rdpKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
$port = (Get-ItemProperty $rdpKey -Name PortNumber -ErrorAction SilentlyContinue).PortNumber
$report["PortNumber"] = $port
Listener
$listenerOk = (qwinsta | Select-String -SimpleMatch "rdp-tcp").ToString()
$report["ListenerLine"] = $listenerOk
Socket
$tnc = Test-NetConnection -ComputerName localhost -Port ($port ? $port : 3389)
$report["TCP3389_Reachable"] = $tnc.TcpTestSucceeded
Certificato
$certs = Get-ChildItem Cert:\LocalMachine\RemoteDesktop -ErrorAction SilentlyContinue
if(-not $certs) { $certs = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.EnhancedKeyUsageList.FriendlyName -contains "Server Authentication" } }
$cert = $certs | Sort-Object NotAfter -Descending | Select-Object -First 1
$report["CertThumbprint"] = $cert.Thumbprint
$report["CertNotAfter"] = $cert.NotAfter
Associazione certificato & NLA
$hash = (Get-ItemProperty $rdpKey -Name SSLCertificateSHA1Hash -ErrorAction SilentlyContinue).SSLCertificateSHA1Hash
$report["HasSSLCertHash"] = [bool]$hash
$nla = (Get-ItemProperty $rdpKey -Name UserAuthentication -ErrorAction SilentlyContinue).UserAuthentication
$report["NLA_UserAuthentication"] = $nla
Firewall
$fw = Get-NetFirewallRule -DisplayGroup "Remote Desktop" -ErrorAction SilentlyContinue |
Get-NetFirewallRule | Select-Object DisplayName, Enabled, Direction, Action
$report["FirewallRulesEnabled"] = ($fw | Where-Object {$.Enabled -eq "True" -and $.Action -eq "Allow"}).Count
Output
$report.GetEnumerator() | ForEach-Object { "{0} : {1}" -f $.Key, $.Value }
Script di riparazione certificato (se necessario)
Se il controllo indica assenza/scadenza del certificato o mancata associazione, usa lo script seguente. Nota: esegue modifiche controllate (crea un nuovo certificato self‑signed, lo associa e riavvia il servizio).
# Crea nuovo certificato per RDP
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME `
-CertStoreLocation "Cert:\LocalMachine\RemoteDesktop" -KeyAlgorithm RSA -KeyLength 2048
Associa al listener (SSLCertificateSHA1Hash)
$thumb = ($cert.Thumbprint).Replace(" ","")
[byte[]]$hash = for ($i=0; $i -lt $thumb.Length; $i+=2) { [Convert]::ToByte($thumb.Substring($i,2),16) }
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
-Name "SSLCertificateSHA1Hash" -Value $hash
Riavvia e verifica
Restart-Service TermService -Force
Start-Sleep 3
qwinsta
Policy e cifrari: compatibilità TLS
Ambienti hardening possono imporre set di cifrari TLS o livelli minimi incompatibili con client legacy o con il certificato usato dal listener. Suggerimenti:
- Evita di disabilitare indiscriminatamente TLS 1.2/1.3: verifica piuttosto che i client possano parlare almeno TLS 1.2.
- Se hai policy “FIPS compliant” o suite ristrette, prova da un client aggiornato per escludere problemi lato endpoint.
- In caso di ispezione TLS/SSL off‑box, bypassa temporaneamente il flusso RDP per testare l’handshake end‑to‑end.
GPO utili per RDP (percorsi rapidi)
Funzione | Percorso GPO | Chiave Registro |
---|---|---|
Abilita RDP | Computer Config ▶ Administrative Templates ▶ Windows Components ▶ Remote Desktop Services ▶ Remote Desktop Session Host ▶ Connections ▶ “Allow users to connect remotely…” | HKLM\System\CurrentControlSet\Control\Terminal Server\fDenyTSConnections = 0 |
Richiedi NLA | … ▶ Security ▶ “Require user authentication for remote connections by using NLA” | HKLM\…\RDP-Tcp\UserAuthentication = 1 |
Limite connessioni | … ▶ Connections ▶ “Limit number of connections” | HKLM\…\RDP-Tcp\MaxInstanceCount |
Livello sicurezza | … ▶ Security ▶ “Set client connection encryption level” | HKLM\…\RDP-Tcp\SecurityLayer , MinEncryptionLevel |
Diagnosi rete quando il loopback funziona
Se l’RDP verso localhost
funziona, sposta il focus su rete e perimeter:
- Firewall locale: profili (Domain/Private/Public) coerenti con il NIC attivo; Remote Desktop (TCP-In) abilitato.
- Appliance/NGFW: controlla policy, NAT, oggetti di rete, logging (drop/reset) e ispezioni applicative.
- Cloud NSG/NACL: consenti 3389 in ingresso dall’IP sorgente; verifica priorità delle regole.
- Routing/VPN: route corrette e assenza di asymmetric routing che causi RST.
Hardening e differenze tra “storici” e “nuovi”
Spesso i server “storici” ereditano GPO, ciphers, driver, strumenti EDR o agent legacy che interferiscono con il canale RDP. Una strategia pragmatica:
- Confronta le GPO risultanti (gpresult/rsop) tra un server “storico” e uno “nuovo” che funziona.
- Allinea le cumulative, driver NIC e le versioni degli agent di sicurezza.
- Valuta la rimozione di policy obsolete (es. NTLM deny all senza SPN corretti) o cifrari non più supportati.
Ripristino d’emergenza (senza console grafica)
Se non puoi accedere alla GUI ma hai una shell (Serial Console/WinRM/Run Command):
# 1) Riabilita RDP e firewall
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 0
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
2) Disabilita NLA (temporaneo)
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp" -Name UserAuthentication -Value 0
3) Rigenera certificato e riavvia servizio
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\RemoteDesktop"
$thumb = $cert.Thumbprint.Replace(" ","")
[byte[]]$hash = for ($i=0; $i -lt $thumb.Length; $i+=2) { [Convert]::ToByte($thumb.Substring($i,2),16) }
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name SSLCertificateSHA1Hash -Value $hash
Restart-Service TermService -Force
Subito dopo il test, riattiva NLA e applica un certificato valido secondo gli standard aziendali.
Domande frequenti (FAQ)
Perché la sessione RDP si chiude subito dopo l’autenticazione?
La casistica più frequente è il certificato del listener scaduto/non valido o non accessibile al servizio, con conseguente errore nel handshake TLS. Subito dopo l’immissione delle credenziali, il canale viene terminato e il client mostra “Your Remote Desktop Services session has ended…”.
Se cambio la porta RDP, risolvo?
Cambiare porta può aggirare conflitti o blocchi specifici, ma complica firewall/monitoring e non risolve cause come NLA o certificati. È preferibile riportare alla 3389 salvo eccezioni progettuali.
Disabilitare NLA è sicuro?
No, è solo un workaround diagnostico. Mantieni NLA attiva in produzione per ridurre la superficie di attacco (pre‑auth brute force, enumerazioni).
Devo usare un certificato pubblico?
In ambienti interni basta un certificato emesso dalla CA aziendale. L’importante è che abbia “Server Authentication”, chiave privata accessibile a NT SERVICE\TermService
e sia correttamente associato al listener (hash SHA‑1 in SSLCertificateSHA1Hash
).
È necessario riavviare il server?
Per molte modifiche (certificato, NLA, porta) è sufficiente riavviare TermService
. Pianifica un reboot se applichi cumulative, aggiorni driver di rete o modifichi estensivamente la crittografia di sistema.
Best practice di prevenzione
- Standardizzazione build: usa template/immagini con regole firewall, NLA e certificato già correttamente configurati.
- Rinnovo certificati: monitora la scadenza dei certificati nel Remote Desktop store e avvisa prima della data di scadenza.
- Patch cadence: applica regolarmente le cumulative di Windows Server 2022 e verifica i servizi RDP dopo ogni change.
- Accesso sicuro: limita la 3389 con NSG/ACL a IP amministrativi e usa soluzioni di accesso bastionato o JIT.
- Documentazione: registra ogni deviazione standard (porta non 3389, ciphers custom, RDP proxy) per semplificare la futura diagnostica.
Approfondimenti utili
- Servizi – Verificare che Remote Desktop Services sia avviato (services.msc) e che nessuna GPO imponga limiti di connessioni o di crittografia obsoleta.
- NLA – Temporaneamente disabilitare Network Level Authentication per escludere problemi di Kerberos/NTLM.
- Event Viewer – Controllare i log Applications and Services Logs ► Microsoft ► Windows ► TerminalServices‑* per messaggi indicativi nel percorso di handshake e logon.
- Aggiornamenti – Applicare l’ultima cumulativa di Windows Server 2022: alcune patch hanno corretto bug nel canale RDP‑TCP.
- Cloud/Azure – Se il server è una VM Azure, usare strumenti come Network Watcher/Run Command o un port‑scanner esterno per sostituire/integrare il test di loopback.
In sintesi
Il metodo più rapido per isolare la causa è il test di loopback locale: se la connessione va a buon fine, concentra la diagnosi su firewall, ACL e rete; se fallisce, verifica listener, porta, certificato e log del server. Nella pratica, applicare le patch più recenti e – quando necessario – rigenerare/riassociare il certificato RDS risolve spesso la chiusura immediata della sessione.
Esempi di comandi utili (promemoria)
# Stato servizi RDP
Get-Service TermService, UmRdpService
Listener attivo
qwinsta
Porta in ascolto
netstat -ano | findstr 3389
Test-NetConnection -ComputerName localhost -Port 3389
Abilitare RDP e regole firewall
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 0
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Disattivare/riattivare NLA (diagnostica)
Set-ItemProperty "HKLM:...\RDP-Tcp" -Name UserAuthentication -Value 0
Set-ItemProperty "HKLM:...\RDP-Tcp" -Name UserAuthentication -Value 1
Rigenerare e applicare certificato
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\RemoteDesktop"
$thumb = $cert.Thumbprint.Replace(" ","")
[byte[]]$hash = for ($i=0; $i -lt $thumb.Length; $i+=2) { [Convert]::ToByte($thumb.Substring($i,2),16) }
Set-ItemProperty "HKLM:...\RDP-Tcp" -Name SSLCertificateSHA1Hash -Value $hash
Restart-Service TermService -Force
Suggerimento finale: quando intervieni su server “storici”, confronta sempre i risultati con un server 2022 “sano” (stessa OU/GPO): differenze su NLA, cifrari, certificati o regole firewall emergono subito e accelerano la risoluzione.