Skip to main content

Securing Azure VMs with Network Security Groups

Learn to configure Network Security Group rules that allow only intended traffic, and understand the danger of exposing management ports.

Overview and What You Will Learn

In this lab, you will create a Network Security Group, add rules allowing only HTTPS traffic while denying everything else by default, then attempt a connection on a blocked port to confirm the NSG is actually enforcing the boundary you configured.

Why This Matters in Production

An engineer at a growing startup opens RDP directly to the internet on a production VM "just to finish a quick fix," and within days automated scanners have found the open port and are attempting brute-force logins against it. A correctly configured NSG that only allows the specific traffic a VM actually needs prevents this exact category of exposure from ever existing in the first place.

Core Principles

A Network Security Group is a set of allow and deny rules controlling inbound and outbound traffic to a subnet or a specific network interface, evaluated in priority order.

◈ DIAGRAM
+------------------------------------------+
| Default NSG behavior |
| |
| Inbound: denies everything from the |
| internet by default |
| Outbound: allows everything out to the |
| internet by default |
+------------------------------------------+

Each rule has a priority number - lower numbers are evaluated first, and the first matching rule wins. This means a broad deny rule at a low priority number can block traffic that a more permissive rule at a higher priority number would otherwise have allowed.

Detailed Step-by-Step Practical Lab

  1. Create a Resource Group and a VNet with a subnet:
Bash
az group create --name rg-nsg-lab-mumbai --location centralindia
az network vnet create \
--resource-group rg-nsg-lab-mumbai \
--name vnet-nsg-lab \
--address-prefix 10.0.0.0/16 \
--subnet-name subnet-web \
--subnet-prefix 10.0.1.0/24
  1. Create a Network Security Group:
Bash
az network nsg create \
--resource-group rg-nsg-lab-mumbai \
--name nsg-web-lab
  1. Add a rule allowing only inbound HTTPS traffic:
Bash
az network nsg rule create \
--resource-group rg-nsg-lab-mumbai \
--nsg-name nsg-web-lab \
--name allow-https \
--priority 100 \
--destination-port-ranges 443 \
--access Allow \
--protocol Tcp
  1. Associate the NSG with the subnet so its rules actually apply:
Bash
az network vnet subnet update \
--resource-group rg-nsg-lab-mumbai \
--vnet-name vnet-nsg-lab \
--name subnet-web \
--network-security-group nsg-web-lab
  1. Create a VM inside that subnet to test the NSG's effect:
Bash
az vm create \
--resource-group rg-nsg-lab-mumbai \
--name vm-nsg-test \
--image Ubuntu2204 \
--vnet-name vnet-nsg-lab \
--subnet subnet-web \
--nsg "" \
--admin-username azureadmin \
--generate-ssh-keys
Note

--nsg "" tells the VM creation command not to create its own separate NSG on the network interface, since the subnet-level NSG created in step 2 already applies to everything inside the subnet.

  1. Confirm the effective security rules applying to this VM's network interface:
Bash
NIC_ID=$(az vm show \
--resource-group rg-nsg-lab-mumbai \
--name vm-nsg-test \
--query "networkProfile.networkInterfaces[0].id" --output tsv)
NIC_NAME=$(basename "$NIC_ID")
# Now check the effective NSG rules applied to that interface
az network nic list-effective-nsg \
--resource-group rg-nsg-lab-mumbai \
--name "$NIC_NAME"
  1. Attempt to connect on a port that was never explicitly allowed (like port 8080) and confirm it is blocked by the default deny rule, then confirm port 443 traffic succeeds as expected given the rule created in step 3.

  2. Clean up:

Bash
az group delete --name rg-nsg-lab-mumbai --yes --no-wait

Production Best Practices & Common Pitfalls

Security

Never open management ports like RDP (3389) or SSH (22) directly to the internet (0.0.0.0/0) on a production NSG. Use Azure Bastion for secure browser-based access instead, or restrict the source IP range to your organization's own known, trusted network if Bastion genuinely isn't an option.

Tip

Use az network nic list-effective-nsg whenever troubleshooting unexpected connectivity behavior. A VM can have NSGs applied at both the subnet level and the network interface level simultaneously - this command shows the actual combined, effective rule set rather than requiring you to manually reason through both separately.

  • Rule priority determines evaluation order, not creation order. A rule created last but given a lower priority number is evaluated before a rule created first with a higher priority number - always check the priority field, not the order rules appear in a list.
  • The default deny-inbound rule is a safety net, not a substitute for explicit rules. Relying on the default alone means anyone who later adds an overly broad allow rule has effectively removed that protection - explicit, narrow rules stay correct even as an NSG's rule set grows over time.

Quick Reference & Troubleshooting Commands

Command Description
az network nsg create Create a new Network Security Group
az network nsg rule create Add an inbound or outbound rule
az network vnet subnet update --network-security-group Associate an NSG with a subnet
az network nic list-effective-nsg Show the actual combined effective rules for a NIC

Explore More in Azure Networking and Traffic Management

All 6 Topics

Frequently Asked Questions

Is Securing Azure VMs with Network Security Groups free to learn on DevOps Network?

Yes - this topic, like everything on DevOps Network, is 100% free with no paywall or sign-up gate.

What does the Securing Azure VMs with Network Security Groups topic cover?

Learn to configure Network Security Group rules that allow only intended traffic, and understand the danger of exposing management ports.