EthicsComputerCourses
Join training +91 90532 10052

Network Security Groups

Microsoft Azure · Lesson 11 of 29 Beginner 7 min read Updated

By the end of this lesson you will be able to read and write network security group rules, predict which rule wins, use service tags and application security groups, and avoid the most common mistake of all: opening SSH or RDP to the whole internet.

What is a network security group?

A network security group (NSG) is a list of rules that allows or denies network traffic to and from Azure resources in a virtual network. Each rule looks at five things, often called the 5-tuple: source address, source port, destination address, destination port and protocol.

Think of the security guard at a hostel gate with a register of rules: "students may enter", "delivery agents only until 9 pm", "everyone else stays out". The guard reads the rules from the top and acts on the first one that matches.

You attach an NSG to a subnet, to a VM's network interface (NIC), or both. If both are attached, traffic must pass both: for inbound traffic the subnet NSG is checked first, then the NIC NSG.

How rules are evaluated

Every rule has:

  • a priority from 100 to 4096; lower numbers are checked first;
  • a direction: Inbound or Outbound;
  • an action: Allow or Deny;
  • source, destination, ports and protocol (TCP, UDP, ICMP or Any).

Azure checks rules in priority order and stops at the first match. NSGs are stateful: if inbound traffic on port 443 is allowed, the reply traffic is allowed out automatically. You do not write a matching outbound rule for replies.

Every NSG also has default rules with priorities 65000 and above. You cannot delete them, but your own rules with lower numbers override them:

Default ruleDirectionEffect
AllowVnetInBoundInboundAllow traffic from inside the virtual network (and peered networks)
AllowAzureLoadBalancerInBoundInboundAllow Azure load balancer health probes
DenyAllInBoundInboundDeny everything else, including the internet
AllowVnetOutBoundOutboundAllow traffic to the virtual network
AllowInternetOutBoundOutboundAllow traffic to the internet
DenyAllOutBoundOutboundDeny everything else

So, by default, the internet cannot start a connection to your VM. You open only what you need.

Service tags and application security groups

Typing IP ranges is error-prone. Azure offers two helpers:

  • A service tag is a name for a group of IP ranges that Microsoft keeps up to date, such as Internet, VirtualNetwork, AzureLoadBalancer, Storage or Sql. You can also scope some by region, such as Storage.CentralIndia.
  • An application security group (ASG) is a label you put on NICs, such as asg-web or asg-db. Rules can then say "allow asg-web to reach asg-db on port 5432" without any IP addresses. When you add a new web VM, you just give its NIC the asg-web label.

Step by step: secure a web subnet

You will create an NSG that allows HTTPS from anywhere and SSH only from your office's public IP, then attach it to the snet-web subnet from the virtual networks lesson.

Step 1: create the NSG.

Terminal
az network nsg create --resource-group rg-net-demo --name nsg-web-cin --output none

Step 2: add the HTTPS rule.

Terminal
az network nsg rule create --resource-group rg-net-demo --nsg-name nsg-web-cin \
  --name allow-https --priority 100 --direction Inbound --access Allow \
  --protocol Tcp --source-address-prefixes Internet --destination-port-ranges 443 --output none

Step 3: add an SSH rule limited to one office IP. The address 203.0.113.25 is from a range reserved for documentation; use your real office IP.

Terminal
az network nsg rule create --resource-group rg-net-demo --nsg-name nsg-web-cin \
  --name allow-ssh-office --priority 110 --direction Inbound --access Allow \
  --protocol Tcp --source-address-prefixes 203.0.113.25/32 --destination-port-ranges 22 --output none

Step 4: attach the NSG to the subnet.

Terminal
az network vnet subnet update --resource-group rg-net-demo --vnet-name vnet-shop-cin \
  --name snet-web --network-security-group nsg-web-cin --output none

Step 5: list all rules, including the defaults.

Terminal
az network nsg rule list --resource-group rg-net-demo --nsg-name nsg-web-cin --include-default \
  --query "[].{Name:name, Priority:priority, Direction:direction, Access:access}" --output table
