How Azure Firewall Decides: 5 Packets Through a Hub and Spoke, Rule by Rule

September 30, 2026 · Azure Networking, Packet by Packet: NSGs, Route Tables, ASGs and Azure Firewall (part 4)

▶ 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 system 0.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 typeMatches onNotes
DNATInbound traffic to the firewall’s public IPA match is translated and allowed, no network rule needed
NetworkSource, destination address, protocol, portA match ends processing: application rules aren’t checked
ApplicationHost name (FQDN) or FQDN tagOnly 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)RuleAllowsSources
DefaultNetworkRuleCollectionGroup (200)azure-global-services-nrc (1250)time-windows (network)UDP 123 to 13.86.101.172workload, infra IP groups
DefaultApplicationRuleCollectionGroup (300)global-rule-url-arc (1000)winupdate-rule-01 (application)HTTPS/HTTP to the WindowsUpdate FQDN tagworkload, infra IP groups
DefaultApplicationRuleCollectionGroup (300)Global-rules-arc (1202)global-rule-01 (application)HTTPS to www.microsoft.comworkload, 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.

#PacketVerdictDecided by
1app-1 → NTP, UDP 123Allowednetwork rule time-windows
2app-1 → www.microsoft.com, TCP 443Allowedapplication rule global-rule-01 (SNI)
3app-1 → example.org, TCP 443Deniedno rule: default deny
4lab-1 → NTP, UDP 123Deniedno rule: source not in any IP group
5app-1 → lab-1, TCP 443Deniedno 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.

Before / after this video

Sources

Read on 1 October 2026:

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.