This would apply to Azure App Services too.
This is an interesting feature. To me it resembles or provides the ability to force tunnel. The implementations of forced tunneling I have seen have typically been configured using route tables. Where the route table is a matrix of IP addresses (see Figure 6) that instructs TCP where to forward the packet transmission to next, aka a hop. However, when you run on a PaaS environment without VNET integration, you typically wouldn’t expect to have access to routing tables, at least this is what I have seen up to now. So, this feature is possibly to provide the entry point for such a purpose. Instead of making VNET routing table configurations, you link the PaaS to a Virtual Network (VNET) and then use NSGs for the given Subnet or perhaps the Application security groups (ASG).
Either way, this is how you could force/restrict the traffic for example from an App Service or from a Azure Function to any desired node. By node I mean a machine connected to the internet, intranet or private network which helps route you network traffic. How you would do that is greatly dependent on your requirements, answer “Why do I want to force tunnel?” then you can proceed on to how you need to implement it. One example I can provide is that a company may want to insure all traffic coming from all of their IT resources which goes onto the internet flows through a single server or group of servers. You could force that traffic route by the implementation of an Outbound NSG rule that forces such behavior by disallowing any other. Once you get a PaaS offering bound to a VNET managing traffic can be accomplished by either a route table or NSGs. Again, the one you choose is based on the requirements of your desired solution.
The following is a brief overview of how I configured a solution that worked when I have WEBSITE_VNET_ROUTE_ALL set to 1 with a goal of blocking all outbound internet connectivity. I used an Azure Function and when I was doing this, initially I had some problems with deployments not working. Unable to deploy. Deployment successful but changes are not visible. The reason was that my NSG on the Subnet was blocking a call to Sync Trigger so the new code wasn’t loaded into the process. I cover that more later. Here are also some nice instructions which cover a similar scenario which I have done here: Integrate your app with an Azure virtual network
There are two different types of VNET integration:
- Regional VNET Integration – connecting to VNETs in the same region
- Gateway-required VNET Integration – connecting to VNETs in another region
The one I will be using here is Regional VNET integration. The steps I took to perform this follow.
1. Create VM and VNET with 2 subnets
2. Create Azure Function and connect to VNET/Subnet
3. Publish and Test the Azure Function
4. Add WEBSITE_VNET_ROUTE_ALL=1
5. Testing
It really isn’t so hard if you have the instructions to follow. I didn’t find any, but I did ask a few people who help me make progress.
Create VM and VNET with 2 subnets
An Azure VM is not necessary to use WEBSITE_VNET_ROUTE_ALL but as I didn’t have a Site-to-Site or other service to test my VNET connection with I created one. This VM is what I will use for testing the connectivity from my Azure Function. Without something to connect to, I couldn’t really know if my solution was failing because of a WEBSITE_VNET_ROUTE_ALL configuration problem or if the VNET connection wasn’t working. As seen in Figure 1, I created an Azure VM.
Figure 1, Azure VM creation
A VNET is required to run an Azure VM, the creation or configuration of a VNET is part of the Azure VM creation process. I created a new VNET named CSHAPRGUITAR-VNET which container two subnets CSHARP and GUITAR. I added the VM to subnet CSHARP and will use the GUITAR subnet when I configure VNET integration with my Azure Function. The subnet used for configuring VNET integration with an App Service or an Azure Function must be empty. Figure 2 shows how the VNET and subnet configuration looked for my Azure VM.
Figure 2, configuring an Azure VNET for my Azure VM with two subnets for my Azure Function
After a few moments I created an Azure Function and integrated it with a VNET.
Create Azure Function and connect VNET/Subnet
To use the VNET configuration the App Service must run in the Standard or greater pricing tier. For an Azure Function you must be in dedicated mode, which is Standard or greater or Elastic Premium. Figure 3 shows that I create the Azure Function in the same Subscription and Resource Group as the Azure VM and VNET. I also created it in the same region as well, which is not shown.
Figure 4, creating an Azure Function for VNET integration
Once the Azure Function was created I configure the VNET integration for it. Notice in Figure 5 that I used the GUITAR subnet which exists in the CSHARPGUITAR-VNET as expected.
Figure 5, configuring VNET integration for use with an Azure Function and WEBSITE_VNET_ROUTE_ALL
By default Azure route tables will affect all IP address ranges found in RFC1918. Here is a table which shows the IP address ranges. Figure 6 shows an exampke of the possible default Azure route table settings.
Start IP Address | End IP Address | Prefix |
10.0.0.0 | 10.255.255.255 | 10/8 |
172.16.0.0 | 172.31.255.255 | 172.16/12 |
192.168.0.0 | 192.168.255.255 | 192.168/16 |
Figure 6, default Azure Route Table settings
Once you click on the save button to apply your VNET configuration, take w short break, there is a lot going on in the background to make this happen. Wait, be patient. Test VNET connectivity with the Azure VM in Subnet CSHARP (172.19.1.0/24). All traffic, by default, between Subnets in the same VNET is allowed as seen in Figure 7. Since both subnets, CSHARP and GUITAR are in the same VNET, connectivity should work by default. You can check that by looking at the Network Security Group (NSG).
Figure 7, default Azure VM Network Security Group (NSG)
After installing IIS on my Azure VM, I then accessed the KUDU/SCM console, which I explain here, of my Azure Function and tested the connectivity using CURL. Notice in Figure 8 shows that I use the internal IP address of the Azure VM in subnet CSHARP.
Figure 8, using CURL to test VNET connectivity from an Azure Function to an Azure VM
I was not able to successfully connect to the Azure VM Public IP address from the Azure Function SCM/KUDU console. At first that seemed odd, but makes sense because if I can use an internal IP why would I want to use the public one? I didn’t test it to see if it is possible without the VNET configuration, but I was able to CURL to other public internet sites.
Publish and Test the Azure Function
I then published an HTTP triggered Azure Function, I explain how did this here. I also wrote a short lab here. Figure 9 illustrates how I triggered it and that it was successful
Figure 9, trigger an Azure Function, HTTP Trigger using CURL
At this point outbound traffic from the Azure Function is not forced into the VNET. To change that, you must add the WEBSITE_VNET_ROUTE_ALL application setting.
Add WEBSITE_VNET_ROUTE_ALL=1
Add the WEBSITE_VNET_ROUTE_ALL application setting to the Azure Function, it should be the same for an Azure App Service. Set the value to 1 to enable, Figure 10 illustrates how that look.
Figure 10, enable WEBSITE_VNET_ROUTE_ALL on an Azure Function, App Service
I then performed the following tests.
Testing
Tests 1 – 5 I performed using the default NSGs. Test 6 was performed after the configuration of the Outbound NSG as shown in Figure 11.
Test | Result |
1. Test Public Internet outbound Azure VM (Subnet: CSHARP) | |
2. Test Azure Function | |
3. Test connectivity to Azure VM from Azure Function SCM/KUDU | |
4. Test connectivity to Public Internet from Azure Function SCM/KUDU | |
5. Test deployment | |
6. Deny Outbound Internet / allow VNET | —- |
Test Public Internet outbound Azure VM (Subnet: CSHARP) | |
Test Azure Function | |
Test connectivity to Azure VM from Azure Function SCM/KUDU | |
Test connectivity to Public Internet from Azure Function SCM/KUDU | |
Test deployment |
Notice in Figure 11, I use a Service Tag instead of an IP address or IP range. Service Tags should be used instead of IP addresses for Azure hosted resources. This will remove the need for you to find which IP address you require. Most of Azure specific resource IP addresses would be internal, not easy to find, might change and would require maintenance. Service Tags are maintained by Microsoft and will contain all resources required for the selected purpose. Also notice in Figure 11 that I include both AppService.WestEurope and AppService. This is done simply to call out the fact that in many scenarios you can isolate the traffic restrictions to a specific region. Since my Azure Function exists in the West Europe region, I can restrict outbound calls to AppService features within that specific region. If I needed access to all regions, then I could use the global AppService Service Tag.
Figure 11, NSG for an App Service with WEBSITE_VNET_ROUTE_ALL
I hope you found this useful. HTH