Security, Security!

This is top of mind for everyone these days and Azure has many security features.  Today we are going to explore the world of Network Security Groups (NSGs) and their use on Virtual Machines and traffic into and out of Virtual Networks.

A network security group (NSG) is a networking filter (firewall) containing a list of security rules allowing or denying network traffic to resources connected to Azure VNets. These rules can manage both inbound and outbound traffic. NSGs can be associated to subnets and/or individual Network Interfaces attached to ARM VMs and Classic VMs. Each NSG has the following properties regardless of where it is associated:

  • Name for the NSG
  • Azure region where the NSG is located
  • resource group
  • Rules either Inbound or Outboard defining what traffic is allowed or denied

When a NSG is associated to a subnet, the rules apply to all resources connected to the subnet. Traffic can be further restricted by also associating a NSG to a VM or NIC. NSGs that are associated to subnets are said to be filtering “North/South” traffic (in other words, packets flowing in and out of a subnet). NSGs that are associated to Network Interfaces are said to be filtering “East/West” traffic (in other words, how the VMs within the subnet connect to each other).

NSG Rules

NSG Rules are the mechanism defining traffic the administrator is looking to control.  All NSGs have a set of default rules. These default rules cannot be deleted, but since they have the lowest possible priority, they can be overridden by the rules that you create. The lower the number, the sooner it will take precedence. The default rules allow and disallow traffic as follows:

  • Virtual network: Traffic originating and ending in a virtual network is allowed both in inbound and outbound directions.
  • Internet: Outbound traffic is allowed, but inbound traffic is blocked.
  • Load balancer: Allow Azure’s load balancer to probe the health of your VMs and role instances. If you are not using a load balanced set, you can override this rule.

NSG Rules are enforced based on their Priority. Priority values start from 100 and go to 4096. Rules will be read and enforced starting with 100 then 101, 102 etc., until all rules have been evaluated in this order. Rules with the priority “closest” to 100 will be enforced. For example, if you had an inbound rule that allowed TCP traffic on Port 80 with a priority of 250 and another that denied TCP traffic on Port 80 with a priority of 125, the NSG rule of deny would be put in place. This is because the “deny rule”, with a priority of 125 is closer to 100 than the “allow rule”, containing a priority of 250.

Associating NSGs

NSGs are used to define the rules of how traffic is filtered for your IaaS deployments in Azure. NSGs by themselves are not implemented until they are “associated”, with a resource in Azure. NSGs can be associated to ARM network interfaces (NIC), which are associated to the VMs, or subnets.

For NICs associated to VMs, the rules are applied to all traffic to/from that Network Interface where it is associated. It is possible to have a multi-NIC VM, and you can associate the same or different NSG to each Network Interface. When NSGs are applied to subnets, rules are applied to traffic to/from all resources connect to that subnet.

In what order are NSGs enforced?

Understanding the effective rules of NSGs is critical. Security rules are applied to the traffic by priority in each NSG in the following order:

Inbound Traffic:
  1. NSG applied to subnet: If a subnet NSG has a matching rule to deny traffic, the packet is dropped.
  2. NSG applied to NIC: If VM\NIC NSG has a matching rule that denies traffic, packets are dropped at the VM\NIC, even if a subnet NSG has a matching rule that allows traffic.
Outbound Traffic:
  1. NSG applied to NIC: If a VM\NIC NSG has a matching rule that denies traffic, packets are dropped.
  2. NSG applied to subnet: If a subnet NSG has a matching rule that denies traffic, packets are dropped, even if a VM\NIC NSG has a matching rule that allows traffic.

Configuring and associating NSGs with subnets

NSGs are a bit different than other types of resources in Azure given they are first created. You must add rules to them (inbound or outbound), and they must be associated to have the desired effect of filtering traffic based on those rules. Remember that NSGs with no rules will have the six default rules covered earlier in this section.

NSGs can be configured and associated with subnets using the Azure portal, PowerShell or the Azure CLI.

Creating a NSG and associating with a subnet using the Azure portal

To create a NSG using the portal, first click Create a Resource, then Networking, and select Network security group. Once the Create network security group blade loads you will need to provide a Name, the Subscription where your resources are located, the resource group for the NSG and the Location (this must be the same as the resources you wish to apply the NSG). In screen shot below, the NSG will be created to allow HTTP traffic into the Apps subnet and be named BuildAzureNSG.

