How to Secure A Network Using NSGs and ASGs

Security Hero
In this post, I will explain how you can use Application Security Groups (ASGs) in addition with Network Security Groups (NSGs) to create secure network designs for virtual machines in Azure.
Before you read this post, you should read Understanding Application Security Groups in the Azure Portal to understand the purpose of ASGs and how to deploy them.

The Scenario

In a previous post, How to Secure A Network Using NSGs, I explained how you could secure a reference architecture for a web application that is deployed using virtual machines in an Azure virtual network. In the design, the service has three tiers, each of which is deployed into its own subnet and secured with a dedicated NSG resource:

  • Web Tier: The web servers that are accessed from the Internet.
  • Business Tier: The application servers that are only connected to by the web servers.
  • Data Tier: The database servers that are only connected to by the database servers.

Securing a web service using NSGs [Image Credit: Aidan Finn]
Securing a web service using NSGs [Image Credit: Aidan Finn]
The above example is quite simple. In the real world, I’ve seen designs that might have 10+ subnets and one NSG resource per subnet. That is a complex design and could be fun to troubleshoot firewall rules in many NSG resources.

Application Security Groups

If you “zoomed out” on the above design, you might say that there is an external tier (the web servers) and an internal or backend tier (everything else). What if we could flatten the above design to just 2 subnets/2 NSGs, but still have the same levels of effective firewall security? What if we could replace 10.0.2.0/24 and 10.0.3.0/24 with human-friendly labels? Application Security Groups (ASGs) can be used as follows:

  • Join the NICs of virtual machines to an ASG.
  • The ASG(s) give us friendly names, such as “BusinessTier”, which are easier to read and more meaningful than 10.0.2.0/24.
  • Use the ASGs as sources or destinations in NSG rules.
  • Create security zones inside a single NSG, and therefore inside a single subnet.
  • Reduce the number of subnets.
  • Ease troubleshooting by having more rules spanning zones in a single NSG ruleset.

If we took the above network example and used ASGs, it might look like the below diagram. In this design we have:

  • Web Tier: This tier remains isolated in its own subnet because it is directly connected to the Internet. An NSG that is dedicated to this subnet allows web traffic into the web servers.
  • Backend Tier – BusinessASG: An Application Security Group is created for NICs of the application servers in the Backend Tier subnet. A single NSG for this subnet allows application traffic into the BusinessASG members from the Web Tier subnet.
  • Backend Tier – DataASG: The NICs of the database servers in the Backend Tier subnet are joined to a second ASG. The DataASG allows database traffic from the machines in the BusinessASG.
Securing a web service using NSGs and ASGs [Image Credit: Aidan Finn]
Securing a web service using NSGs and ASGs [Image Credit: Aidan Finn]

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 servers. 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 Backend Tier NSG

The purpose of this NSG is twofold:

  • Allow application traffic from the web servers (10.0.1.0/24) into the application servers (BusinessASG).
  • Allow database traffic from the application servers (BusinessASG) into the database servers (DataASG).

The rule set will look as follows, assuming that application is hosted on TCP 8080 and the data tier is based on SQL Server running in the guest OS of the database virtual machines:

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

As with the Web Tier NSG, you might also allow SSH/RDP traffic from a trusted source, as well as database management traffic from the same/different trusted source.

Comments

Which is better: using NSGs or using NSGs with ASGs? For me, it’s an “it depends” situation. In simpler designs, I am leaning towards splitting tiers of a service across subnets. I have encountered several scenarios recently, though, where the subnet design could be very complex and using ASGs will reduce the number of subnets and make it easier to document & troubleshoot NSG rules.