Azure Network Security Best Practices

Securing an Azure network is not one firewall rule — it is a series of overlapping controls, each stopping a different class of attack at a different network layer. This page walks through each layer of defence, from subnet-level NSG rules to centralised Azure Firewall egress control, and explains what each layer stops, what it does not, and how to layer them correctly.

Defence in depth: the layers

A defence-in-depth network architecture stacks multiple independent controls. An attacker who bypasses one layer faces the next:

LayerControlWhat it stops
Edge / internetDDoS Protection, WAFVolumetric attacks, OWASP exploits, malformed HTTP
PerimeterAzure Firewall, NSG on GatewaySubnetUnauthorised inbound traffic, egress to malicious IPs/FQDNs
VNet / subnetNSG on subnets, Application Security GroupsLateral movement between workloads, unnecessary port exposure
Service levelPrivate Endpoints, service endpoint policiesPublic IP exposure of PaaS services, exfiltration to other tenants
VM / NIC levelNSG on NIC, host-based firewallDirect NIC-level traffic control, defence if subnet NSG is misconfigured

NSG rules: default deny, least privilege

Network Security Groups enforce allow and deny rules on subnet or NIC traffic. The correct baseline: deny everything, then explicitly allow only what is needed.

Every NSG comes with three default inbound deny rules at priority 65000, 65001, and 65500, and three equivalent outbound rules. These catch everything not explicitly allowed at lower priority numbers. Do not delete these rules.

Key practices for NSG rules:

Use service tags instead of IP ranges. Service tags like AzureLoadBalancer, Internet, VirtualNetwork, and AzureCloud are managed by Microsoft and stay current. Hardcoded IP ranges become stale.

# Allow HTTPS inbound from the internet to the web tier
az network nsg rule create \
  --name Allow-HTTPS-Inbound \
  --nsg-name nsg-snet-web \
  --resource-group rg-networking \
  --priority 100 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --destination-port-ranges 443 \
  --source-address-prefixes Internet \
  --destination-address-prefixes "*"

# Deny all other inbound explicitly (belt-and-suspenders, before the default deny)
az network nsg rule create \
  --name Deny-All-Inbound \
  --nsg-name nsg-snet-web \
  --resource-group rg-networking \
  --priority 4000 \
  --direction Inbound \
  --access Deny \
  --protocol "*" \
  --destination-port-ranges "*" \
  --source-address-prefixes "*" \
  --destination-address-prefixes "*"

Application Security Groups for workload grouping

Application Security Groups (ASGs) let you write NSG rules using workload names rather than IP ranges. Assign VMs to an ASG, then reference the ASG in NSG rules. As VMs are added or removed, the rules stay correct without any IP range updates.

Example: allow the app tier to connect to the database tier on port 1433 without knowing any IP addresses:

# Create ASGs for each workload tier
az network asg create --name asg-web-tier --resource-group rg-networking --location eastus
az network asg create --name asg-app-tier --resource-group rg-networking --location eastus
az network asg create --name asg-db-tier --resource-group rg-networking --location eastus

# NSG rule: only app tier can reach db tier on 1433
az network nsg rule create \
  --name Allow-App-to-DB \
  --nsg-name nsg-snet-data \
  --resource-group rg-networking \
  --priority 200 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --destination-port-ranges 1433 \
  --source-asgs asg-app-tier \
  --destination-asgs asg-db-tier
Tip

ASGs are associated with VM NICs, not subnets. Multiple VMs in the same subnet can belong to different ASGs, enabling fine-grained intra-subnet traffic control that subnet-level NSGs cannot provide.

Azure Firewall for centralised egress control

NSGs control which resources can talk to each other inside your VNet, but they do not filter outbound internet traffic effectively. Azure Firewall is the right tool for centralised egress control — it inspects all outbound traffic from your VNets and enforces policy at the hub.

Azure Firewall supports FQDN-based rules (allow traffic to *.microsoft.com), network rules (allow TCP 443 to a specific IP range), and application rules (allow HTTP/HTTPS to specific FQDNs with TLS inspection in Premium tier). It logs all allowed and denied traffic to Log Analytics.

Deploy Azure Firewall in the hub VNet and route spoke VNet traffic through it using User Defined Routes:

# Route all internet-bound traffic from spoke VNet to Azure Firewall
FIREWALL_IP="10.0.0.4"  # Azure Firewall's private IP in hub VNet

az network route-table create \
  --name rt-spoke-app-to-fw \
  --resource-group rg-networking \
  --location eastus \
  --disable-bgp-route-propagation true

az network route-table route create \
  --route-table-name rt-spoke-app-to-fw \
  --resource-group rg-networking \
  --name route-default-to-firewall \
  --address-prefix 0.0.0.0/0 \
  --next-hop-type VirtualAppliance \
  --next-hop-ip-address $FIREWALL_IP

# Associate the route table with the spoke subnet
az network vnet subnet update \
  --name snet-app \
  --resource-group rg-spoke-app \
  --vnet-name vnet-spoke-app-eastus \
  --route-table rt-spoke-app-to-fw

DDoS Protection

Every Azure subscription automatically receives DDoS Basic protection, which defends against common volumetric attacks at the platform level. It is always on and requires no configuration, but provides no telemetry, alerting, or SLA guarantees.

