Last Update: Sep 04, 2024 | Published: Jan 26, 2018
This post will answer a question that I always get when I am teaching the subject of network security groups, “How do I block Internet access for my Azure virtual machines?”
Every Azure virtual machine has direct connectivity to the Internet via a NAT IP address by default and that access is unfiltered.
Tip: That NAT IP address is the public IP address of the load balancer or NIC if the virtual machine is assigned to either one. You can use this for creating firewall rules to allow inbound access at remote sites for your Azure virtual machines.
Some organizations do not like any machine having such access. For example:
One reason might be to stop malware from activating after it reaches out to a controller on the Internet. Another reason is to stop data leakage.
One can use a number of solutions for accomplishing the above but in this post, I will show you how to do this using Network Security Groups.
The demand to “block all outbound traffic” is easily accomplished using Azure’s Layer-4 (TCP/UDP/etc) solution, Network Security Groups (NSGs). You create a single outbound rule to Deny traffic to the service tag (or location) of Internet.
Within a month or two, you should get a call from your boss/client, not to thank you, but to demand to know why their virtual machine-based services are no longer available to users/customers. You’ll scratch your head, log into the Azure Portal and find that your virtual machines cannot boot up.
When you create a virtual machine in Azure, you probably take the wise step of doing things like enabling Diagnostics or Boot Diagnostics. Both of these troubleshooting features leverage a storage account:
When a virtual machine with either of these services enabled boots up, the virtual machine must have access to the storage account. And here’s the gotcha: The Internet tag included all IP ranges of the Azure services because it was neither a Load Balancer probe or the Virtual Network (the other two service tags or locations that were available). Without that access, the virtual machine would not boot up.
Note: Boot Diagnostics now includes a new text-based serial output full of useful information for Windows Server virtual machines.
What if you needed to block outbound traffic to the Internet but needed a solution to allow your virtual machines to boot up? Sadly, this was complicated. You would have to download the frequently updated list of IP addresses/ranges that are used by Azure and create exceptions to allow traffic to the Azure services.
This was cumbersome, fragile, probably didn’t scale well, and a nightmare to troubleshoot, not to mention that whatever script solution you came up with would have to be scheduled to run on a frequent basis. The kinds of organization that require outbound traffic to be controlled are probably the same organizations with strict change control rules, such as pharmaceuticals, and I cannot imagine what the bureaucracy around this would be been like.
Microsoft announced at Ignite that the location/Service Tag feature of NSGs would be updated to solve this problem. In January, Microsoft made those changes generally available. The old service tags still exist:
The following service tags were added along with the GA announcement:
The new service tags for Azure services are dynamically updated by Microsoft. For example, if Microsoft adds new service fabrics for hosting Azure SQL in East US, the IP addresses used to access those services will be added to the SQL.EastUS service tag by Microsoft. I don’t have to change anything; I continue to use the same service tag. That means that:
How can we use service tags to block outbound traffic to the Internet for our virtual machines now? It’s easy.
First, you will create the Deny-to-Internet rule:
This Deny-AllInternet rule is set with the lowest possible user-defined priority, 4096. This leaves us plenty of capacity to create exception rules. The essential rule to create now is a higher-priority one that will allow access to Azure storage. You could allow access to all storage in all Azure regions but it would be better to restrict that access to the same region as the virtual machine, for example, Storage.EastUS. In my case, the virtual machine is running in West Europe (Amsterdam):
Now my virtual machine cannot talk to the Internet but it can talk to Azure Storage.
Note: I have seen a blog post that says this exception is required for Azure virtual machines to be protected by Azure Backup if Security Center’s Just In Time Virtual Machine Access is enabled.
What if the virtual machine also must talk to Azure SQL? In that case, we add another exception:
With these Service Tag-based rules, you can easily control access to the Internet while enabling Azure virtual machines to operate correctly with a minimum amount of effort or change.