View on GitHub

The Unofficial r/selfhosted Wiki

Creating Verifiable Remote Desktop Host Certificates with spki

This guide will show you how to use spki to generate and deploy fully verifiable x509 certificates for accessing your hosts via Windows Remote Desktop, eliminating the dreaded security warning.

Accessing remote desktops securely and without certificate warnings

By default, Windows will generate a self-signed certificate and present that when you try to connect to a remote host. This certificate is used both to verify the host’s identity and to encrypt the connection. However, this makes the connection very susceptible to man-in-the-middle attacks, as an attacker can easily generate their own self-signed certificate that appears near-identical to the one on your host. Unless you’re paying careful attention, you may not notice the change, and then the attacker can eavesdrop on your connection.

When you connect to a host that presents a self-signed certificate, Windows will show the following security warning because it is not signed by a trusted authority:

Windows Remote Desktop Warning

While you can just ignore the warning, it is easy and much more secure to create your own certificate authority and create a trusted, verifiable certificate that won’t generate a warning if everything is in order.

Setting up a PKI with CRL’s

The first step is creating a Public Key Infrastructure with Certificate Revocation Lists. CRL’s are used to verify that the Certificate Authority (CA) of your PKI has not revoked the certificate your host is presenting. This guide is geared towards Linux users, but as spki and openssl are both cross-platform, it should work for other OSes with minor modifications.

A simple CRL Distribution Point over http

The easiest way to create a CRL DP is by serving it over http. NB: this is one case where https should not be used, as the CRL of the https server would also have to be verified, and the CRL of its CA, and so on and so forth. The distribution point should be set up in advance of creating your certificates, as the URI will be permanently encoded in the certificates. If you are accessing your remote hosts over the internet, you’ll also want to make sure that your CRL Distribution Point is publicly accessible.

First we’ll set up a directory from which to server CRL’s and public certificates generated by our pki, for convenience:

sudo mkdir /var/pki
sudo ln -s /root/ca/intermediate/certs/ /var/pki/certs
sudo ln -s /root/ca/intermediate/crl/intermediate.crl.der /var/pki/intermediate.crl
sudo ln -s /root/ca/crl/ca.crl.der /var/pki/root.crl
sudo ln -s /root/ca/certs/ca.cert.pem /root/intermediate/certs/root.cert.pem

Your directory structure will end up looking something like this:

administrator@fserver:~$ ll /var/pki
total 8.0K
drwxr-xr-x  2 root root 4.0K Apr  4 15:16 ./
drwxr-xr-x 17 root root 4.0K Mar 29 10:15 ../
lrwxrwxrwx  1 root root   31 Apr  4 15:15 certs -> /root/ca/intermediate/certs//
lrwxrwxrwx  1 root root   49 Apr  4 15:15 intermediate.crl -> /root/ca/intermediate/crl/intermediate.crl.der
lrwxrwxrwx  1 root root   26 Apr  4 15:16 root.crl -> /root/ca/crl/ca.crl.der

In this example, we’ll use the Apache HTTP server, but any alternative can be used.

First, install apache2 with your distribution’s package manager (e.g. sudo apt-get install apache2 or sudo yum install httpd)


