Azure Virtual Networks — VNets, Subnets, NSGs, and Peering
Your VMs are running, your storage accounts are full of data, and your App Services are serving traffic. But right now, everything is either wide open to the internet or completely isolated. Azure Virtual Networks sit between those two extremes — giving you precise control over which resources can talk to each other and who can reach them from outside.
What Is a Virtual Network?
An Azure Virtual Network (VNet) is an isolated network boundary in the cloud. Resources inside a VNet can communicate with each other by default. Resources in different VNets cannot — unless you explicitly connect them.
Think of a VNet as your private data center network, except you define it with a few CLI commands instead of racking switches.
Key VNet facts:
- A VNet exists in a single region
- A VNet has one or more address spaces (CIDR blocks)
- A VNet contains one or more subnets
- Resources in the same VNet communicate freely
- VNets are free — you pay for the resources inside them
Address Spaces and CIDR
Every VNet needs an address space defined in CIDR notation. Choose private IP ranges from RFC 1918:
| CIDR Block | Range | Available IPs | Common Use |
|---|---|---|---|
10.0.0.0/16 | 10.0.0.0 - 10.0.255.255 | 65,536 | Large production VNets |
10.1.0.0/16 | 10.1.0.0 - 10.1.255.255 | 65,536 | Secondary region VNet |
172.16.0.0/16 | 172.16.0.0 - 172.16.255.255 | 65,536 | Development environments |
192.168.0.0/16 | 192.168.0.0 - 192.168.255.255 | 65,536 | Lab/testing |
Critical rule: VNet address spaces must not overlap if you plan to peer them or connect them via VPN. Plan your IP addressing scheme before you create your first VNet.
Step-by-Step: Creating a VNet with Subnets
# Create a VNet with a /16 address space
az network vnet create \
--resource-group rg-prod-network-eastus \
--name vnet-prod-eastus \
--address-prefix 10.0.0.0/16 \
--location eastus \
--tags Environment=Production Team=Platform
Designing Subnets
Subnets divide your VNet into smaller segments. Each subnet gets a slice of the VNet's address space:
# Web tier subnet
az network vnet subnet create \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-web \
--address-prefixes 10.0.1.0/24
# Application tier subnet
az network vnet subnet create \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-app \
--address-prefixes 10.0.2.0/24
# Database tier subnet
az network vnet subnet create \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-db \
--address-prefixes 10.0.3.0/24
# List all subnets
az network vnet subnet list \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--output table
Note: Azure reserves 5 IP addresses in every subnet (first 4 and the last). A /24 subnet gives you 251 usable IPs, not 256.
Subnet Delegation
Some Azure services require dedicated subnets. This is called delegation:
# Delegate a subnet to Azure App Service
az network vnet subnet create \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-appservice \
--address-prefixes 10.0.10.0/24 \
--delegations Microsoft.Web/serverFarms
Network Security Groups (NSGs)
NSGs are Azure's built-in firewall. They contain rules that allow or deny traffic based on source, destination, port, and protocol. NSGs can be attached to subnets or individual network interfaces.
Creating an NSG with Rules
# Create an NSG for the web tier
az network nsg create \
--resource-group rg-prod-network-eastus \
--name nsg-web-tier
# Allow HTTP from the internet
az network nsg rule create \
--resource-group rg-prod-network-eastus \
--nsg-name nsg-web-tier \
--name AllowHTTP \
--priority 100 \
--direction Inbound \
--access Allow \
--protocol Tcp \
--source-address-prefixes Internet \
--destination-port-ranges 80
# Allow HTTPS from the internet
az network nsg rule create \
--resource-group rg-prod-network-eastus \
--nsg-name nsg-web-tier \
--name AllowHTTPS \
--priority 110 \
--direction Inbound \
--access Allow \
--protocol Tcp \
--source-address-prefixes Internet \
--destination-port-ranges 443
# Allow SSH only from your office IP
az network nsg rule create \
--resource-group rg-prod-network-eastus \
--nsg-name nsg-web-tier \
--name AllowSSHFromOffice \
--priority 200 \
--direction Inbound \
--access Allow \
--protocol Tcp \
--source-address-prefixes 203.0.113.50/32 \
--destination-port-ranges 22
# Deny all other inbound traffic (explicit catch-all)
az network nsg rule create \
--resource-group rg-prod-network-eastus \
--nsg-name nsg-web-tier \
--name DenyAllInbound \
--priority 4096 \
--direction Inbound \
--access Deny \
--protocol '*' \
--source-address-prefixes '*' \
--destination-port-ranges '*'
Associating NSG with a Subnet
# Attach the NSG to the web subnet
az network vnet subnet update \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-web \
--network-security-group nsg-web-tier
# View effective rules
az network nsg show \
--resource-group rg-prod-network-eastus \
--name nsg-web-tier \
--query "securityRules[].{Name:name, Priority:priority, Direction:direction, Access:access, Port:destinationPortRange}" \
--output table
NSG Rule Processing
Rules are processed by priority number (lowest number = highest priority):
| Priority | Direction | Action | Description |
|---|---|---|---|
| 100 | Inbound | Allow | HTTP from internet |
| 110 | Inbound | Allow | HTTPS from internet |
| 200 | Inbound | Allow | SSH from office only |
| 4096 | Inbound | Deny | Everything else blocked |
Application Security Groups (ASGs)
ASGs let you group VMs logically and reference those groups in NSG rules instead of using IP addresses. When VMs scale up or down, the rules stay the same.
# Create ASGs for web and database tiers
az network asg create \
--resource-group rg-prod-network-eastus \
--name asg-web-servers
az network asg create \
--resource-group rg-prod-network-eastus \
--name asg-db-servers
# NSG rule: allow web servers to talk to DB servers on port 5432
az network nsg rule create \
--resource-group rg-prod-network-eastus \
--nsg-name nsg-db-tier \
--name AllowPostgresFromWeb \
--priority 100 \
--direction Inbound \
--access Allow \
--protocol Tcp \
--source-asgs asg-web-servers \
--destination-asgs asg-db-servers \
--destination-port-ranges 5432
VNet Peering
VNet peering connects two VNets so resources in both can communicate using private IP addresses. Traffic stays on the Microsoft backbone — it never touches the public internet.
# Create a second VNet (simulating another region or workload)
az network vnet create \
--resource-group rg-prod-network-eastus \
--name vnet-shared-eastus \
--address-prefix 10.1.0.0/16 \
--location eastus
# Peer VNet A → VNet B
az network vnet peering create \
--resource-group rg-prod-network-eastus \
--name peer-prod-to-shared \
--vnet-name vnet-prod-eastus \
--remote-vnet vnet-shared-eastus \
--allow-vnet-access true
# Peer VNet B → VNet A (peering must be created in BOTH directions)
az network vnet peering create \
--resource-group rg-prod-network-eastus \
--name peer-shared-to-prod \
--vnet-name vnet-shared-eastus \
--remote-vnet vnet-prod-eastus \
--allow-vnet-access true
# Verify peering status
az network vnet peering list \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--output table
Important: VNet peering is non-transitive. If VNet A peers with VNet B, and VNet B peers with VNet C, VNet A cannot reach VNet C automatically. You need a hub-spoke topology or Azure Virtual WAN for that.
Global peering works across regions (e.g., East US to West Europe) with the same commands. Cross-region data transfer costs apply.
Service Endpoints and Private Endpoints
Service Endpoints
Service endpoints extend your VNet's identity to Azure services, allowing you to restrict access to storage accounts, databases, and other services so they only accept traffic from your VNet.
# Enable service endpoint for Azure Storage on a subnet
az network vnet subnet update \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name snet-app \
--service-endpoints Microsoft.Storage
# Restrict storage account to only accept traffic from that subnet
az storage account network-rule add \
--resource-group rg-prod-webapp-eastus \
--account-name stprodappeastus2025 \
--vnet-name vnet-prod-eastus \
--subnet snet-app
Private Endpoints
Private endpoints go a step further — they bring the Azure service into your VNet with a private IP address. Traffic never leaves the virtual network.
# Create a private endpoint for a storage account
az network private-endpoint create \
--resource-group rg-prod-network-eastus \
--name pe-storage-prod \
--vnet-name vnet-prod-eastus \
--subnet snet-app \
--private-connection-resource-id /subscriptions/<sub-id>/resourceGroups/rg-prod-webapp-eastus/providers/Microsoft.Storage/storageAccounts/stprodappeastus2025 \
--group-id blob \
--connection-name pe-connection-storage
Azure DNS
Azure DNS hosts your DNS zones and resolves queries using Microsoft's global network of DNS servers.
# Create a DNS zone
az network dns zone create \
--resource-group rg-prod-network-eastus \
--name myapp.com
# Add an A record
az network dns record-set a add-record \
--resource-group rg-prod-network-eastus \
--zone-name myapp.com \
--record-set-name www \
--ipv4-address 20.185.100.50
# Add a CNAME record
az network dns record-set cname set-record \
--resource-group rg-prod-network-eastus \
--zone-name myapp.com \
--record-set-name blog \
--cname myapp-blog.azurewebsites.net
VPN Gateway Basics
A VPN Gateway connects your on-premises network to your Azure VNet over an encrypted tunnel. This is the hybrid cloud bridge.
The setup involves creating a gateway subnet, a public IP, and the gateway itself — it takes 30-45 minutes to provision:
# Create a gateway subnet (must be named GatewaySubnet)
az network vnet subnet create \
--resource-group rg-prod-network-eastus \
--vnet-name vnet-prod-eastus \
--name GatewaySubnet \
--address-prefixes 10.0.255.0/27
# Create a public IP for the gateway
az network public-ip create \
--resource-group rg-prod-network-eastus \
--name pip-vpn-gateway \
--allocation-method Static \
--sku Standard
# Create the VPN gateway (takes 30-45 minutes)
az network vnet-gateway create \
--resource-group rg-prod-network-eastus \
--name vpn-gateway-prod \
--vnet vnet-prod-eastus \
--public-ip-addresses pip-vpn-gateway \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw1 \
--no-wait
Wrapping Up
Networking is the invisible infrastructure that makes everything else work. A well-designed VNet with proper subnets, NSG rules, and peering keeps your resources secure and connected. Start with a hub-spoke architecture, use NSGs to enforce least-privilege network access, and use private endpoints to keep traffic off the public internet. Plan your CIDR ranges carefully — renumbering a production network is a pain you want to avoid.
Next up: We will explore Azure Monitor and Log Analytics — setting up alerts, dashboards, and diagnostics to keep your infrastructure healthy and observable.