Output
Name                           Priority  Direction  Access
-----------------------------  --------  ---------  ------
allow-https                    100       Inbound    Allow
allow-ssh-office               110       Inbound    Allow
AllowVnetInBound               65000     Inbound    Allow
AllowAzureLoadBalancerInBound  65001     Inbound    Allow
DenyAllInBound                 65500     Inbound    Deny
AllowVnetOutBound              65000     Outbound   Allow
AllowInternetOutBound          65001     Outbound   Allow
DenyAllOutBound                65500     Outbound   Deny

This table is traced from the documented default rules; the row order you see may differ.

A worked example: which rule wins?

A packet arrives from the internet on TCP port 3306 (MySQL). Walk the inbound list:

  1. allow-https (100): port 443 only. No match.
  2. allow-ssh-office (110): port 22 from one IP. No match.
  3. AllowVnetInBound (65000): source is the internet, not the VNet. No match.
  4. AllowAzureLoadBalancerInBound (65001): not a load balancer probe. No match.
  5. DenyAllInBound (65500): matches everything. Denied.

That is exactly what you want for a database port.

Seeing what the NSG did

When traffic is blocked and you do not know why, use Network Watcher:

  • IP flow verify tells you whether a specific packet would be allowed and which rule decides it.
  • Effective security rules shows the combined rules from the subnet and NIC NSGs for one NIC.
  • Flow logs record allowed and denied flows to a storage account for later analysis. Microsoft now recommends VNet flow logs, which cover a whole virtual network, over the older NSG flow logs.
Terminal
az network watcher test-ip-flow --resource-group rg-net-demo --vm vm-web-01 \
  --direction Inbound --protocol TCP --local 10.10.1.4:3306 --remote 198.51.100.7:50000
Output
{
  "access": "Deny",
  "ruleName": "securityRules/DenyAllInBound"
}

This output is traced from the Network Watcher docs and assumes a VM called vm-web-01 exists in the subnet. The exact rule name format can include more prefix text.

Common mistakes

  • Using priority 4096 for important rules. Leave gaps (100, 110, 120) so you can insert rules later.
  • Allowing * as the source "for testing". Tests become production. Start narrow.
  • Forgetting the NIC NSG. If both subnet and NIC have NSGs, both must allow the traffic.
  • Treating NSGs as a full firewall. NSGs filter by IP and port. For URL filtering and threat intelligence, add Azure Firewall or a web application firewall.

Key points

  • An NSG holds prioritised allow and deny rules; the first matching rule wins.
  • Rules are stateful, so replies are allowed automatically.
  • Default rules allow VNet traffic and outbound internet, and deny all other inbound traffic.
  • Service tags and application security groups replace hard-coded IP lists.
  • Use Azure Bastion or just-in-time access instead of opening SSH or RDP to the internet.

Exercise

Write NSG rules for nsg-data-cin on the data subnet of a shop app. The PostgreSQL port 5432 must be reachable only from the web subnet 10.10.1.0/24. Everything else inbound from inside the VNet must be blocked. Give the rules priorities 100 and 200.

Show solution
Terminal
az network nsg rule create --resource-group rg-net-demo --nsg-name nsg-data-cin \
  --name allow-postgres-from-web --priority 100 --direction Inbound --access Allow \
  --protocol Tcp --source-address-prefixes 10.10.1.0/24 --destination-port-ranges 5432 --output none

az network nsg rule create --resource-group rg-net-demo --nsg-name nsg-data-cin \
  --name deny-vnet-inbound --priority 200 --direction Inbound --access Deny \
  --protocol "*" --source-address-prefixes VirtualNetwork --destination-port-ranges "*" --output none

The deny rule at 200 overrides the default AllowVnetInBound (65000), and the allow rule at 100 is checked first, so only web servers reach port 5432.

Quick Quiz

1. Two rules match a packet: priority 300 Allow and priority 200 Deny. What happens?

2. Why do you not need an outbound rule for replies to allowed inbound HTTPS traffic?

3. What is the safest way to SSH into a VM with no public IP?

Learn Microsoft Azure with a mentor

Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call