In my lab I have a gateway server that is responsible for both DirectAccess and RD Gateway operations.

Since I only have one external IP, I sit behind a NAT (or two). In order to be able to do both DirectAccess (DA) and RD Gateway (RDG), I need to use the Web Application Proxy (WAP) feature from Server 2012 R2’s Remote Access role.

See: https://technet.microsoft.com/en-us/library/dn383662.aspx

The rough network path to the lab is as follows:

[Internet] <-> FW1 <-> [DMZ] <-> FW2 <-> [LAB]

The DA server and RD gateway sit inside [LAB]. I have the RD gateway installed elsewhere inside [LAB]. I published the RD Gateway through WAP in order to have both DA and RDG available on the same public IP on port 443.

The beauty of WAP is that it can coexist with DA and VPN features on the same Server 2012 R2 instance. In fact, installing it takes over the 443 port and handles requests accordingly.

Initially, I had setup DirectAccess using a certificate issued by my internal PKI. It wasn’t trusted publicly but the machines accessing DA are domain joined so this wasn’t an issue.

RDG connections are rejected if the gateway’s certificate is not trusted. So if I try to use RDG from a non-domain machine the connection would fail. Unlike direct RDP connections there is no option to “connect anyway” if there is a certificate issue.

Cue my shiny new StartSSL Let’s Encrypt certificate.

I went through the DiretAccess wizard and replaced the IP-HTTPS certificate in Step 2 > Network Adapters, saved and re-applied the configuration. DirectAccess still worked, but it was using the old certificate (??)

I could see the updated certificate when I ran this in PowerShell:

PS C:\> Get-DaServer

IIS is not used as the listening service for 443, so it wasn’t obvious why it was still serving the old certificate. The Remote Access GUI had no option (besides the DA wizard) to modify the certificate. WAP only had Publish and Remove functions.

It turns out DA and WAP use HTTP.sys to bind to 443. When I tried to edit a published WAP app (RDG in this case), I could see it using the old certificate.

So I figured, publishing a new app using the new certificate would fix my problem… Nope. It was still serving the old certificate…

Alright… time to dig into SSL bindings:

PS C:\> netsh http show sslcert

What I’m looking for here is the binding for 0.0.0.0:443 ([::]:443) and potentially a [public.host.name]:443 as well.

The output confirmed that the bindings for 0.0.0.0 and [public.host.name] had the old certificate. Curious enough the IPv6 binding [::]:443 had the new certificate. (bug?)

I made a note of the Application Id for the 0.0.0.0:443 binding, as I’ll need it later.

First I will remove the bindings for the old certificate and re-bind using the new certificate hash:

PS C:\> netsh http del sslcert ipport=0.0.0.0:443
PS C:\> netsh http del sslcert hostname=[public.host.name]:443
PS C:\> netsh http add sslcert ipport=0.0.0.0:443 certhash=[new certificate hash] appid="[appid guid]" 
PS C:\> netsh http add sslcert hostname=[public.host.name]:443 certhash=[new certificate hash] appid="[appid guid]" certstorename=my 

… and restart relevant services:

PS C:\> Restart-Service iphlpsvc
PS C:\> Restart-Service remoteaccess

My external certificate finally changed to the new one and DA/WAP/VPN were working just fine. As long as the public.host.name doesn’t change, the clients won’t notice the swap.