Using Let's Encrypt to secure Windows Remote Desktop connections

Since we’re setting up our local network with a domain, I’d like to properly secure our connections to Remote Desktop sessions. One might argue that using self-signed certificated is valid in the context of the local network, but I don’t like the idea of collecting self-signed certificates in my keychain, plus it would also stop people from the company to dismiss security warnings about certificates.

I did some googling about this, but many informations are outdated or not specific to this issue. The main assumption is that I’d like to automate the whole process of renewal. The second assumption is that a DNS challenge becomes the necessary way of obtaining the certificate, since servers/workstations are not accessible directly from outside our network via public-facing DNS.

In our case, our domain and public DNS are hosted on OVH, which as far as I can tell has an API to manage the DNS zone programmatically. Many other DNS providers offer APIs to make such changes. Can you confirm that this would allow me to pass the DNS challenge, if properly configured?

The next step would be the setup of Remote Desktop services to use the certificate. The way to configure it and reloading it is outside the scope of this community site (even though if you found a killer guide/blogpost, I would be very grateful!), but I would like to know if a certificate from Let’s Encrypt is compatible with such a use case. Maybe it just need extra processing/packaging in a different format?

In summary, has anyone tried to automate this use case? Any tips?

Hi @mcdado,

Yes, that should be fine.

In terms of using Let's Encrypt certificate in Windows Remote Desktop, we've had a handful of questions about that and it doesn't look like anyone ever reported back afterward about how well it worked (or didn't work).

Thank you for your answer!

I’ll try to at least get the certificate part rolling, with the DNS challenge that is going to be some fiddling I believe, and eventually try use that certificate to enable Remote Desktop with it.

I’ll definitely report back, either way.

my 5 cents below :smiley:

obtain cert using zerossl (speed)

Create PFX:

openssl pkcs12 -export -out pfxname -in certname -inkey keyname

Import Cert to Key Store

3 Likes

The Tricky Bit

If you are using Remote Desktop Gateway use instructions here: Select an Existing Certificate for Remote Desktop Gateway | Microsoft Learn

If you want this for a standalone server (my case) then use instructions here: Remote Desktop listener certificate configurations - Windows Server | Microsoft Learn

I used the command below:

wmic /namespace:\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="FINGERPRINT"

Acquiring the fingerprint:

I used notepad to clean up the fingerprint (not spaces)

Telling Remote Desktop To Use the Cert:

No restart needed.

Confirm cert is being used

This can be hard as it works with domain name, So i login using IP to verify the cert

3 Likes

this is a fairly manual process but it works

it’s up to you if you use certbot on windows (read my other article on how to get this working) or one of the other clients such as ACME Sharp or https://github.com/Lone-Coder/letsencrypt-win-simple

you can write the remote desktop update as a hook after the cert is installed.

you will also need to use powerhsell to install the certificate: https://technet.microsoft.com/en-us/itpro/powershell/windows/pki/import-pfxcertificate

note: our internal domain is a internet based name so we can do DNS challenges etc

The flow would look something like

Obtain Certificate
hook code:

  1. Obtain Certificate Thumbprint
  2. Convert to PFX
  3. Import PFX to Store
  4. Associate Certificate with Remote Desktop

Andrei

3 Likes

Thanks for all these details, @ahaw021! They should be super-useful and I’ll try to remember this thread in case people ask about this in the future.

For removing the spaces from the fingerprint, do you have an equivalent of tr in the Windows command line, maybe with Powershell? In Unix you could use tr -d ' ' to remove spaces from a string, without having to do it by hand in a text editor.

I would use the replace powerhsell command.

there is a trim command in powershell but it removes leading and tailing spaces so not what we are after in this case :smiley:

i usually do things "manually" first and then write the scripts

e.g.

$SHATHUMB = " 90 JF EF 83 DF"
$SHATHUM = $SHATHUMB.replace(" ","")
Write-Host($SHATHUMB)

will write this as a script later and integrate it with my certbot run

i believe for windows it will be a mix of python and powershell for a while as powershell has really good commandlets for doing windows related functions.

Andrei

1 Like

Andrei, your posts are awesome! I’m glad you shared your knowledge here.

Also, I didn’t know about https://zerossl.com, it’s a great starting point for experimentation!
I bookmarked this conversation so that I can try to accomplish the same on my own, later on when I’ll set this up.

As far I understand it, this should be completely automatable through PowerShell and Python, right?
For example, at renewal you would run certbot, with a hook for DNS validation, and once we have the certificate then obtain the thumbprint and store it in a PowerShell variable (with space removal), convert the certificate to PFX and import it. This last step is still not clear to me: in your screenshot you used the key store GUI, can you use PowerShell to import the certificate, or update it on renewal? On Windows does it work and makes sense to use something such as symlinks like on Unix OSes?

Thank you so much.

You mean this?

Bookmarked too.

yes that’s the one article

this is where i am currently having challenges with windows

i am trying to figure out how to put the RSA key in to the store. There is no point having a cert without a key.

