Time and time again I’ve seen Network Security Groups configured incorrectly, misunderstood or sometimes completely omitted! The intention of this post is to clear up some of the confusion and to define some network security group best practices.
What are Network Security Groups (NSGs)?
NSGs are a method in Azure networking to filter network traffic. They are free Azure resources and can be assigned to Virtual Machine network interfaces (NICs) or Virtual Network Subnets. They contain lists of security rules (similar to a firewall) either ALLOWING or DENYING traffic in/out of that NIC/Subnet. These rules follow a list of priorities.
Default Rules
All network security groups contain the following default rules:
By default therefore, an NSG will allow all traffic with either the ‘VirtualNetwork’ or ‘AzureLoadBalancer’ tag inbound. The ‘VirtualNetwork’ tag means ALL Private traffic, whereas the LoadBalancer tag allows Azure Load Balancer traffic inbound (so for example if you had a Public Load balancer in front of a number of VMs).
Outbound all private traffic and Internet traffic is allowed (‘VirtualNetwork’ and ‘Internet’ Tags respectively).
Everything else is denied.
Best Practices
By default you can see that the security rules are pretty basic and provide little protection – they allow ALL private traffic inbound and outbound on all ports and really only offer protection from the public internet (so a rule will need to be written to allow public Remote Desktop to a VM, for example).
Having said that, having an NSG assigned to a NIC or subnet is still better than not having one at all. If you don’t have any NSGs assigned to VM (or other network service) then there is no filtering at all from either private or public traffic.
One NSG per Subnet
The first thing I would recommend is to create Network Security Groups for every subnet in any VNet you deploy. Use separate, individual NSGs for each subnet (rather than associating a single NSG with multiple subnets or an NSG per NIC). This allows you to write specific rules for each subnet, and if a rule needs to be modified, it will only affect the one subnet it is attached to.
Add Specific Inbound rules and a Deny Rule
Secondly, I highly recommend overriding the default rules with a manually defined DENY_ALL rule. I then create an AllowLocalSubnetInbound rule (to allow intra-subnet traffic) and then define custom rules from outside the subnet to the ports required. This is great deal more secure than the default ruleset:
Note you will also get a warning when creating this DENY_ALL Rule that it will affect LoadBalancer connectivity. If Azure Load Balancer is a requirement, simply create a LoadBalancer rule above your DENY_ALL.
Remember also priorities are important – Lower Priorities are evaluated before higher priorities (hence the default rules at very high priorities are overridden by the DENY_ALL rule created). Create your DENY_ALL rule at a high enough priority to be able to add as many custom rules as you require above it.
Common Mistakes
I often see rules written in NSGs defining private IPs while leaving the default rules intact. The ‘VirtualNetwork’ Tag will allow all private traffic unless a DENY_ALL is put at a higher priority (as I recommend).
When deploying VMs from the Azure Marketplace, the templates deployed will often attach an NSG to the NIC of the VM. These should be reviewed and often removed (if rules are copied into the NIC NSG you can put them instead into the subnet NSG). Also, in the New Virtual Machine wizard in the portal the following section will automatically create an NSG and attach it to the NIC of the VM:
In a production environment, I’d highly recommend setting this to ‘None’ and ensuring there is an NSG attached to the subnet instead.
Further Reading
https://docs.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview
https://docs.microsoft.com/en-us/azure/security/fundamentals/network-best-practices
Hi Archie,
Love your page, can you confirm if the same best practices apply when using a Firewall to protect your vNETs?
Hi Joe – good question. If you’re routing all traffic through a Firewall in the VNet (like in a hub and spoke topology) then I’d still recommend having NSGs on all subnets, but it’s up to you whether you’d add the custom deny rule to block all private traffic. It’s definitely more secure, but any change to rules will then need to be done in two places – on the Firewall and on the NSGs. So more security, but more admin!