Australian cloud for business software — built and run in Sydney since 2003

NetLeverage
NetLeverage

Azure hub-and-spoke: why VNet peering is not transitive, and how to prove the path

Technical article
Cloud

About this article: AI-assisted writing, reviewed against the cited sources. This is source research, not a lab validation of the procedures. Check the stated versions and your own recovery requirements before making changes.

Two spokes peered to the same hub cannot reach each other by default. A peering is a nontransitive relationship between exactly two virtual networks, and it only gives each side routes for the other side's address space. A virtual machine in Spoke A has no route to Spoke B. With private address space and no on-premises or custom route covering that range, Azure drops the packet before it leaves the subnet.

The fix is one of four things: a direct peering between the spokes, a route through a forwarding device in the hub, a connected group in Azure Virtual Network Manager, or a move to Virtual WAN. Whichever you choose, prove the result from the platform's own route data rather than from a ping that happens to succeed.

All commands below come from Microsoft's published reference. They were not run in a lab for this article, and the addresses are examples.

Why it matters

The failure looks like a firewall problem. Peering status shows Connected, the hub can reach both spokes, and the network security groups look fine. Engineers then spend hours on the firewall when the packet never arrived at it.

The opposite fault is worse. A hub firewall can be deployed with policies and logging in place while some traffic takes a path around it, because a more specific route exists. Connectivity works, so nobody looks. Reading the effective routes finds both faults.

How Azure chooses a route

Azure creates a route table for each subnet and fills it with system routes. Selection then follows two rules, in this order:

  1. Longest prefix match. A /24 beats a /16 for any address inside the /24.
  2. Source priority for identical prefixes. A user-defined route (UDR) beats a BGP route, and a BGP route beats a system route.

Microsoft adds an exception that catches people: system routes for the virtual network, for peerings and for service endpoints are preferred even if BGP routes are more specific. Routes with a service endpoint next hop cannot be overridden at all.

Where the non-transitive behaviour shows up

When you peer two networks, Azure adds a route for each address range in the address space of each network in that peering. It does not add the ranges that the other network has peered with.

Take this example layout:

Network Address space
Hub 10.0.0.0/16
Spoke A 10.1.0.0/16
Spoke B 10.2.0.0/16

A network interface in Spoke A would have a table of this general shape. This table is illustrative, not captured output.

Source Prefix Next hop type
Default 10.1.0.0/16 Virtual network
Default 10.0.0.0/16 Virtual network peering
Default 0.0.0.0/0 Internet
Default 10.0.0.0/8 None
Default 172.16.0.0/12 None
Default 192.168.0.0/16 None
Default 100.64.0.0/10 None

Now trace 10.2.0.5. No route names Spoke B. The longest match is the default 10.0.0.0/8 route, whose next hop is None. Traffic sent to None is dropped rather than routed out of the subnet.

In this table the drop happens in the source subnet's routing, so the hub firewall logs nothing and a capture on the destination shows nothing.