PFX allows us to do this.

There is the certutil.exe utility which will generate a CSR and create a key in the right store (you then fulfill the challenge and import the cert only)

Windows IIS cannot make use of certs on file stores they have to be in the cert store

I am working my way through the powershell side also going to log a request with the boulder team to make PFX an option as being able to download a PFX file from letsencrypt will simplify things for windows users

Andrei

in the mean time if openssl is on the system the openssl syntax can be scripted

but i would like to do as much as i can with windows native tools :smiley:

Andrei

there is also a library called iis_bridge which I am quite impressed with.

so tossing up how to create an IIS installer plugin at the moment :smiley:

whether to use hooks or the plugin system

sorry for the ramblings :smiley:

Andrei

No, that’s all good to know! And I agree that less external dependencies the better.

Are you going to publish your scripts in a nice configurable way?

I’ll give you the manual steps that I take. I only have a couple of client stations that it is needed on, so I have not taken the time to automate the process. Besides, this is the best way to see what is actually happening.

  • Even though we have a valid LetsEncrypt certificate in the server’s certificate store [Remote Desktop]-[Certificates], RDP clients still see a “The identity of the remote computer cannot be verified” message when trying to connect.
  • We need to digitally sign the RDP files on the client machines with an SSL certificate to get rid of the message.
  • First - Copy the Let’s Encrypt certificate that you want to use from [Personal]-[Certificates] and Paste it into the certificate store under [Remote Desktop]-[Certificates].
  • Export that LetsEncrypt certificate on the server from the server’s certificate store under [Remote Desktop]-[Certificates].
  • You MUST choose to include the cert’s Private Key when exporting.
  • Copy the exported PFX file from the server to the client machines that have RDP files.
  • On the client machine, import the server’s PFX format certificate into the client’s Personal certificate store.
  • Now, we can use rdpsign.exe to sign the client’s RDP file that connects to the server.
  • Go into the client’s certificate store to [Personal]-[Certificates].
  • Open the imported cert and go the [Details] tab of the [Certificate Information] dialog.
  • Choose [All Fields] from the first dropdown list.
  • Find the value of the [Signature Hash Algorithm] … (probably SHA256, or maybe SHA1 on older certs).
  • Find the value of the [Thumbprint] field. This will be a series of two byte characters that are separated by spaces.
  • Copy the Thumbprint value and edit all of the white-space out of it, so that it is a solid string of characters. There may be an odd character at the front of the string - if so, that will need to be deleted. You might not be able to see this character, so it is best to place the cursor at the front of the string and just hit delete until the first real character of the thumbprint string is deleted - and then retype that character at the beginning of the string.
  • Launch a Command Prompt (with admin privileges).
  • Run this command with YOUR OWN values:
    rdpsign.exe /sha256 f428629df8fdaefc701ee0335e956edc9844b0aa “C:\Users\bubba\Desktop\MyServerConnection.rdp”
  • If rdpsign completes successfully, you will see the message “All rdp file(s) have been succesfully signed.”
  • Now, when that signed client is used to connect to its server the first time; the user will see the server name, etc.; and they will have to click on [Ok] the first time.
  • After that, future RDP connections will connect with no messages.

CBruce

And you need to sign the clients again each time that the certificate is renewed?

Yes. Since you will have a new Let’s Encrypt certificate when it is set to renew, you will need to copy the new cert to the RDP cert location in the server’s certificate store - and then perform the export and the rest of the steps each time.

Hmmm @mcdado… I never thought about it before, but you may be able to perform the RDP client script signing on a single client workstation - import the new cert on the rest of your client workstations - and copy the signed RDP script to those other client workstations. Not sure, but if it works it could save a tedious step.

CBruce

I bet a PowerShell expert can automate most of this process. I understand that Microsoft has exposed a significant amount of Windows configuration to PowerShell in one way or another. So I expect there could be a script made that takes care of most of these steps for you.

This limitation throws me off somehow… for me automating the server is one thing, automating n clients is another. Plus is not a situation where you enter the host and credentials on the fly and you can access securely, you’d need to have a signed .rdp file that expires whenever there’s a renew.
Also, I’d need to figure out how to sign macOS clients.

Thanks so much for the feedback @CBruce , soon I’ll be able to experiment myself when I get the local domain and DNS going.

@mcdado, since you are setting up a Windows Domain and Active Directory - you might want to look at using AD Group Policies to automate the distribution of the certificate to the client workstations:

Deploy Client Computer Certificates:
https://technet.microsoft.com/en-us/library/cc731242(v=ws.10).aspx

And IF a single signed RDP client will work when copied to other client workstations - you can also use Active Directory to deploy that signed RDP client file to the other workstations:

Using Group Policy Preferences for copying files:

Group policy preferences copy files:
https://social.technet.microsoft.com/Forums/windows/en-US/681e32aa-d7ed-4e35-99f3-020e09b35dec/group-policy-preferences-copy-files?forum=winserverGP

CBruce

1 Like