If you want to use subdomain as your CRL DP (e.g., add the following to a “site” configuration file /etc/apache2/sites-available/pki.conf

<VirtualHost *:80>
	DocumentRoot /var/pki
	<Directory /var/pki>
		Allowoverride none
		Options FollowSymLinks
		Require all granted
	<Directory /var/pki/certs>
		Options Indexes FollowSymLinks

(Don’t forget to replace the ServerName with your actual domain name)

Activate the site with sudo a2ensite pki and then restart apache2 (sudo systemctl restart apache2 or sudo systemctl restart httpd)


If you already have domain and you’d like to add the CRL DP as a subdirectory, add the following to your existing server configuration (default location: /etc/apache2/sites-available/000-default.conf)

Alias /pki /var/pki/
<Directory /var/pki>
	Allowoverride none
	Options FollowSymLinks
	Require all granted
<Directory /var/pki/certs>
	Options Indexes FollowSymLinks

Now restart apache2 (sudo systemctl restart apache2 or sudo systemctl restart httpd)

Before continuing with the PKI setup, ensure that your Distribution Point is accessible through a browser!

Setting up the PKI

Grab the spki from the Github repo and save it somewhere in your path, like /usr/local/bin.

Open the script in your favorite text editor, and set the following two variables based on your previous http server setup:

Now run spki init to go through the process of setting up the PKI. You can watch an example asciicast here.

This will create a Root CA and use it to sign an Intermediate CA. The Intermediate CA will then be used to actually sign your host certificates. The CRL’s are also automatically generated and signed.

You’ll want to make sure that the Intermediate Certificate has the correct CRL DP:

X509v3 CRL Distribution Points:
Full Name:

If the CRL is not accessible, the verification step will fail. You’ll want to correct that and re-verify the intermediate certificate before continuing: spki verify-intermediate

CA Security

The Root CA private key should be stored offline in a safe place. If that key is compromised, the entire PKI is compromised. If the Intermediate CA key is compromised, however, you can revoke it and generate a new one. Any attempts to verify certificates signed by your compromised intermediate key will fail upon checking the CRL.

Creating certificates

Now we’ll actually create the certificate that will be used by your Windows host.

Run spki create server <windows host name> and follow the prompts. If you access the host over the internet using a domain, you can use a subjectAltName so that the certificate is valid for both your local computer name, and also the domain name. In that case use spki create server <windows host name> -SAN

Again, make sure that the certificate has the correct CRL DP:

X509v3 CRL Distribution Points:
Full Name:

Deploying on Windows

The easiest way to import multiple certificates in Windows is by using the pkcs12 format. Run spki export-pkcs12 <windows host name> to generate the .p12 file that will contain the Root CA, Intermediate CA, and your newly created keypair. You’ll have to supply an export password. Now copy that file (default: /root/ca/intermediate/certs/<windows host name>.p12) over to your Windows host, and open the file to begin the import process. Import everything to your “Personal Store” by following the steps below.

Windows P12 Import Wizard Step 0

Windows P12 Import Wizard Step 1

Windows P12 Import Wizard Step 2

Windows P12 Import Wizard Step 3

Windows P12 Import Wizard Step 4

After the import completes, open up the Certificate Management Tool (search: manage computer certificates or Win+R, certlm.msc, Enter). There will be three new certificates in Personal Store\Certificates: Root CA, Intermediate CA, and the host certificate. Drag the Root CA into Trusted Root Certification Authorities\Certificates and the Intermediate CA into Trusted Intermediate Certification Authorities\Certificates. You can leave your host certificate in the Personal Store.

Verify the complete trust chain by double-clicking your host certificate in the Personal Store and going to Certification Path tab, you should see the entire path back to your Root CA.

Certification Path

Finally, you need to tell remote desktop to use the new certificate. First, find the certificate’s SHA1 Hash, or “Thumbprint” by checking its “Details” tab:

SHA1 Thumbprint

Copy that thumprint and open a command prompt with administrator privileges.

Run wmic /namespace:\\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="THUMBPRINT", replacing THUMBPRINT with what you just copied.

You’ll have to restart the remote desktop service or host for this to take effect.

Deploying on clients

In order to trust the newly deployed certificate, your clients will also need to trust the Root CA cert and Intermediate CA cert. If you used the symbolic links above to serve certificates, you should be able to download them simply by accessing and Repeat the import process from above, this time on the two certificate files, and place them in the same trusted CA stores. You can also import them by changing the file extension to .crt and simply opening the files.

Deploying on Linux

If you’re accessing your host via Linux, you’ll need to copy the Root and Intermediate CA certs into /usr/local/share/ca-certificates and run sudo update-ca-certificates

Tags: openssl pki rdp spki windows

Last updated: 06 May 2019 by Aram Akhavan