Secure Communications Between Azure Web Apps and Virtual Machines
Editor’s note: The following post was written by Visual Studio and Development Technologies MVP Thomas Ardal as part of our Technical Tuesday series with support from his technical editor, Microsoft Azure MVP Morten Christensen.
This post is a step-by-step tutorial on how to set up a secure connection between an Azure Web App and a service running on a Virtual Machine using Point-to-site VPN.
A couple of months back, I was looking for an alternative way of communicating securely from an Azure Web App to an instance of Elasticsearch hosted on a virtual machine. I had been using Jetty to secure Elasticsearch so far, using SSL and basic authentication. I originally implemented it this way, because of lacking possibilities to secure calls from a web app to a virtual machine. In the meantime, Microsoft implemented a feature called Point-to-site VPN, which (among other things) lets you setup a secure channel between resources like web apps and virtual machines.
A lot of examples and tutorials exists out there. Common for most of them is that they try to explain every possible use of Point-to-site, goes into too much detail about certificates or the like. After having played with P2S for a couple of days, I found out that setting it up in the right order, actually made most of the manual configuration redundant. In this post, I will show you the easiest possible solution for setting up a secure channel between a web app and a virtual machine through a virtual network.
If you have not already, create a new resource group for your application:
When created, add a new web app inside the resource group. The easiest way to do this is to navigate to your newly created resource group and clicking the Add button:
In the screenshot, I have created a new App Service plan to host the web app. When asked for “Pricing tier”, select “S1 Standard” which is required for Point-to-site VPN to work.
If this is the time where you start to think about what to code when you have read this post, please do not. The following step is probably the most important part of this tutorial. While you can easily create a virtual network through the Azure portal, creating it from your web app, will automatically set up all configuration needed, as well as exchange certificates and other boring stuff.
Go to your web app and enter the Networking Settings (click Settings and find the “Routing” section). In the top of the Network Feature Status tab, there is a VNET Integration section. Integrating our web app to a Virtual Network is exactly what we are trying to achieve here. Click the Setup link:
Remember when I told you to start focusing on the post? Well now is actually the time to dream off. Creating the resources needed for the VNET Integration can take quite an amount of time.
To make sure that everything is setup correctly, navigate to the virtual network by clicking the vpndemo-virtualnetwork resource in the summary:
On the virtual network tab, we now see an active Point-to-site connection. Since we have not added anything to the virtual network yet, there is no clients on the newly created gateway. Let us fix this by creating a new virtual machine. I am selecting the Windows Server 2012 R2 image, but this can be any OS:
Most of the configuration is straightforward. I have expanded the Network section to show how to put the virtual machine into the virtual network that was automatically created when setting up the VPN. Remember the vpndemo-virtualnetwork that we created in an earlier step? Since the Point-to-site VPN is configured to let the web app communicate with this network, that is where the new VM should go. A few things to note when creating the virtual machine- First make sure to select the Classic Deployment Model (not default selected), since Resource Manager don’t seem to be supported through the Portal yet. And for the configuration ensure that the right resource group is selected, so the VM is created in the desired group
Creating a virtual machine takes time as well, but once it is running, the virtual network now shows an active VPN connection:
If you do not see “1 clients” after the VM has been created, do not worry, once your web app and VM are both running, the active connection will show up (if configured correctly).
Time to install some software. In my case, I have logged into the virtual machine, installed Elasticsearch and allowed incoming requests on port 9200 in Windows Firewall. If you are not interested in using Elasticsearch, you can enable IIS on the VM instead and test using port 80.
To test that Point-to-site is set up correctly, I have created a small ASP.NET Web API app, which is able to proxy a request to Elasticsearch. The API controller is pretty simple and kindly borrowed from this post by Philip Cox:
This is of course not how you would expose the service running on the VM, but its fine for the initial verification to ensure that the web app actually discovers the VM.
Deploy the Web app to Azure using your favourite deployment method (Visual Studio, Git, Source Control integration etc.).
To find the internal IP address of the virtual machine, go to the virtual machine settings and select “Properties”:
Let us test the connection using the virtual machines private IP. Since Elasticsearch is listening on port 9200, the URL to test will be http://10.0.2.4:9200, but the port can be anything, as long as Windows Firewall accepts incoming connections on that port:
Well isn’t that just great! The web app is able to communicate with Elasticsearch on the virtual machine. Of course, no one else can access the service, since we never created an endpoint on the VM.
Using Point-to-site to secure communication between Azure resources, turned out to be not only easy to set up, but also extremely well-functioning. I have not experienced any problems, neither functional nor performance wise so far.
About the author
Ardal is a freelance software developer/architect and entrepreneur. He works at various customers as an external consultant alongside his work as a founder of a number of SaaS products. At 37 years old, he already has more than 14 years of professional experience as a .NET, Java, Mobile and web developer. Through his work at multiple companies and with multiple projects he’s had many different roles and experiences from hardcore programming to job interviews and training.