Azure DDoS Network Protection (formerly DDoS Standard) adds adaptive tuning per public IP, real-time attack telemetry and mitigation metrics in Azure Monitor, attack diagnostics reports, and a cost guarantee (Azure credits your VM, Application Gateway, and Load Balancer costs incurred during an attack).

Enable DDoS Network Protection on the hub VNet containing your public-facing resources:

# Create a DDoS protection plan (required before enabling on VNets)
az network ddos-protection create \
  --name ddosplan-prod \
  --resource-group rg-security \
  --location eastus

# Enable DDoS protection on the hub VNet
az network vnet update \
  --name vnet-hub-eastus \
  --resource-group rg-hub-networking \
  --ddos-protection true \
  --ddos-protection-plan ddosplan-prod

WAF on Application Gateway and Front Door

A Web Application Firewall (WAF) inspects HTTP/HTTPS traffic for application-layer attacks: SQL injection, cross-site scripting (XSS), path traversal, and other OWASP Top 10 exploits. Azure offers WAF integrated into two services:

Application Gateway WAF operates regionally. It terminates TLS, inspects each request, and forwards clean traffic to backend services. Use it for regional applications where you control the ingress point. WAF rules run in Detection mode (log only) or Prevention mode (block matching requests). Start with Detection, review the logs for false positives, then switch to Prevention.

Front Door WAF operates globally at the network edge, before traffic enters any Azure region. It provides the same OWASP rule set plus managed bot protection rules and rate limiting. Use it for global applications or when you want to stop attack traffic before it reaches any region.

Private Endpoints: eliminating public IP exposure

Storage accounts, SQL databases, Key Vaults, Container Registries, and dozens of other Azure PaaS services are accessible over public IP addresses by default. If your applications only need to reach these services from within Azure, there is no reason for those services to have public IP exposure.

Private Endpoints give a PaaS service a private IP in your VNet. You then disable public access entirely on the service. Traffic from your VMs to the service never leaves the Azure network — it goes through the private endpoint IP, which is inside your VNet.

Disabling public access after creating a private endpoint:

# Disable public network access on a storage account
# (after private endpoint is created and DNS is configured)
az storage account update \
  --name mystorageaccount \
  --resource-group rg-prod \
  --public-network-access Disabled

# Disable public access on Azure SQL Database
az sql server update \
  --name sql-prod-001 \
  --resource-group rg-prod \
  --restrict-outbound-network-access true \
  --minimal-tls-version 1.2

Network Watcher for visibility

Security controls are only useful if you know when they fire. Azure Network Watcher provides the visibility layer:

NSG flow logs record every flow allowed or denied by each NSG rule — source IP, destination IP, port, protocol, and allow/deny verdict. Send flow logs to a storage account and query them in Log Analytics to detect unexpected traffic patterns, port scans, or policy violations.

Azure Monitor Traffic Analytics processes NSG flow logs and provides dashboards showing top talkers, flows by geography, and malicious IP connections. It aggregates the raw flow log data into actionable network intelligence.

Microsoft Defender for Cloud analyses your NSG configurations, flags overly permissive rules (like SSH open to the internet), and provides a network map showing resource connectivity and attack surface.

Common mistakes

  1. Opening management ports (SSH/RDP) to the internet. NSG rules allowing TCP 22 or TCP 3389 from source address * are a permanent invitation to brute-force attacks. Use Azure Bastion for browser-based SSH/RDP access with no public port exposure, or Just-in-Time VM Access in Microsoft Defender for Cloud to open ports only when needed and only for specific approved IPs.
  2. Leaving PaaS service public access enabled after creating private endpoints. Creating a private endpoint does not disable public access on the service. If you do not explicitly set the service to reject public connections, attackers can still reach it over the internet using the public endpoint. Always complete the configuration: create the private endpoint, configure DNS, test, then disable public access.
  3. Running Azure Firewall in a spoke VNet instead of the hub. Deploying Azure Firewall in each spoke VNet requires a separate firewall instance per spoke — multiplying cost and management overhead. Azure Firewall belongs in the hub VNet with User Defined Routes directing spoke traffic through it. One firewall instance covers all spokes and gives you a single policy management point.

Frequently asked questions

Should I use NSGs or Azure Firewall — or both?

Both, for different purposes. NSGs are subnet and NIC-level filters that control which ports and IPs can talk to each other within your VNet. Azure Firewall is a centrally managed, stateful firewall that controls all traffic leaving your VNets (egress). NSGs stop lateral movement between workloads. Azure Firewall enforces consistent egress policy and provides FQDN-based filtering that NSGs cannot do.

What is DDoS Protection Standard and when is it worth the cost?

DDoS Protection Standard (now called Azure DDoS Network Protection) adds adaptive tuning, attack telemetry, and cost guarantees on top of the Basic DDoS protection every Azure subscription includes. It costs roughly $2,944/month per protected VNet. It is worth it for public-facing services where downtime has a material business cost — e-commerce, financial services, public APIs. For internal or low-traffic services, Basic protection is sufficient.

What is the difference between WAF on Application Gateway and WAF on Front Door?

Application Gateway WAF operates at the regional level — it protects applications hosted in a specific Azure region. Front Door WAF operates globally at the edge, inspecting traffic before it enters any Azure region. Front Door WAF is better for global applications and bot protection; Application Gateway WAF is appropriate for regional applications where you control the ingress point. Both use OWASP Core Rule Set rules.

Last verified: 19 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.