Network Security Groups
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 rule | Direction | Effect |
|---|---|---|
| AllowVnetInBound | Inbound | Allow traffic from inside the virtual network (and peered networks) |
| AllowAzureLoadBalancerInBound | Inbound | Allow Azure load balancer health probes |
| DenyAllInBound | Inbound | Deny everything else, including the internet |
| AllowVnetOutBound | Outbound | Allow traffic to the virtual network |
| AllowInternetOutBound | Outbound | Allow traffic to the internet |
| DenyAllOutBound | Outbound | Deny 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,StorageorSql. You can also scope some by region, such asStorage.CentralIndia. - An application security group (ASG) is a label you put on NICs, such as
asg-weborasg-db. Rules can then say "allowasg-webto reachasg-dbon port 5432" without any IP addresses. When you add a new web VM, you just give its NIC theasg-weblabel.
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.
az network nsg create --resource-group rg-net-demo --name nsg-web-cin --output noneStep 2: add the HTTPS rule.
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 noneStep 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.
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 noneStep 4: attach the NSG to the subnet.
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 noneStep 5: list all rules, including the defaults.
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 tableName 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:
allow-https(100): port 443 only. No match.allow-ssh-office(110): port 22 from one IP. No match.AllowVnetInBound(65000): source is the internet, not the VNet. No match.AllowAzureLoadBalancerInBound(65001): not a load balancer probe. No match.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.
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{
"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
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 noneThe 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?
Lower priority numbers are checked first, so the Deny at 200 wins.
2. Why do you not need an outbound rule for replies to allowed inbound HTTPS traffic?
Stateful filtering automatically allows return traffic for permitted connections.
3. What is the safest way to SSH into a VM with no public IP?
Bastion provides SSH and RDP through the portal without exposing the VM.
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
