One of the most ubiquitous actions a sysadmin does is accepting the untrusted certificates we are presented with daily when opening RDP to a server. I believe training this behaviour is a horrible practice that Microsoft should discourage more forcefully. I decided to see what I could do about it in my lab.
There are two solutions available, the first is to trust all of the self-signed certificates from each server at a domain level. If you have 2 or 3 servers that may work but it does not scale well and is not an automated solution. Your second option is to issue certificates from your internal CA through GPO and that is the option we are going to explore.
I found numerous sources and hit a couple of issues but the docs below should be a solid baseline for anyone else to explore the idea of issuing out signed RDP certificates to all of their servers.
- Default Configuration
- Creating a RDP Certificate Template
- Applying the Policy
- Removing the Default Self-Signed Certificate
Windows server by default uses self signed certificates to secure RDP, this makes sense. The settings that control the issuance are located at
HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server. The most relevant key on the server is
Creating a RDP Certificate Template
The following images and most of the content is from this source I am copying it for the sake of preservation and my personal notes. Review his work instead if you prefer. His notes are from 2015 but they still seem relevant and worked for me on Server 2019 and Windows 10.
Any deviation is marked in [Brackets]. My work picks back up at Applying the Policy
In your CA
Open the Certificate Authority management console, Right-Clicking on Certificate Templates and selecting Manage
Select Computer template and Right-Click on it selecting Duplicate Template
[In the compatibility settings I chose Server 2019 and Windows 10] so as to make sure my connection uses stronger encryption algorithms and ciphers. This will vary depending on your network if you are forced to keep end of life versions of Windows or not.
Navigate to the General Tab and set a Display Name and Template Name. I recommend using the same and with no spaces. Had once a weird bug where on Windows 2008 it would enroll a new certificate again and again if a space was in the display name.
On the Extensions tab we click on Edit to modify the extensions for the certificate that will be issued.
We now select Client Authentication and click Remove. Many tutorial I see out there follow blindly the recommendations on others to also remove Server Authentication, this will break compatibility on none Windows platforms using the Microsoft Remote Desktop Client.
After removing the Client Authentication policy we now click on Add and in the window that appears we click on New to create a new policy specific for use of RDP TLS.
We provide the policy a name, in the example I give it a name of Remote Desktop Authentication and provide a Object Identifier of 184.108.40.206.4.1.3220.127.116.11 this will identify the certificate as one that can be used to authenticate a RDP server.
Under the Security tab we need to identify those systems that can enroll using this template. Domain Computers is already present and with the Enroll permission but if you also plan to enable RDP on Domain Controllers add the Domain Controllers group and ensure the Enroll permission is selected. [Do not remove Authenticated users from this or any other certificate template. I found this generates cryptic errors when trying to enroll in the certificate]
If you have computers that are not able to enroll using the certificate template a quick way to identify it is a permission issue is to look in the Event Viewer and look under the System Windows Log for events with ID 1064 from the source TerminaServices-RemoteConnectionManager.
Go in to the Certificate Authority management console and select under the CA Certificate Template, right click and select New -> Certificate Template to Issue
Select the certificate template you just created and click OK
Create or select an existing GPO and editing it. In the Group Policy Object Select Computer Configuration -> Policies -> Administrative Template -> Windows Components -> Remote Desktop Services -> Remote Desktop Session Host -> Security and select Server authentication certificate template.
Click on Enable and under Certificate Template Name we enter the name of the certificate template we made available for enrollment and click on OK.
To have the server use TLS 1.0 (I know TLS 1.0 is not the most secure) we select Require use of specific layer for remote (RDP) connection
❗ If you have TLS 1.2 configured this setting will enforce TLS 1.2 not SSL 1.0 source
Optional GPO Settings
While under security settings I would also recommend enabling NLA since this and TLS will break most public RDP brute forcing tools. Select Require user authentication for remote connections by using Network Level Authentication and double click on it. On the properties screen select Enable and click on OK.
Also since we do not want users to simply accept and always trust connections since this defeats the purpose of all this settings we ensure that clients always validate the server certificate. We select Computer Configuration -> Policies -> Administrative Templates -> Windows Components -> Remote Desktop Settings -> Remote Desktop Connection Client We double click on Configure Authentication for Client. Select Enable and set the Option to Warn me if authentication fails
If Remote Desktop is not enabled on another GPO you will need to go in to Connections under Remote Desktop Session Host and enable Allow users to connect remotely by using Remote Desktop Service.
Applying the Policy
Now that GPO is configured you can run
gpupdate /force on a server, it should pull the certificate into its personal store at
Cert:\LocalMachine\My\. To start using the newly requested certificate you must reboot the server or run
Restart-Service -Name TermService -Force.
Once you run the above or reboot you can validate the configuration with the following function. This function will compare the certificate in use to the certificate that was requested. If they match you are using a signed cert.
Removing the Default Self-Signed Certificate
You will notice that the above function most likely returns “A Self-Signed RdpCertificate is present” this is because Windows does not remove nor does it stop generating the self-signed certificate located at
If you do not mind having an unused certificate you can leave this alone and forget about it, but if you need to appease security scanners that check for self-signed certificates then you will need to take further action.
Windows will generate a self-signed certificate at every boot, and every time TermService gets restarted, deleting the cert does nothing for you. I found 2 solutions to this but both are incredibly hacky and may introduce new issues.
Change the CertStore location to an invalid path in the registry
- Change “SelfSignedCertStore” to “NULL” or any other invalid path
- Delete the certificate from
Cert:\LocalMachine\Remote Desktop\and restart the “TermService”
Remove SYSTEM permissions from the CertStore location
- Choose “Permissions…” ![[Pasted image 20220514123102.png]]
- Select “SYSTEM” and tick “Deny” on Full Control ![[Pasted image 20220514123209.png]]
- Delete the certificate from
Cert:\LocalMachine\Remote Desktop\and restart the “TermService”
Using Traditional “Server Authentication” Certificates
I found that the “Remote Desktop Authentication” Extended Key Usage is only required when using GPO. The “Server Authentication” attribute also works but you must manually set the certificate to be used by thumbprint on the host.
The above needs to be fully clarified. You might be able to set a “Server Authentication” template via GPO and have it work just fine. As far as I can tell the only hard requirement for GPO is that a template is used. If you issue certificates via CSR or some method that does not use templates then I do not see any method to specify this in GPO, you must use the below manual method on each host.
The “Enhanced Key Usage” extension has a value of either “Server Authentication” or “Remote Desktop Authentication” (18.104.22.168.4.1.322.214.171.124). Certificates with no “Enhanced Key Usage” extension can be used as well. source
The command for this would be
wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="THUMBPRINT"
, the source above has a much messier implementation but according this redddit post and a couple other sources I saw this command is all you need.
Verifying Certificates in Use
You can query a server with OpenSSL to see what cert is truly in use.
openssl.exe s_client -showcerts -connect localhost:3389
- RDP TLS Certificate Deployment Using GPO (darkoperator.com)
- Securing RDP Connections with Trusted SSL/TLS Certificates
- The Requested Template is not Supported by this CA (Error 0x80094800) - PKI Solutions Inc.
- Prevent remote desktop from generating a self-signed certificate - Microsoft Q&A
- (67) Force Remote Desktop to use an established certificet - NOT a self-signed : sysadmin (reddit.com)
- What are the steps to stop Windows 10 systems from generating/regenerating a RDP self-signed certificate? (microsoft.com)
- Configuring Remote Desktop certificates