Microsoft Defender for Cloud · Azure Virtual Network
Virtual networks should be protected by Azure Firewall
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Virtual networks should be protected by Azure Firewall" check?
Flags virtual networks that look like they carry workloads yet have no Azure Firewall deployed. The backing policy, '[Preview]: All Internet traffic should be routed via your deployed Azure Firewall', flags a VNet when it holds a subnet that has two or more IP configurations, has no route table attached at all, and is not named AzureBastionSubnet or GatewaySubnet. The VNet is treated as compliant only when exactly one Azure Firewall has an IP configuration in a subnet named AzureFirewallSubnet. It does not read route table contents, so it never checks for a 0.0.0.0/0 route or a next-hop, and it is audit-only, so it never deploys a firewall or changes routing for you. It does not inspect network security group rules, application gateway WAF, or third-party next-generation firewalls, so a VNet protected by another appliance can still flag.
Why does "Virtual networks should be protected by Azure Firewall" matter?
A subnet with the default 0.0.0.0/0 route reaches the internet directly, with no central point to inspect, log or block egress. That lets a compromised workload reach an attacker's command-and-control endpoint or exfiltrate data unseen, and it leaves you without the per-flow logs an investigation needs. Forcing traffic through Azure Firewall gives you stateful inspection, threat-intelligence-based filtering of known malicious IPs, and a single audited choke point. The business consequence of skipping it is slower breach detection and a weaker story for auditors who expect a defence at the network edge.
How do I fix "Virtual networks should be protected by Azure Firewall"?
- Deploy an Azure Firewall into a dedicated 'AzureFirewallSubnet' in the hub virtual network: 'az network firewall create --name fw01 --resource-group rg-net --location uksouth', then add an IP configuration with 'az network firewall ip-config create' to attach it to the subnet and a public IP.
- Create a route table and a default route pointing at the firewall's private IP, then associate it with the workload subnets: 'az network route-table route create --route-table-name rt-egress --resource-group rg-net --name to-fw --address-prefix 0.0.0.0/0 --next-hop-type VirtualAppliance --next-hop-ip-address <firewall-private-ip>' followed by 'az network vnet subnet update --vnet-name spoke-vnet --name workloads --route-table rt-egress'.
- To enforce this at scale, assign the built-in policy by its exact display name so a missing route is reported across every subscription: 'pid=$(az policy definition list --query "[?displayName=='[Preview]: All Internet traffic should be routed via your deployed Azure Firewall'].name" -o tsv)' then 'az policy assignment create --name route-via-firewall --policy "$pid" --scope /subscriptions/<sub-id>'.
Remediation script · bash
# Create one shared DDoS protection plan, then bring the internet-facing
# virtual networks under it. A single plan can be shared across every
# subscription in the tenant; its fixed monthly charge covers up to 100
# public IP addresses.
RG=net-hub-rg
LOC=uksouth
az network ddos-protection create \
--resource-group "$RG" \
--name ddos-plan-shared \
--location "$LOC"
for vnet in vnet-payments-prod vnet-web-prod; do
az network vnet update \
--resource-group "$RG" \
--name "$vnet" \
--ddos-protection true \
--ddos-protection-plan ddos-plan-shared
echo "$vnet: associated with shared DDoS Network Protection plan"
done
# Stand up a Premium Azure Firewall policy in the hub with IDPS and
# threat intelligence both in Deny mode (deploy the firewall + route
# 0.0.0.0/0 to its private IP from each spoke to complete the path).
az network firewall policy create \
--resource-group "$RG" \
--name hub-fw-policy \
--location "$LOC" \
--sku Premium \
--threat-intel-mode Deny \
--idps-mode Deny
# Ratchet it shut: assign the built-in policy that requires DDoS protection
# on virtual networks. Look the definition up by its exact display name so
# no GUID is hardcoded.
pid=$(az policy definition list \
--query "[?displayName=='Virtual networks should be protected by Azure DDoS Protection'].name" -o tsv)
az policy assignment create \
--name require-vnet-ddos \
--policy "$pid" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Protect Azure networks with DDoS and firewalls.
Is "Virtual networks should be protected by Azure Firewall" a false positive?
A perimeter virtual network whose egress is deliberately handled by a third-party next-generation firewall NVA, or by an on-premises firewall reached over ExpressRoute, still flags because the policy only recognises a native Azure Firewall resource deployed in an AzureFirewallSubnet, never another appliance. If that appliance already inspects all internet-bound traffic, this is a correct exception: exempt the VNet from the assignment rather than deploying a redundant Azure Firewall alongside it.