How-to Guide LetsEncrypt a 2012 R2 Web Application Proxy


With Chrome (and presumably Edge and Firefox in the future) beginning to move towards an "SSL preferred" world (and I anticipate a future move to "enforced SSL"), it's beginning to look like HTTPS will be required for most sites.

Microsoft-centric environments generally have websites hosted on IIS - possibly plain webs, but also LOB applications, Exchange, SharePoint etc (yes, there's the cloud - but that doesn't suit all organisations).

LetsEncrypt are moving towards production-ready status, offering free certificates with short expiry and automated renewal. Free, fully trusted certificates are available today, and there are Windows tools to generate and renew.

Wouldn't it be nice if it were possible to do certificates for free, and still comply with security requirements (like reverse proxies in a DMZ for external users accessing websites)?

With that in mind this guide presents an architecture and approach for ongoing support for SSL certificates that's scalable to dozens or hundreds of web applications and websites, can provide HA for applications and the reverse proxy layer, and takes little more time to set up than HTTP.

Request Routing

Part of what we're going to do is route certain requests to different servers. This allows for a server to host just the certificates and answer the HTTP requests from the LetsEncrypt servers, while existing web servers and application servers service all other requests.

This diagram shows the data flows for HTTP and HTTPS:

ARR+WAP Request Paths.png

Server Architecture

This guide assumes a traditional network environment - an internal zone for protected servers, a DMZ hosting servers that provide access to (some) internal systems, and firewalls between each zone. The distinction between a three-legged firewall and two separate firewalls does not impact on the solution.

IIS+WAP Architecture.png

