How to Configure TLS/SSL for Remote Desktop Protocol on Windows Server 2025
Remote Desktop Protocol (RDP) is one of the most widely used remote access tools in Windows Server environments, and it is also one of the most frequently targeted services by attackers. Exposed RDP endpoints attract brute-force attacks, credential stuffing campaigns, and exploitation of unpatched vulnerabilities. While perimeter controls such as VPNs and Network Level Authentication add important protective layers, ensuring that RDP sessions are encrypted with strong TLS and backed by a trusted certificate is a critical baseline control that is often overlooked. Windows Server 2025 provides multiple mechanisms for configuring RDP over TLS, selecting certificates, enforcing modern cipher suites, integrating with Active Directory Certificate Services for auto-enrollment, and requiring Network Level Authentication (NLA) before a desktop session is established. This guide walks through the complete configuration from Group Policy, manual certificate binding, FIPS mode considerations, and validation of the resulting TLS configuration.
Prerequisites
- Windows Server 2025 with Remote Desktop Services (RDS) role or RDP enabled (Settings → Remote Desktop)
- Active Directory Certificate Services (AD CS) with an Enterprise CA, or access to a commercial SSL certificate
- Domain Admin rights for GPO configuration; local admin for manual certificate binding
- PowerShell 5.1 or later with the RemoteDesktop and PKI modules available
- RDP client (mstsc.exe on Windows, or any client supporting TLS 1.2/1.3)
- A valid FQDN resolving to the server for proper certificate subject name matching
Step 1: Understand RDP Security Layers and TLS
RDP supports three security layer configurations that determine how the initial RDP handshake is secured:
- RDP Security Layer (legacy): Uses RDP’s own RC4-based encryption. No server certificate is presented to the client. Vulnerable to man-in-the-middle attacks. Should never be used on Windows Server 2025.
- Negotiate: The server and client negotiate the highest mutually supported layer. Falls back to RDP security if TLS is not available on the client. Acceptable only in closed, controlled environments.
- SSL (TLS): Forces TLS for the entire session, including the initial connection. The server must present a certificate trusted by the client. This is the recommended setting for all Windows Server 2025 deployments.
Network Level Authentication (NLA) is orthogonal to the security layer — it requires the client to authenticate via CredSSP (using Kerberos or NTLM) before the RDP desktop session is established, significantly reducing the attack surface of unpatched pre-authentication vulnerabilities. NLA and TLS should always be used together.
Step 2: Configure RDP TLS Security via Group Policy
The Group Policy settings for RDP security are located at:
Computer Configuration → Policies → Administrative Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Security
# Create and link a GPO for RDP TLS configuration
Import-Module GroupPolicy
$gpoName = "RDP-TLS-Hardening"
$domain = (Get-ADDomain).DNSRoot
$targetOU = "OU=Servers,DC=corp,DC=example,DC=com"
New-GPO -Name $gpoName -Domain $domain -Comment "Enforce TLS and NLA for RDP"
New-GPLink -Name $gpoName -Target $targetOU -LinkEnabled Yes -Enforced Yes
Write-Host "GPO '$gpoName' created and linked. Configure via GPME."
In the Group Policy Management Editor, configure these specific settings:
- Require use of specific security layer for remote (RDP) connections: Set to SSL. This forces TLS and prevents downgrade to the legacy RDP security layer.
- Set client connection encryption level: Set to High Level. This requires 128-bit encryption (TLS handles this automatically when SSL layer is selected, but setting High Level ensures no weak cipher fallback at the RDP application layer).
- Require Network Level Authentication for remote connections: Set to Enabled. This enforces NLA (CredSSP pre-authentication) before the session desktop is presented.
- Server authentication certificate template: Specify the name of your AD CS certificate template (e.g., RemoteDesktopComputer) to enable auto-enrollment of RDP certificates via Group Policy.
Step 3: Configure the RDP TLS Certificate
Option A: Use a CA-Issued Certificate via Auto-Enrollment
# Create a custom certificate template for RDP in AD CS (via Certificate Templates MMC)
# The template should have:
# - Extended Key Usage: Server Authentication (1.3.6.1.5.5.7.3.1)
# - Subject Name: Built from AD (DNS name of the computer)
# - Security: Allow Enroll and Autoenroll for Domain Computers
# After creating the template, publish it on the CA and configure auto-enrollment
# via GPO: Computer Config → Windows Settings → Security Settings → Public Key Policies
# → Certificate Services Client - Auto-Enrollment → Enabled, with Update/Renew checked
# Verify that a certificate has been auto-enrolled on the target server
Get-ChildItem -Path Cert:LocalMachineMy |
Where-Object { $_.EnhancedKeyUsageList.ObjectId -contains "1.3.6.1.5.5.7.3.1" } |
Select-Object Subject, Thumbprint, NotAfter
Option B: Manually Bind a Certificate to RDP
# Identify the certificate thumbprint to bind to RDP
# (Use a cert from LocalMachineMy with Server Authentication EKU)
$cert = Get-ChildItem -Path Cert:LocalMachineMy |
Where-Object {
$_.Subject -like "*server01.corp.example.com*" -and
$_.EnhancedKeyUsageList.ObjectId -contains "1.3.6.1.5.5.7.3.1" -and
$_.NotAfter -gt (Get-Date)
} | Sort-Object NotAfter -Descending | Select-Object -First 1
Write-Host "Using certificate: $($cert.Subject) [Thumbprint: $($cert.Thumbprint)]"
# Bind the certificate to the RDP listener via WMI
$rdpThumbprint = $cert.Thumbprint -replace " ",""
$rdpConfig = Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace "rootCIMV2TerminalServices" `
-Filter "TerminalName='RDP-Tcp'"
$rdpConfig.SetUserAuthenticationRequired(1) | Out-Null # Enforce NLA
$rdpConfig.SSLCertificateSHA1Hash = $rdpThumbprint
$rdpConfig.Put() | Out-Null
Write-Host "RDP certificate bound: $rdpThumbprint"
# Verify the binding
(Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace "rootCIMV2TerminalServices" `
-Filter "TerminalName='RDP-Tcp'").SSLCertificateSHA1Hash
Option C: Bind Certificate via CertUtil and Registry
# Alternative binding via registry (persists across reboots without WMI)
$thumbprint = $cert.Thumbprint -replace " ",""
$rdpRegPath = "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp"
Set-ItemProperty -Path $rdpRegPath -Name "SSLCertificateSHA1Hash" `
-Value ([byte[]]($thumbprint -split '(?<=G..)(?=.)' | ForEach-Object { [Convert]::ToByte($_, 16) }))
# Grant the RDP service (NETWORK SERVICE) read access to the certificate private key
$keyPath = (Get-Item "Cert:LocalMachineMy$thumbprint").PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
$keyDir = "$env:ALLUSERSPROFILEMicrosoftCryptoRSAMachineKeys"
$fullPath = Join-Path $keyDir $keyPath
$acl = Get-Acl $fullPath
$permission = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT AUTHORITYNETWORK SERVICE", "Read", "Allow")
$acl.AddAccessRule($permission)
Set-Acl -Path $fullPath -AclObject $acl
Write-Host "Private key permission granted to NETWORK SERVICE."
Step 4: Enforce FIPS-Compliant Encryption for RDP
In environments subject to FIPS 140-2 compliance requirements, you can enforce FIPS-approved algorithms for all cryptographic operations including RDP sessions.
# Enable FIPS mode system-wide (applies to RDP and all other cryptographic operations)
# WARNING: Test thoroughly — FIPS mode can break applications that use non-FIPS algorithms
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlLsaFipsAlgorithmPolicy" `
-Name "Enabled" -Value 1
# Verify FIPS mode is active
(Get-ItemProperty "HKLM:SYSTEMCurrentControlSetControlLsaFipsAlgorithmPolicy").Enabled
# When FIPS is enabled, RDP automatically uses FIPS-approved cipher suites
# (TLS_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, etc.)
# Verify active TLS cipher suites
Get-TlsCipherSuite | Where-Object { $_.Name -like "*AES_256*" } | Select-Object Name
Step 5: Restrict RDP to TLS 1.2 and TLS 1.3
# Disable TLS 1.0 and TLS 1.1 at the system level
$tlsBase = "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocols"
foreach ($version in @("TLS 1.0", "TLS 1.1")) {
foreach ($role in @("Server", "Client")) {
$path = "$tlsBase$version$role"
New-Item -Path $path -Force | Out-Null
Set-ItemProperty -Path $path -Name "Enabled" -Value 0
Set-ItemProperty -Path $path -Name "DisabledByDefault" -Value 1
}
}
# Ensure TLS 1.2 is explicitly enabled (it is by default, but be explicit)
foreach ($role in @("Server", "Client")) {
$path = "$tlsBaseTLS 1.2$role"
New-Item -Path $path -Force | Out-Null
Set-ItemProperty -Path $path -Name "Enabled" -Value 1
Set-ItemProperty -Path $path -Name "DisabledByDefault" -Value 0
}
Write-Host "TLS 1.0 and 1.1 disabled. TLS 1.2+ enforced. Reboot required."
# On Windows Server 2025, TLS 1.3 is enabled by default and preferred
# Verify TLS 1.3 is enabled
(Get-ItemProperty "$tlsBaseTLS 1.3Server" -ErrorAction SilentlyContinue)
Step 6: Validate the RDP TLS Configuration
# Test RDP TLS from a remote machine using Test-NetConnection
Test-NetConnection -ComputerName "server01.corp.example.com" -Port 3389
# Use openssl (if available via WSL or installed) to inspect the RDP TLS certificate
# openssl s_client -connect server01.corp.example.com:3389 -starttls rdp
# Check the currently configured RDP security settings via WMI
$rdpSettings = Get-WmiObject -Class "Win32_TSGeneralSetting" `
-Namespace "rootCIMV2TerminalServices" `
-Filter "TerminalName='RDP-Tcp'"
[PSCustomObject]@{
SecurityLayer = $rdpSettings.SecurityLayer # 2 = SSL/TLS
UserAuthenticationRequired = $rdpSettings.UserAuthenticationRequired # 1 = NLA
MinEncryptionLevel = $rdpSettings.MinEncryptionLevel # 3 = High
CertificateThumbprint = $rdpSettings.SSLCertificateSHA1Hash
}
# Confirm the bound certificate details
$thumbprint = $rdpSettings.SSLCertificateSHA1Hash
if ($thumbprint) {
Get-ChildItem "Cert:LocalMachineMy$thumbprint" |
Select-Object Subject, Issuer, NotBefore, NotAfter, Thumbprint
}
Step 7: Security Consideration — RDP Port and Exposure
# While changing the RDP port from 3389 does not provide real security
# (port scanning trivially discovers it), documenting the consideration is useful
# If your organization policy requires a non-standard port:
$newPort = 3390 # Example custom port
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "PortNumber" -Value $newPort
# Update Windows Firewall to allow the new port
New-NetFirewallRule -DisplayName "RDP Custom Port $newPort" `
-Direction Inbound `
-Protocol TCP `
-LocalPort $newPort `
-Action Allow `
-Profile Domain
# Disable the default 3389 rule if the custom port is used
Disable-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)"
Write-Host "RDP port changed to $newPort. Reboot required to take effect."
Write-Host "Preferred approach: keep 3389 but restrict via firewall to specific source IPs."
# Best practice: restrict RDP firewall rule to PAW IP ranges only
Set-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)" `
-RemoteAddress "10.10.50.0/24" # PAW subnet only
Conclusion
Properly securing RDP with TLS on Windows Server 2025 is a straightforward process that yields substantial security benefits. Enforcing the SSL security layer via Group Policy ensures that all RDP connections are encrypted with TLS from the first packet, eliminating man-in-the-middle risks inherent in the legacy RDP security layer. Binding a CA-issued certificate — ideally via AD CS auto-enrollment — provides clients with a verifiable identity for the server, while Network Level Authentication gates desktop session establishment behind a credential challenge. Disabling legacy TLS versions (1.0 and 1.1) at the system level ensures that no weak negotiation is possible. Together, these controls transform RDP from a frequently targeted weak point into a well-hardened management channel. Combine this configuration with source IP restrictions on the firewall, PAW-based administration, and monitoring of successful and failed RDP logon events (Event IDs 4624, 4625, and 4648) for a comprehensive RDP security posture on Windows Server 2025.