The table is one common state, not the only one. Under the same selection rules, a gateway or custom route covering the destination would win over the default None route, and a spoke outside the default None ranges would match 0.0.0.0/0 to Internet instead (our reasoning from Microsoft's rules). Step 2 below shows which case you are in.

Azure's default table contains further None routes, such as 127.0.0.0/8. The four above are the ones most relevant to private addressing.

What the peering settings do and do not do

Two settings and one peering state are often confused, and none of them creates a route to another spoke.

Allow forwarded traffic lets a network accept traffic that did not originate in the peered network. Microsoft states that it does not create any user-defined routes or network virtual appliances. Ticking it alone changes nothing about reachability.

Allow gateway transit on the hub, paired with Use remote gateways on the spoke, lets the spoke use a VPN or ExpressRoute gateway in the peered network. A network using a remote gateway cannot also have its own, and the transit option works with all VPN Gateway SKUs except Basic.

Status must be Connected on both sides. A first link shows Initiated, and the peering is not established until both are Connected.

Building spoke-to-spoke through the hub

To send spoke traffic through a firewall or network virtual appliance (NVA) in the hub, every one of these has to be true. Assume the appliance is at 10.0.1.4.

  1. Spoke A has a UDR for 10.2.0.0/16 with next hop type VirtualAppliance and next hop 10.0.1.4.
  2. Spoke B has the mirror route for 10.1.0.0/16. Without it, the return path is broken or takes a different route.
  3. The peering connections allow forwarded traffic. Microsoft's reference architecture says to configure all peering connections to allow it.
  4. For a VM-based appliance, the network interface has Azure IP forwarding enabled. Azure otherwise applies a source and destination check to that interface.
  5. For a VM-based appliance, the guest operating system also forwards. Azure's setting and the operating system's setting are separate.
  6. The appliance's policy permits the flow, and it has routes back to both spokes.
  7. The appliance sits in its own subnet. Microsoft warns that placing it in the same subnet as the workloads it serves, then applying the route table there, can cause routing loops.

The next hop must also be directly reachable. A next hop that would need to pass through an ExpressRoute gateway or Virtual WAN makes the UDR invalid.

The summary-route trap

It is tempting to give each spoke one route: 10.0.0.0/8 to the firewall. That handles Spoke A to Spoke B, because 10.2.0.5 has no more specific route. It does not handle Spoke A to the hub.

The peering route for 10.0.0.0/16 is longer than /8, so longest prefix match sends hub-bound traffic straight across the peering, around the firewall. If hub-hosted services need inspection, add a route that matches the peering prefix exactly, or a more specific one. For an identical prefix, the UDR wins over the system route.

This is an inference from Microsoft's published selection rules, and the effective routes will confirm it for your subnet.

A preview feature that does not help here yet

Azure has a public preview called disable peering route propagation. It suppresses peering routes so that a summary UDR can take over. During preview, the firewall or NVA next hop must be in the same virtual network as the source workload, and a next hop in a peered network is not supported. A classic hub firewall is exactly that unsupported case, so check the current restrictions before planning around it.

The proof sequence

Work in this order. Each step removes one class of fault before the next step depends on it.

Step 1: confirm the peering on both sides

az network vnet peering show \
  --resource-group <rg> --vnet-name <vnet> --name <peering-name> \
  --query peeringState

Run it for both networks. Microsoft's troubleshooter lists three states: Initiated means only the first link exists, Connected means both exist, and Disconnected means one link was deleted.

Disconnected cannot be repaired in place. Microsoft says you must delete the links on both networks and re-create them. It also lists an unsynchronised address-space change as a possible cause. After you resize a peered network, peers must sync with the new address space, which az network vnet peering sync performs.

Deleting a peering interrupts traffic between those networks. Treat it as a change with a window.

Step 2: read the effective routes

az network nic show-effective-route-table \
  --resource-group <rg> --name <nic-name> --output table

Effective routes are the combination of default routes and any custom routes for that interface. Output is returned only while the VM is running. A VM with several interfaces can have different routes on each, so query the interface that carries the traffic.

Look for these:

  • Is there a route to the destination at all? If the longest match is 10.0.0.0/8 with None, you have found the fault.
  • Does a peering route exist for the hub? Peering routes confirm that the peering is delivering address space.
  • Is the next hop IP populated? Microsoft notes that a Virtual appliance or Virtual network gateway hop showing None as its next hop IP may mean the device is not running or not fully configured.

Step 3: ask for the next hop of one specific flow

az network watcher show-next-hop \
  --resource-group <rg> --vm <source-vm> \
  --source-ip 10.1.0.4 --dest-ip 10.2.0.5

Next hop returns the type, the IP and the route table ID. If a UDR selected the hop, you get the route table that holds it. Otherwise it reports System Route. This command removes the need to work out longest prefix match by eye, and it requires Network Watcher to be enabled in the VM's region. If the VM has several network interfaces and IP forwarding is enabled on any of them, --nic is required, which is the usual case on an appliance.

What to expect:

Result Meaning
None Dropped in the source subnet. Add a route or a peering.
VirtualAppliance, 10.0.1.4, your route table The UDR is being used. Move on to the appliance.
VirtualNetworkPeering Direct peering is carrying it, and the firewall is not in the path.
Internet A public or unmatched destination, or a typed address that is not what you meant.

Then run it again in the reverse direction, from the destination VM back to the source. Next hop answers for one direction only. A forward path through the firewall with a return path over a peering is the classic asymmetric flow, and a stateful firewall will commonly discard it.

Step 4: test the actual connection

az network watcher test-connectivity \
  --source-resource <source-vm-id> --dest-resource <dest-vm-id> \
  --protocol Tcp --dest-port 443

Connection troubleshoot returns Reachable or Unreachable with a hop-by-hop list. Each hop can carry issues of the type NetworkSecurityRule, UserDefinedRoute, GuestFirewall, DnsResolution, CPU or Memory, each with an origin of inbound, outbound or local.

Three cautions apply. The test-connectivity CLI command is marked preview. Traditional tests need the Network Watcher agent extension on the source VM, and the agentless experience is itself in preview. If you are testing across resource groups, use resource IDs rather than names, and the CLI reference says the same for VMs in different regions.

Step 5: look inside the appliance only when the platform is clean

If the next hop is the appliance in both directions and connection troubleshoot points past the platform, the problem is in the appliance's configuration. Check its logs for the flow first, then capture.

Microsoft's peering troubleshooter suggests a trace on the destination, using Netsh on Windows or tcpdump on Linux, while running a TCP ping from the source. A SYN that arrives and gets no reply points to the destination's guest firewall or service. A SYN that never arrives points back to the appliance.

Microsoft also suggests temporarily removing the UDR to test the direct path.

Warning: removing that route sends traffic around your inspection point and may break policy or compliance requirements. Record the original route, get change approval, keep the window short and restore the route straight away.

What to choose and why

These are editorial recommendations built on the facts above.

Need Option Trade-off
Two spokes, high volume, low risk Direct peering Lowest latency, and no inspection. Microsoft notes it can cut firewall processing costs, but in a hub-spoke design says to use it only in special circumstances.
Central inspection of east-west traffic UDRs to a hub firewall or NVA Full control. You own route maintenance and appliance capacity.
Many spokes that must talk directly Azure Virtual Network Manager connected group Up to 3,000 networks in a mesh. Group membership is still nontransitive. Microsoft recommends limiting direct connectivity to spokes in the same environment and workload, so do not mesh production with development on this table's strength.
Few flows, a VPN gateway already in the hub UDR to the gateway Microsoft warns of latency and throughput impact. VPN gateways only, not ExpressRoute.
You want Microsoft to run the hub Virtual WAN Less control, and some NVAs are not supported.

If a network is connected both by peering and through a gateway, traffic uses the peering. A VNet-to-VNet tunnel left in place as a "backup" will therefore carry nothing while the peering stands.

Risks and limits

  • As checked on 9 November 2026, the published limits are 650 peerings per virtual network and 1,000 UDRs per route table for Resource Manager networks. With a per-spoke UDR in every spoke, route count grows with spoke count. Use summarised routes where the trap above does not apply.
  • Azure charges ingress and egress at both ends of a peering. Forwarding through a hub crosses two peerings (our reasoning), and adds firewall processing costs where a firewall is used. Include both in the design cost.
  • Spoke-side changes can leave clients stale. After establishing or changing a peering, Microsoft says point-to-site clients must download and reinstall the VPN package to receive routes to the spoke.
  • Never disable route propagation on GatewaySubnet. Microsoft states that the gateway stops functioning if you do.
  • Effective routes and next hop describe the Azure platform only. They say nothing about routes inside a guest operating system or an appliance.
  • This article's commands were not lab tested. Test them in a non-production subscription first.

Sources

Opened 9 November 2026. Sources behind the corrections reopened 10 November 2026.