Creating a network security group using the Azure portal

Once BuildAzureNSG has been created, the portal will open the overview blade. Here, you will see that the NSG has been created, but there are no inbound or outbound security rules beyond the default rules.

Default Security rules of the BuildAzureNSG

The next step is to create the inbound rule for HTTP. Under the settings area, click on Inbound Security Rules link. Then to click +Add to allow HTTP traffic on Port 80 into the Apps subnet.

Adding an inbound security rule blade

Now, use the following inputs to complete the Inbound security rule.  This will allow TCP traffic from any IP address to the CIDR range of our Apps subnet.  This means that we can assign this rule to a NIC or Subnet that is in this range to allow traffic to a web server.

  • Source: Any
  • Source Port Ranges: *
  • Destination: IP Addresses
  • Destination IP Addresses/CIDR Ranges: The Apps subnet:
  • Destination Port Ranges: 80
  • Protocol: TCP
  • Action: Allow
  • Priority: 100
  • Name:  Port 80_HTTP

Adding an Inbound Rule to allow HTTP traffic

Once the portal has saved the inbound rule, it will appear in the portal. Review your rule to ensure it has been created correctly. This NSG with its default rules and the newly created inbound rule named Port_80_HTTP are not yet filtering any traffic. It has yet to be associated with a subnet or a Network Interface, so the rules are currently not in effect.

The next task will be to associate it with the Apps subnet. In the Azure portal / Settings, click subnets button, and click +Associate. The portal will ask for two configurations: “Name of the Virtual Network” and the “Name of the subnet”.

The VNet BuildAzureVNET and subnet Apps has been selected.

Once it’s saved, the rules of the NSG are now being enforced for all Network Interfaces that are associated with this subnet. This means that TCP traffic on Port 80 will be allowed for all VMs that are connected to this subnet. Of course, you would need have a webserver VM configured and listening on Port 80 to respond, but with this NSG, you have opened the ability for that traffic to flow to the VMs in this subnet from any other subnet in the world.

In our example, we have a VM named BuildAzureWEBVM that has been provisioned and it’s NIC has been associated with the APPs subnet.

Ipconfig1 of the NIC in the BuildAzureWEBVM

This VM is an Ubuntu Server 16.04 LTS, but doesn’t have a web server installed.  Even with the Port 80 exposed there is nothing running, so we can’t test to see if our rule is working properly.  Let’s try to SSH to the server so we can install the NGINX web server.  To do this, open the Azure Portal and click Connect on the VM Blade.  The portal will provide the SSH command for use to use.

SSH command shown for the BuildAzureWEBVM in the Azure portal

In a BASH client, you can paste this command and click enter.  The command will fail to connect to the VM.  This is because our NSG is in fact open to port 80, but port 22 which SSH uses is not open.  This means our NSG is functioning properly as a disallowed port was blocked.

SSH command failing to connect on port 22

To resolve this, we need to update the Inbound security rule on the BuildAzureNSG to allow port 22.  By clicking +Add again in the Inbound Security rules we can add a rule to allow SSH.  Notice that you must have a different priority for each rule. (This is not a best practice for an internet facing server – Azure even warns you in the dialog).

SSH port 22 is opened

It may take a few minutes to update, but once the rule updates you can now see I was able to SSH to the BuildAzureWEBVM Linux box.  Remember the BuildAzureNSG was associated with the Apps subnet, which means that all VMs attached to that subnet would have this new rule applied.

Connected to BuildAzureWEBVM after opening port 22 on the BuildAzureNSG

Once connected via SSH now we can run a few commands to get a NGINX installed

sudo apt-get update -y && sudo apt-get install nginx -y

After the web server has been installed we can check locally to make sure that the webserver is running by running a few commands.

sudo systemctl status nginx
sudo curl -f localhost

NGINX is installed and Running and the server is responding to HTTP requests on port 80

Once this has been completed, if we open a new browser tab and connect to the BuildAzureWEBVM Public IP address we can see the nginx server is now responding!

BuildAzureWEBVM allowing connections on Port 80

