Setting up an SSTP VPN on Windows Server with LetsEncrypt

Setting up a VPN on Windows Server for remote access to company resources comes up often enough, and a great deal has been written on the subject online.

However, back when I first went through the whole process, I found it time-consuming to sift through all the outdated information floating around, so I created this document for personal reference. I've had the opportunity to test them out on a number of fresh installs, and worked out a bunch of kinks that way.

These instructions assume a brand new install of Windows Server 2016, but they should be easily adaptable to other scenarios.

Installing the Necessary Software

IIS and RRAS

In Server Manager, Manager → Add Roles and Features, check Remote Access and Web Server (IIS).

Under the Features pane, select Remote Server Administration Tools and all submodules, and under Remote Access Role Services, select DirectAccess and VPN and Routing.

Install.

win-acme

Grab a copy of win-acme from Github; we'll be using it to streamline the requesting of SSL certificates from LetsEncrypt.

Setting up the Routing and Remote Access Service

First, we must get RRAS set up.

  • Run rrasmgmt.msc.
  • Right click server → Configure → Custom Configuration → VPN Access & Demand-dial connections
  • Start the service
  • Right click the server → Properties
  • IPv4 tab, select static address pool and choose an appropriate IP range for VPN clients (e.g. 192.168.26.0 — 192.168.26.50)

Next, ensure that the Default Web Site host in IIS has an HTTPS binding, and furthermore has its Server Name Identification box unticked — the host used for an SSTP VPN must not require SNI.

To begin, we should get rid of any certificates for the VPN host.

$ $hostname = "vpn.company.com"
$ Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match $hostname} | Remove-Item

Typically, certificates for IIS are stored in the WebHosting certificate store. However, RRAS can only use certificates under the Personal certificate store, so we must ask win-acme to place the certificate in the Personal store explicitly.

$ ./letsencrypt.exe --plugin iisbinding --manualhost $hostname  --certificatestore My --notaskscheduler

Then, we can fetch a PowerShell object referencing our certificate. By default win-acme removes old (expired) certificates when requesting a new one with the same host, so we can just filter by hostname.

$ $cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match $hostname}

Finally, we can import the RRAS module, and set our RRAS cert to the one we just created.

$ Import-Module RemoteAccess
$ Stop-Service RemoteAccess
$ Set-RemoteAccess -SslCertificate $cert
$ Start-Service RemoteAccess

LetsEncrypt certificates expire every 3 months, so it's a good idea to make this script run periodically in Task Scheduler, so that you're not faced with unexpected VPN outages.

Next, since RRAS doesn't start up by default on a machine boot, we should make it do so,

  • Open up Services
  • Find the Remote Access Connection Manager service, right-click → PropertiesStartup type: Automatic

Testing the VPN

Now, you may set up the VPN on a Windows machine, and attempt connecting. The VPN should connect, without any connectivity to the internet or the host machine. If the VPN immediately disconnects upon a connection attempt, you can use the rasdial (rasdial /? for usage help) command in a command prompt on the client to get more detailed error information than from the regular Windows interface.

At this point, you may or may not be able to ping the host machine from your client when connected to the VPN (you can use ipconfig /all on the host to determine its VPN IP, and try ping-ing it from the client).

Note that you will not be able to access the internet. To fix this, you must configure your client not to attempt to use the server gateway (because it doesn't exist). Open the Network and Sharing Center, and click into Change adapter settings.

Right-click the VPN connection you just created, and select "Properties". Switch to the Networking tab. Select the Internet Protocol Version 4 (TCP/IPv4) list item, then click the Properties button. Click Advanced, and uncheck Use default gateway on remote network.

Troubleshooting

VPN user must be allowed to dial-in

  • Run mmc.exe
  • Add the Local Users and Groups snap-in from the File menu
  • Click into your user account, then right-click Properties
  • Dial-in tab, Allow access under Network Access Permission

Network Policy Server must allow VPN connections

If you have NPS enabled, you will have to configure it to allow VPN connections.

Under the NPS snap-in from mmc.exeAdvanced ConfigurationNetwork PoliciesGrant access to both policies relating to VPN connections (they are deny by default).

Host machine must be discoverable

  • Open up the Network and Sharing Center
  • Click Advanced sharing settings
  • Expand the Private and Guest or Public groups, and turn on Network Discovery and File and printer sharing on both

Wrapping Up

At this point, clients should be able to connect to the VPN host, and any file shares created on it should be mountable. A minor caveat to be aware of is that LetsEncrypt certificates expire every 3 months, so you must either have a reminder in your calendar to renew the certificate, or have a scheduled script to request a new certificate and reconfigure RRAS to use it.