How Azure Firewall Decides: 5 Packets Through a Hub and Spoke, Rule by Rule
▶ Watch on YouTube & subscribe to The Stack Underflow
In many Azure networks, workloads live in separate virtual networks called spokes, and all their traffic goes through one shared firewall in a central network, the hub. How does a packet find the firewall, and how does the firewall decide? The video builds a hub from Microsoft’s quickstart Bicep template azurefirewall-create-with-firewallpolicy-apprule-netrule-ipgroups, adds two spokes, and follows five packets. This page walks the same packets with every rule and the documentation behind it.
The one-line version: a 0.0.0.0/0 route in each spoke brings its traffic to the firewall. The firewall checks DNAT rules, then network rules, then application rules, and the first match decides. No match means denied.
Last verified against Microsoft Learn: 1 October 2026.
Getting to the firewall
- Each spoke is peered with the hub. Peering is not transitive: if spoke A and spoke B are each peered only with the hub, A can’t reach B directly.
- Each spoke subnet gets a route table with one route:
0.0.0.0/0→ virtual appliance, the firewall’s private IP. A user-defined route beats the system0.0.0.0/0→ Internet route for the same prefix, so everything without a more specific route goes to the firewall. That includes traffic for the other spoke, because the spokes have no peering route to each other.
How Azure Firewall decides
Default deny. Azure Firewall denies all traffic until you configure rules to allow it, and rules are terminating: processing stops on a match.
Structure. In a Firewall Policy, rules live in rule collections, and collections live in rule collection groups. A collection holds rules of one type (DNAT, network or application) and has one action. Groups and collections each have a priority from 100 (highest) to 65,000 (lowest). Policies can inherit from a parent, and the parent’s rule collection groups always come first.
Three passes. The firewall always processes DNAT rules, then network rules, then application rules, regardless of rule collection group or collection priority, and regardless of inheritance. Priorities order things within each pass. If threat intelligence filtering is enabled, it’s processed before all of them.
| Rule type | Matches on | Notes |
|---|---|---|
| DNAT | Inbound traffic to the firewall’s public IP | A match is translated and allowed, no network rule needed |
| Network | Source, destination address, protocol, port | A match ends processing: application rules aren’t checked |
| Application | Host name (FQDN) or FQDN tag | Only for HTTP, HTTPS or MSSQL. For HTTPS without TLS inspection, the name the client sends in the TLS handshake (SNI) |
If no application rule matches, the packet is checked against a built-in infrastructure rule collection (a short list of Azure platform FQDNs), and then denied by default.
IP groups are named lists of addresses, ranges and prefixes. They can be the source of DNAT, network and application rules, and the destination of network rules.
The lab
Hub (from the template): hub VNet 10.10.0.0/24, AzureFirewallSubnet 10.10.0.0/25, the firewall hub-fw. Its private IP is shown as 10.10.0.4, the usual first address of its subnet (Azure doesn’t guarantee which address a dynamic allocation gets).
IP groups: workload = 10.20.0.0/24, 10.30.0.0/24; infra = 10.40.0.0/24, 10.50.0.0/24.
Firewall policy (from the template):
| Group (priority) | Collection (priority) | Rule | Allows | Sources |
|---|---|---|---|---|
| DefaultNetworkRuleCollectionGroup (200) | azure-global-services-nrc (1250) | time-windows (network) | UDP 123 to 13.86.101.172 | workload, infra IP groups |
| DefaultApplicationRuleCollectionGroup (300) | global-rule-url-arc (1000) | winupdate-rule-01 (application) | HTTPS/HTTP to the WindowsUpdate FQDN tag | workload, infra IP groups |
| DefaultApplicationRuleCollectionGroup (300) | Global-rules-arc (1202) | global-rule-01 (application) | HTTPS to www.microsoft.com | workload, infra IP groups |
There are no DNAT rules. The WindowsUpdate tag is a list of names Microsoft manages (you can’t see or edit its contents), so the video doesn’t simulate it.
Spokes (added for the video): spoke-app (10.20.0.0/24) with app-1 at 10.20.0.4, inside the workload IP group; spoke-lab (10.60.0.0/24) with lab-1 at 10.60.0.4, in no IP group. Both spoke subnets use the route table spoke-routes (0.0.0.0/0 → 10.10.0.4). Neither spoke has an NSG, so the firewall is the only guard.
Five packets, step by step
Packet 1: app-1 syncs its clock. 10.20.0.4 → 13.86.101.172, UDP 123 (NTP).
The 0.0.0.0/0 UDR sends it to 10.10.0.4. DNAT: none. Network rules: time-windows matches (source in the workload IP group, destination, protocol and port exact). Allowed. Because the destination is a public address, the firewall sends it on with its own public IP as the source (SNAT); AzureFirewallSubnet has no route table, so the system 0.0.0.0/0 route sends it to the Internet.
Packet 2: app-1 opens https://www.microsoft.com. 10.20.0.4 → 203.0.113.80, TCP 443. To the firewall via the UDR. Network rules: time-windows is for 13.86.101.172, so no match; on to application rules. winupdate-rule-01 uses the WindowsUpdate tag (not simulated). global-rule-01 matches: the client asked for www.microsoft.com in the TLS handshake (SNI). Allowed, sent on with the firewall’s public IP as the source. Application rules match the name, not the IP address.
Packet 3: app-1 opens https://example.org. 10.20.0.4 → 203.0.113.90, TCP 443. Network rules: no match. Application rules: the WindowsUpdate tag (not simulated); global-rule-01 is for www.microsoft.com, not example.org. No rule matched in any pass. Denied. To allow it, you’d add example.org to an application rule.
Packet 4: lab-1 tries the same time server. 10.60.0.4 → 13.86.101.172, UDP 123. Same destination, protocol and port as packet 1, but 10.60.0.4 is in neither IP group, so time-windows’ source doesn’t match. No rule allows it. Denied. IP groups decide who a rule is for. (See the correction note below on how this packet is processed after the network rules.)
Packet 5: app-1 talks to lab-1 in the other spoke. 10.20.0.4 → 10.60.0.4, TCP 443.
spoke-app isn’t peered with spoke-lab, and peering isn’t transitive, so the only route is 0.0.0.0/0 to the firewall. Network rules: time-windows is for 13.86.101.172, no match. Application rules: the WindowsUpdate tag (not simulated); global-rule-01 has no host name in this packet to match. Denied: the firewall has no rule for spoke-to-spoke traffic.
| # | Packet | Verdict | Decided by |
|---|---|---|---|
| 1 | app-1 → NTP, UDP 123 | Allowed | network rule time-windows |
| 2 | app-1 → www.microsoft.com, TCP 443 | Allowed | application rule global-rule-01 (SNI) |
| 3 | app-1 → example.org, TCP 443 | Denied | no rule: default deny |
| 4 | lab-1 → NTP, UDP 123 | Denied | no rule: source not in any IP group |
| 5 | app-1 → lab-1, TCP 443 | Denied | no rule for spoke-to-spoke |
What to remember
- A default route in each spoke brings its traffic to the firewall.
- DNAT, then network, then application rules, whatever the priorities say; the first match decides.
- Application rules match host names; network rules match addresses, protocols and ports.
- No matching rule means denied.
Pause & Prove: the questions from the video
1. The pinned question
The firewall policy has one network rule (UDP 123 to a time server, from the workload IP group 10.20.0.0/24 and 10.30.0.0/24) and two application rules. lab-1 at 10.60.0.4 sends UDP 123 to that exact time server. Allowed or denied?
Denied. Same destination, protocol and port, but 10.60.0.4 is in neither IP group, so the rule’s source doesn’t match, and Azure Firewall denies traffic no rule allows.
2. The Community poll
Azure Firewall has a DNAT rule at priority 500 and a network rule at priority 100. Which pass does the firewall check first?
- The network rule: lower number first. Tempting, but priority numbers only order rules within a pass.
- The DNAT rule: DNAT is always first. ✓ The order is always DNAT, network, application.
- Application rules first. Application rules are always last.
- Whichever was created first. Creation order plays no part.
Related Shorts
- Azure Firewall’s default answer is no (packet 3)
- Azure Firewall application rules match names, not IPs (packet 2)
- Same server, same port, still denied: Azure Firewall IP groups (packet 4)
Before / after this video
- Before: How Azure NSGs Allow or Deny a Packet (video 1), Azure Route Tables and NVAs (video 2: how a UDR sends traffic to an appliance), Azure Subnet NSG vs NIC NSG (video 3)
- After: Why Your Azure VM Can’t Reach On-Premises: VPN vs ExpressRoute, Packet by Packet, where the packet leaves Azure (words first: the hybrid networking primer)
Sources
Read on 1 October 2026:
- Azure Firewall rule processing logic: default deny, terminating rules, groups/collections and priorities 100–65,000, parent policy first, DNAT → network → application regardless of priority, threat intelligence first, network match skips application rules, application rules only for HTTP/HTTPS/MSSQL, SNI for HTTPS, infrastructure rule collection, DNAT match allowed
- IP Groups in Azure Firewall: what IP groups contain and where they can be used
- FQDN tags overview: WindowsUpdate tag, managed by Microsoft
- Azure Firewall SNAT private IP address ranges: network rules SNAT to public destinations; application rules always SNAT
- Azure Virtual Network FAQ: transitive peering isn’t supported
- Azure virtual network traffic routing: 0.0.0.0/0 UDR to a virtual appliance overrides the system route
- Private IP addresses: dynamic allocation is usually, not always, the next address
- Hub template: “azurefirewall-create-with-firewallpolicy-apprule-netrule-ipgroups” from Azure/azure-quickstart-templates (MIT License)
Change notes
- 1 Oct 2026: first published.
- Correction (1 Oct 2026): for packet 4 (lab-1, UDP 123) the video shows the firewall moving on to the two application rules and rejecting each on its source. Microsoft documents that application rules are evaluated only when no network rule matched and the protocol is HTTP, HTTPS or MSSQL, so a UDP NTP packet isn’t checked against application rules at all: no rule allows it, so the firewall denies it by default. The verdict (denied) is the same.
- Clarification (1 Oct 2026): the video says the policy groups rules into “rule collection groups, then collections, then rules, each with a priority”. In a Firewall Policy, the priority numbers belong to rule collection groups and rule collections; the page above states it that way.
Not affiliated with or endorsed by Microsoft. Found a mistake? Tell us in the video’s comments and we’ll correct this page.
Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.
Subscribe on YouTube →Prefer email? Get the free newsletter: one failure, traced step by step, about once a week.