Some assumptions about this environment for this guide:
  • We assume the environment must be highly available;
  • Shared content is stored on a file server cluster;
  • IIS servers are already configured to use a Central Certificate Store on the file server cluster, and the share is \\FSCluster\SSLStore;
  • Load balancers are not shown;
  • The Certificate Management host is separate (and presumably a VM) so that the configuration of web servers can be stateless;
  • We require (or desire) SSL end to end - not only for security, but to simplify the web applications (which may depend on the host header to create links or content, for example);
  • We have split-horizon DNS so that all public names resolve externally to the reverse proxies (or firewalls, if you're using NAT) and internally to the web servers;
  • We have a domain environment so that we can use a single user/password combination across all servers.
LE Assumptions and Implications

The LE architecture is not well suited to scaled or HA environments, and this drives some of the architecture and configuration.

Most critically, the ACME protocol generally assume that a file (or set of files, one per name) can be written to the web server as part of the issuance and validation process.

In a distributed environment, simple LE clients are not always capable of handling this - for example, if you wish to deploy a certificate to a set of half a dozen Exchange CAS hosts, in two datacenters - that's ... not easy. Instead, we're going to build this into the certificate management server.

Reverse Proxy - Base Environment

We're going to build and configure the reverse proxy to support obtaining and installing certificates. For this we need the IIS Server role, but only the minimum role services to support the reverse proxy:
  • Web-Application-Proxy
  • Web-Server
  • Web-WebServer
  • Web-Common-Http
  • Web-Http-Errors
  • Web-Static-Content
  • Web-Health
  • Web-Http-Logging
  • Web-Mgmt-Tools
  • Web-Mgmt-Console
Once the role services are installed, open the IIS Management Console and use Web Platform Installer to install the Application Request Routing module - 3.0 was current at time of writing. It will add dependencies such as URL Rewrite. If you cannot run WebPI for the install you can install the components manually.

We need to create two server farms. One will contain all the Certificate Management servers (all one of them) and one will contain the servers hosting real content for the web application.


Find the Server Farms node in the IIS Management console, and click Add Server Farm on the right.


I recommend using the site name as the farm name; it makes much of the rest of the UI more logical. However it is completely arbitrary.


Add the server(s) hosting the web application. Optionally, if necessary, change the httpPort and httpsPort to match the target webserver.


Repeat the process for the certificate management farm (although since this will serve only the LE challenges, select an appropriate name for the farm). You will see the following warning, because both Rewrite rules will process all requests. We'll fix that in a moment.


Navigate back to the server, now, and in the centre select URL Rewrite from the IIS group.


Ensure the Cert Management rule is at the top of the list of inbound rules, then edit the rule.


Change the Pattern to .well-known/acme-challenge/* and ensure the checkbox "Stop processing of subsequent rules" is ticked. Do not preface the pattern with the initial "/" - the rule will not work.

That should permit basic access to the certificate and host validation URLs.

Building the LE environment

The next task will be to configure a server (org-certs.example.com) to obtain all the certificates and store them in the central store.

Start by creating a domain user - I often use sa- as a prefix for the logon name of a service account, so this might be DOMAIN\sa-CertMgmt or similar. Use a logon name and secure password suited to your environment.

Since you'll need an email address for LetsEncrypt, you may choose to assign that email address to the same Windows account to keep it consistent.

You will need to grant it appropriate rights to the central certificate store share, admin rights to the certificate management server and administrative or delegated rights to your reverse proxies, at least. Use whatever process or standard matches your environment (DSC, GPO etc).

Log on to the certificate management host as your service account. The LE client will create files under the AppData\Roaming profile directory to store configuration data, so you really need to run as the service account.

First, you'll need to install the Web Server role - you need enough to serve static files, so install only these role services:
  • Web-Server
  • Web-WebServer
  • Web-Common-Http
  • Web-Http-Errors
  • Web-Static-Content
  • Web-Health
  • Web-Http-Logging
  • Web-Mgmt-Tools
  • Web-Mgmt-Console
Install and Configure the LE Client

Download the Let's Encrypt Simple Windows Client and extract to a folder - perhaps C:\LetsEncrypt but again, use your local environment standards.

Edit letsencrypt.exe.config with your preferred text editor, and change the PFX password from empty to something secure - this password must match the password you configured for certificates in the Central SSL store on your web server farm.

      <setting name="PFXPassword" serializeAs="String">
        <value />
      <setting name="PFXPassword" serializeAs="String">
Run an Administrative command prompt and change to the folder containing the LE client:

C:\Windows\System32> cd \LetsEncrypt

Create the .well-known and acme-challenge directories, and copy the custom web.config into the acme-challenge directory:

C:\LetsEncrypt> mkdir C:\InetPub\WWWRoot\.well-known\acme-challenge
C:\LetsEncrypt> copy Web_Config.XML C:\InetPub\WWWRoot\.well-known\acme-challenge\web.config

Run the LE client for the very first time, to complete a small amount of setup. You'll be asked to enter your email address and agree to the user agreement; then create a manual request for the appropriate hostnames:

C:\LetsEncrypt> letsencrypt --san --centralsslstore \\FSCluster\SSLStore
Let's Encrypt (Simple Windows ACME Client)
Renewal Period: 60
Certificate Store: WebHosting

ACME Server: Boulder: The Let's Encrypt CA
Using Centralized SSL Path: \\FSCluster\SSLStore
Certificate Folder: C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org

Getting AcmeServerDirectory
Enter an email address (not public, used for renewal fail notices): certmgmt@example.com
Calling Register
Do you agree to https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf? (Y/N) Y
Updating Registration
Saving Registration
Saving Signer

Scanning IIS Site Bindings for Hosts
IIS Version not found in windows registry. Skipping scan.
No targets found.

W: Generate a certificate via WebDav and install it manually.
F: Generate a certificate via FTP/ FTPS and install it manually.
M: Generate a certificate manually.
A: Get certificates for all hosts
Q: Quit
Which host do you want to get a certificate for: M
Enter a host name: myweb.example.com
Enter all Alternative Names seperated by a comma myweb.example.com,myweb2.example.com
Enter a site path (the web root of the host for http authentication): C:\InetPub\WWWRoot

Authorizing Identifier myweb.example.com Using Challenge Type http-01
Writing challenge answer to C:\InetPub\WWWRoot\.well-known/acme-challenge/G0FRZLnDDL840KZ2ubj1TiGFQjQ-X_t6Rk2EFRQ7HJ8
Answer should now be browsable at http://myweb.example.com/.well-known/acme-challenge/G0FRZLnDDL840KZ2ubj1TiGFQjQ-X_t6Rk2EFRQ7HJ8
Submitting answer
Refreshing authorization
Authorization Result: valid

Authorizing Identifier myweb2.example.com Using Challenge Type http-01
Writing challenge answer to C:\InetPub\WWWRoot\.well-known/acme-challenge/weihgzBHIf4zZuujRzaabo3qf-DY0O1LA_DKJmMmfpo
Answer should now be browsable at http://myweb2.example.com/.well-known/acme-challenge/weihgzBHIf4zZuujRzaabo3qf-DY0O1LA_DKJmMmfpo
Submitting answer
Refreshing authorization
Authorization Result: valid

Requesting Certificate
Request Status: Created
Saving Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\myweb.example.com-crt.der
Saving Issuer Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\ca-009813F47513E5750B43E7431E971E44BD-crt.pem
Requesting Certificate
Request Status: Created
Saving Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\myweb.example.com-crt.der
Saving Issuer Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\ca-009813F47513E5750B43E7431E971E44BD-crt.pem
Host: myweb.example.com
Saving Certificate to \\FSCluster\SSLStore\myweb.example.com.pfx
Host: myweb2.example.com
Saving Certificate to \\FSCluster\SSLStore\myweb2.example.com.pfx
WARNING: Unable to configure server software.

Creating Task letsencrypt-win-simple httpsacme-v01.api.letsencrypt.org with Windows Task Scheduler at 9am every day.

Do you want to specify the user the task will run as? (Y/N) N
Renewal Scheduled Manual myweb.example.com (C:\InetPub\WWWRoot) Renew After 11/05/2016
Press enter to continue.

Congratulations, you now have a certificate for your web server. Now we need to import it to the reverse proxy.

Reverse Proxy - Site Publishing

Just to recap, we now have:
  • A reverse proxy sending our browsers to the main web servers for content, and sending the LE certificate processors to the certificate management server
  • The LE client generating and renewing certificates on the certificate management server
  • Certificates and private keys stored on the Central Store with a known, strong password
  • Main web servers using the central store for SSL certificates and keys
We now need to configure the Web Application Proxy to handle SSL requests. Build your ADFS servers, and complete the basic configuration of the WAP role using your ADFS certificate.

Load the Remote Access Management console and select the server.


On the right hand side, click Publish.


Click through to the Preauthentication tab.


Unless you're publishing Exchange, SharePoint or another OAuth2 application, you'll want to choose Pass-through, then Next.


Name the application according to the URL. For our guide, this will be myweb.example.com. Specify the external and internal URLs for the website - the recommendation here is that they match. This is where that assumption about split-horizon DNS is really important - the name in the backend server URL must resolve internally to the right server.

For the certificate, select your ADFS certificate for now. We'll replace that with our scheduled script (below).


If you're going to publish a stack of applications, copy the PowerShell snippet for reuse. Click Publish.


Close the next window once it's complete.


Repeat this process for myweb2.example.com (with appropriate changes, naturally).

Automating Certificate Updates

Time for some PowerShell scripting. We're going to add a script to the Certificate Management server that:
  • Finds all the certificates on the Central SSL Store
  • Copies them to the Reverse Proxies
  • Imports the certificates and keys to the LocalMachine store
  • Reconfigures the web application to use the correct certificate
The script is below. You'll need to change the variables defined at the top of the script, but otherwise it should "just work". Post in the discussion thread for this guide if it doesn't; include any error messages or output.

## LetsEncrypt Integration for WAP
## David Rawling, 2016
## V-1.0

# The network location of the central SSL store - PFX files
$CentralStore = "\\FSCluster\SSLStore"
# The local path on each WAP to store certificates
$TargetPath = "C:\Certificates"
# The network path to the directory listed above
$SharePath = "\C$\Certificates"
# The plaintext password used for the PFX files
$Password = "7wfRW2hajUMAtV04Lvb6ugxmYQXpBZHPkIEl5sN1ynzKeSJiCq93O8FGdTcorD"
# An array of the reverse proxy server names (use @("SRV1","SRV2") etc for multiples)
$TargetServers = @("REVPROXY")

$PFXPassword = ConvertTo-SecureString -String $Password -AsPlainText -Force

ForEach ($Target in $TargetServers) {
  New-Item -ItemType Container ("\\" + $Target + $SharePath) -ErrorAction SilentlyContinue
  Copy-Item $CentralStore\* ("\\" + $Target + $SharePath) -Recurse

  $TargetSession = New-PSSession -ComputerName $Target -Authentication Kerberos

  Invoke-Command -Session $TargetSession -ScriptBlock {
  param($TargetPath, $PFXPassword)
  $CertFiles = Get-ChildItem -Path $TargetPath -Filter '*.pfx'
  ForEach ($CertFile in $CertFiles) {
  $Certificate = (Import-PfxCertificate -FilePath $CertFile.FullName -Password $PFXPassword -CertStoreLocation Cert:\LocalMachine\My -Verbose)
  $Thumbprint = $Certificate.ThumbPrint
  ForEach ($DNSName in $Certificate.DnsNameList) {
  $Subject = $DNSName.Punycode
  Get-WebApplicationProxyApplication -Name $Subject -Verbose | Set-WebApplicationProxyApplication -ExternalCertificateThumbprint $Thumbprint -Verbose
  } -ArgumentList $TargetPath, $PFXPassword

  Remove-PSSession -Session $TargetSession
Run this on your Certificate Management server, as your Cert Management service account, with Administrative rights. When it's completed, assuming no errors, refresh and check the published applications on the reverse proxies - they should now use the correct certificates.

Permit SSL traffic from the Internet to your reverse proxy servers and you should have working SSL.


In this guide we configured web servers, Web Application Proxy servers and a certificate management server to automatically obtain and install certificates from LetsEncrypt.
First release
Last update
5.00 star(s) 1 ratings

More resources from DavidRa

Latest updates

  1. Language fixes and minor corrections

    Now that I've had time to "forget" what I wrote I was able to spot a couple of minor errors. I'm...

Latest reviews

Great article David.