SSL termination with Azure App Gateway

When you explain Azure, and get to the load balancer function of Endpoints, you more often than not get the question if it can handle SSL termination to offload the web servers. The answer has up to recently been, no, it can’t. But with the new feature Azure Application Gateway you now have the possibility to to just that.

In this post I will show you how to how to create an AppGateway that fronts a set of high availability web servers that are hosted on Azure. The web servers will only use http and serve (pretty dumb and static) content and the AppGateway will be the point of access and also do the SSL termination. I will also show you how this config can handle auto-scale and replacement of current certificate.

Architecture

The architecure of the solution looks like the below picture, where we have several webservers behind an AppGateway that both acts as a load balancer and handles the SSL termination. The traffic to the AppGateway uses SSL/https and theArchitecture traffic between the AppGateway and the web servers are http on port 80 and is unencrypted, which means that the webservers will not waste precious CPU cycles to decrypt the request/response. The AppGateway can also use Cookie Affinity so that sessions from the client continues to be routed to the same webserver. If we don’t use cookie affinity, the AppGateway will use a pure round robin load balancing. We will disable cookie affinity to show that each request is routed to the next webserver.

Backend Address Pool

The AppGateway has a pool of back end addresses that it will route the traffic to. This can be Azure internal ip addresses in a Virtual Network or it can be urls that are either Azure hosted or public urls. If the Virtual Network is connected via a VPN to an on-premises network, this means that the urls can point to some internal webapp and AppGateway can be used as a mean to expose an internal webapp to the internel. In my example, I will just use a bunch of Ubuntu Linux servers running a very simple Node.js solution, since all I want is something that responds on port 80.

AppGateway probes all VMs in the backend address pool which means that machines that go bad will be put out of rotation until they responde positive on the probe again. You can also update the pool list, which means that you can dynamically scale according to your needs. We’ll look at that towards the end.

Create the AppGateway

The Application Gateway is not currently supported in any portal – new or current – so creating it means running a few Powershell commands. The new-AzureApplicationGateway command creates the gateway and here you specify familiar things like VM size and InstanceCount. VM size can be Small, Medium or Large, where the documentation says to avoid Small unless you are just testing.

new-appgateway-run

You also must put the AppGateway in a subnet of a VirtualNetwork and the recommendation is to let the gatweay have a subnet of it’s own. Not sure how many customers will tear up their VNet config and redo the ip address map, but it’s something to consider.

The XML configuration file

The actual configuration of the AppGateway is specified in an XML configuration file which you edit locally and then upload. The XML file contains five elements

  • FrontendPorts – what tcp ports to listen on, like 80/443
  • BackendAddressPool – list of VMs in the back end (ip addr or urls or a combination or that)
  • BackendHttpSettings – what tcp ports the backend VMs are listenng on, like 80, and if to use cookie affinity or not
  • HttpListeners – a parent to the FrontendPorts where you specify a certificate if the port is 443
  • HttpLoadBalacingRule – where you connect the listener, BackendHttpSettings and BackendAddressPool

Below is the xml config file I used in this example. I have two front end ports just to see that the AppGW is working on regular http. This is handy to troubleshoot problems with the cert, but in a real case, you should remove the HttpListener1 to make the AppGW only accept https.

xml-config-file

Create and upload Certificate

Before we upload the config to the AppGateway, we need to create and upload the certificate referenced in the HttpListener2 part of the config. The certificate you upload must be a pfx file. You can generate a self signed certificate via the makecert tool and then convert it to a pfx file using the pvk2pfx tool like this.

gen_cert

Once you have the pfx file it’s just another Powershell command to upload it

upload-cert-2

Upload the XML Config file

When all referenced certificates are uploaded, the xml config file can be uploaded. This step will fail if the certificate being referenced is not present.

upload-xml-config

Starting the AppGateway

Up until this point there is nothing tangiable in Azure. It’s just a bunch of config objects and nothing is started (which means the cost meter hasn’t start to tick either). By invoking the Powershell below, everything comes to life and AppGateway is activated.Because this involves starting VMs, this is an operation that will take some ~10-15 minutes.

start-appgw

Testing out the AppGateway

The url to the AppGateway is in the format {guid}.cloudapp.net and you can get it with the Get-AzureApplicationGateway Powershell command. Above you can see it as the DnsName value. The browser complains about the certificate being self signed, but that is expected.

SSL_roundrobin-2

Since my configuration disables cookie affinity, each request is routed to the next webserver and the response shifts from being from 10.4.2.4 and 10.4.2.5.

Scaling the backend pool of VMs

For backend pool of webserver I used two Ubuntu 14.04 Linux servers with a simple Node.js script running in a Cloud Services with in an Availability Set. Scaling out means two things; first create a more VMs and seconds change the config of the backend pool definition to reflect their presence.

vm-starting

The third VM gets ip address 10.4.2.6 and once it is up and running it needs to be added to the xml configuration file.

new-backendaddress-pool

To apply the new config you need to upload it again using the same Powershell command. This time the command will take a little bit longer since the AppGateway is running.

upload-xml-config-2

As soon as the configuration is uploaded, the third webserver is in rotation and will start responding to requests.

SSL_roundrobin-3

When it comes to scaling there are two strategies you can follow. Either you can pre-create all VMs you will need and set the backend address pool with their addresses and then shutdown VMs that should not be working. The AppGateway will then fail to probe the VMs not available and will put them out of rotation until it replies on the probe. The other strategy is to create the VMs just-in-time and to update the config at the same time. If you can deploy your web application reasonably fast, this might be a better option. If deployment is complex and takes time, the pre-creation strategy will work better.

Rotation of certificates

Rotating a certificates is done via first uploading the new certificate file to the AppGateway and then update the SslCert element under the HttpListener element in the xml config file and upload the config again. Here is the second large benefit of using AppGateway since you rotate the certificate by invoking 2 Powershell commands against one target. You don’t have to do it on every VM in the backend pool.

Scaling the AppGAteway

Scaling the AppGateway can be done via the Powershell command Update-AzureApplicationGateway where you can change the InstanceCount. In the below example the AppGateway is scaled from 2 to 3 instances.

Scale-appgateway

References

AppGateway dokumentation
https://azure.microsoft.com/en-us/documentation/articles/application-gateway-create-gateway/

Sources

Zip file containing stuff I used to create this architecture
http://data.redbaronofazure.com/public/AppGateway.zip