Creating NSGs from the command line with PowerShell

To Create a NSG and configure the rules using PowerShell, you will need to use the New-AzureRmNetworkSecurityRuleConfig and New-AzureRmNetworkSecurityGroup PowerShell cmdlets together. In this example, it’s assumed that you have run the Login-AzureRmAccount command.

#Build a new Inbound Rule to Allow TCP Traffic on Port 80 to the subnet

$rule1 = New-AzureRmNetworkSecurityRuleConfig -Name PORT_HTTP_80 `

                                              -Description "Allow HTTP" `

                                              -Access Allow `

                                              -Protocol Tcp `

                                              -Direction Inbound `

                                              -Priority 100 `

                                              -SourceAddressPrefix * `

                                              -SourcePortRange * `

                                              -DestinationAddressPrefix `

                                              -DestinationPortRange 80

$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName BuildAzureRG `

                                       -Location centralus `

                                       -Name "BuildAzureNSG" `

                                       -SecurityRules $rule1

Once the NSG has been created along with the inbound rule, you will next need to associate this with the subnet to control the flow of network traffic using this filter. To achieve this goal, you will need to use the Get-AzureRmVirtualNetwork and the Set-AzureRmVirtualNetworksubnetConfig. Once the Configuration on the subnet has been set, you will then use the Set-AzureRmVirtualNetwork to save the configuration.

#Associate the Rule with the subnet Apps in the Virtual Network BuildAzureVNET

$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName BuildAzureRG -Name BuildAzureVNET
Set-AzureRmVirtualNetworksubnetConfig -VirtualNetwork $vnet `

                                      -Name Apps `

                                      -AddressPrefix `

                                      -NetworkSecurityGroup $nsg

Set-AzureRmVirtualNetwork -VirtualNetwork $vnet
Creating NSGs from the command line with the Azure CLI

Creating a NSG using the CLI is a multi-step process just as it was with the portal and PowerShell. The az network nsg create command will first be used to create the NSG. Upon creation of the NSG, you will need to create the rule where we will again allow Port 80 to the subnet. This is created using the az network nsg rule create command. Upon creation, this will be associated with the Apps subnet on the VNet using the az network vnet subnet update command.

# Create the NSG

az network nsg create --resource-group BuildAzureRG \
                      --name BuildAzureNSG

# Create the NSG Inbound Rule allowing TCP traffic on Port 80

az network nsg rule create --resource-group BuildAzureRG \
                           --name PORT_HTTP_80 \
                           --nsg-name BuildAzureNSG \
                           --direction Inbound \
                           --priority 100 \
                           --access Allow \ 
                           --source-address-prefix "*" \
                           --source-port-range "*" \
                           --destination-address-prefix "*" \
                           --destination-port-range "80" \
                           --description "Allow HTTP" \
                           --protocol TCP
# Associate the NSG with the BuildAzureVNET Apps subnet

az network vnet subnet update --resource-group BuildAzureRG \
                              --vnet-name BuildAzureVNET \
                              --name Apps \
                              --network-security-group BuildAzureNSG

Well, I hope you enjoyed getting to know NSGs better!  My advice is that you make sure to use both Subnet and NIC NSGs.  This will ensure that your North/South traffic (into and out of your VNET) and your East/West traffic (between VMs on the same subnet) are secured.

Good luck and let me know if you have any questions!


Posted by Dan Patrick

Dan Patrick is the Chief Infrastructure Architect for Solliance and a 15 year veteran at Microsoft. He has an extensive background in IT Infrastructure and Operations. Dan has both architected and lead teams building and supporting some of the largest service providers in North America with as many 15,000 Windows Servers and 120 million endpoints. Dan has worked with Azure IaaS solutions extensively since 2012. He has a passion for Virtualization with deep experience leveraging Hyper-V, Vmware, and Citrix. He is also a Clustering specialist focusing on large host clusters and SQL Always On Availability Groups. Recently Dan, authored the Networking, Azure Active Directory and Containers portion of the 70-533 Exam Reference for Microsoft Press. You can follow him on Twitter @deltadan

One Comment

  1. […] Securing Azure Virtual Machines using Network Security Groups (NSGs)  by Dan Patrick […]


Leave a Reply