In this post, I will show you how you can use Network Security Groups (NSGs) to secure the subnets of a typical virtual machine-based web application deployment in Azure.
Note that I will focus on inbound rules in this article.
The deployment that I will secure in this article is a typical design you will find for deploying a web farm using virtual machines in Azure. If you have browsed Microsoft’s Azure reference architectures then you might recognize the design – I took their Internet DMZ design and chopped it down to focus just on the machines and their subnets.
In the design, there is a single virtual network and three subnets. Each subnet hosts a tier of virtual machines and has a single network security group (NSG) created for it and associated with it:
An NSG resource has inbound and outbound rules – as I said earlier, we will focus on the inbound rules in this post. The rules can be stacked with prioritized. When a packet enters the subnet, either from another subnet/VNet or from other machines NICs in the same subnet, it will hit the associated NSG. The packet will be matched with each rule in order from high-priority (low number) to low-priority (high number).
The default rules which are always present are:
In rule design we make specific rules high priority and general rules low priority. For example, if we want to allow a specific type of traffic, then we will create a high priority rule. If we want to block everything else, we create a low priority rule.
Tip: It’s easy to create rule 101, rule 102, and rule 103. But if you need to make changes then you will have to re-prioritize each of those rules. Consider using 100, 200, 300 for priorities. If I need to sandwich a rule between 100 and 200 I can create it with a priority of 250.
The purpose of this NSG is to allow web server traffic from the Internet to the web servers in the Web Tier subnet. We can do something like this:
If web traffic comes in through the external load balancer then it will be allowed by one of those rules. We are creating a specific rule to allow probe traffic from the external load balancer; this is because the last rule will deny all other traffic from the virtual network. We don’t want any other traffic in the virtual network getting into these virtual machines – this includes blocking communications between the web severs. Anything else from the Internet will be blocked by the default DenyAllInbound rule.
If you want to extend this, you might add a rule (Priority 500) to allow SSH or RDP from an allowed source IP address, such as a “jump box” virtual machine in a dedicated subnet or peered virtual network.
The purpose of this NSG is to allow traffic only from the Web Tier subnet. No other traffic should get into this subnet – maybe you’ll allow RDP/SSH traffic from a specific IP address.
Let’s assume that the web servers talk to the application servers on TCP 8080. We can create an NSG for the Business Tier NSG that has this rule:
The AllowApp rule will allow TCP 80 from the web tier, and only this subnet, to the business tier. After that, we copy the logic of blocking everything else in this subnet except for the load balancer probe.
The third and final NSG will allow database traffic from the Business Tier, and only the Business Tier, to the Data Tier. In this design, only the application servers in the business tier should ever connect to the databases. As discussed before, you might want to allow RDP/SSH traffic from a specific source. You might also want to allow database administration from restricted & trusted sources too.
Let’s assume that the databases are running on SQL Server which uses TCP 1433:
How do you eat an elephant? One bite at a time. If you take network security in little bites, while keeping an eye on the big picture, designing network security using NSGs isn’t that hard.
NSGs are the foundation of all network security designs in Azure. For some designs, they are all you will use. In others, you might use third-party firewalls, Azure Firewall, the Azure Web Application Firewall, and more, but you always use NSGs to defend each subnet in depth.