How to Secure A Network Using NSGs

Security Hero
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 Web Farm

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:

  • Web Tier: A subnet for virtual machines hosting web services. An NSG dedicated to this subnet will allow web traffic from the Internet and through the external load balancer to the virtual machines.
  • Business Tier: This subnet is where the applications servers are. Another dedicated NSG will allow traffic from the web tier into this tier.
  • Data Tier: Here you can find the database servers. A third dedicated NSG will allow database client-server traffic from the business tier into this subnet.
The design of the Azure virtual network that NSGs will secure [Image Credit: Aidan Finn]
The design of the Azure virtual network that NSGs will secure [Image Credit: Aidan Finn]

The Concept of Stacking Rules

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:

  • AllowVnetInBound (Priority 65000): Allows all traffic from the virtual network (and peered virtual networks) through the NSG.
  • AllowAzureLoadBalancerInBound (Priority 65001): Allows traffic from an Azure load balancer probe through the NSG.
  • DenyAllInbound (Priority 65500): Blocks everything else. This will block traffic from outside of the VNet, including Internet and other non-peered virtual networks.

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 Web Tier NSG

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:

  • AllowHTTP (Priority 100): Allow TCP 80 from * to 10.0.1.0/24.
  • AllowHTTPS (Priority 200): Allow TCP 443 from * to 10.0.1.0/24.
  • AllowLoadBalancerProbe (Priority 300): Allow * from AzureLoadBalancer.
  • BlockVirtualNetwork (Priority 4096): Deny * from VirtualNetwork.

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 Business Tier NSG

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:

  • AllowApp (Priority 100): Allow TCP 8080 from 10.0.1.0/24 to 10.0.2.0/24.
  • AllowLoadBalancerProbe (Priority 200): Allow * from AzureLoadBalancer.
  • BlockVirtualNetwork (Priority 4096): Deny * from VirtualNetwork.

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 Data Tier NSG

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:

  • AllowSqlServer (Priority 100): Allow TCP 1433 from 10.0.2.0/24 to 10.0.3.0/24.
  • AllowLoadBalancerProbe (Priority 200): Allow * from AzureLoadBalancer.
  • BlockVirtualNetwork (Priority 4096): Deny * from VirtualNetwork.

Comments

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.