Skip to main content

Challenge 08: User-defined routes & forced tunneling

Estimated time and cost

90-120 minutes | ~$2-4/hour (NVA VMs running) | Exam weight: 15-20%

Prerequisite

AZ-104 Challenge 24 covers basic UDR concepts (creating a route table, adding a single route, associating with a subnet). This challenge builds on that foundation with enterprise forced tunneling, multi-path routing, BGP route propagation control, and effective route troubleshooting.

Scenario

Contoso's security team requires ALL internet-bound traffic from Azure spoke VNets to flow through a centralized Network Virtual Appliance (NVA) firewall in the hub VNet for inspection. Additionally, specific traffic destined to on-premises networks should use different NVAs based on destination. The network team must implement multi-path routing with UDRs, configure forced tunneling for compliance, and troubleshoot routing conflicts between BGP-learned routes and static UDRs.

Network topology:

On-Premises192.168.0.0/16VPN Gateway (BGP)Hub VNet (10.0.0.0/16)GatewaySubnet (10.0.0.0/27)NVA-A Subnet (10.0.1.0/24)NVA-A: 10.0.1.4NVA-B Subnet (10.0.2.0/24)NVA-B: 10.0.2.4VNet PeeringPeeredSpoke VNet (10.1.0.0/16)Workload Subnet (10.1.1.0/24)App Subnet (10.1.2.0/24)

Learning objectives

After completing this challenge you will be able to:

  • Create route tables with BGP route propagation disabled
  • Implement forced tunneling using UDRs with 0.0.0.0/0 prefix
  • Configure multi-path routing with different NVAs per destination
  • Enable IP forwarding on NVA network interfaces
  • Analyze effective routes to verify routing behavior
  • Use Network Watcher next-hop to diagnose routing issues
  • Resolve conflicts between BGP-learned routes and UDRs

Prerequisites

  • An Azure subscription with Contributor access
  • Azure CLI installed and authenticated (az login)
  • Network Watcher enabled in the target region
  • Basic understanding of routing concepts (from AZ-104 Challenge 24)

Key concepts for AZ-700

ConceptDetail
Route priorityUDR > BGP > System routes
Longest prefix matchMost specific prefix always wins regardless of source
Forced tunneling0.0.0.0/0 next-hop to VirtualAppliance or VNetGateway
BGP propagationWhen disabled on a route table, BGP routes are not injected into that subnet
IP forwardingMust be enabled on the NVA NIC; otherwise Azure drops forwarded packets
Next-hop VirtualApplianceMust reference an IP in a directly reachable subnet

Task 1: Create resource group and network infrastructure

Set up the hub-spoke topology with NVA subnets.

Step 1: Create the resource group

az group create \
--name rg-routing-lab \
--location eastus2

Step 2: Create the hub virtual network with NVA subnets

az network vnet create \
--resource-group rg-routing-lab \
--name vnet-hub \
--location eastus2 \
--address-prefixes 10.0.0.0/16 \
--subnet-name snet-nva-a \
--subnet-prefixes 10.0.1.0/24

az network vnet subnet create \
--resource-group rg-routing-lab \
--vnet-name vnet-hub \
--name snet-nva-b \
--address-prefixes 10.0.2.0/24

az network vnet subnet create \
--resource-group rg-routing-lab \
--vnet-name vnet-hub \
--name GatewaySubnet \
--address-prefixes 10.0.0.0/27

Step 3: Create the spoke virtual network

az network vnet create \
--resource-group rg-routing-lab \
--name vnet-spoke \
--location eastus2 \
--address-prefixes 10.1.0.0/16 \
--subnet-name snet-workload \
--subnet-prefixes 10.1.1.0/24

az network vnet subnet create \
--resource-group rg-routing-lab \
--vnet-name vnet-spoke \
--name snet-app \
--address-prefixes 10.1.2.0/24

Step 4: Peer the hub and spoke VNets

az network vnet peering create \
--resource-group rg-routing-lab \
--name hub-to-spoke \
--vnet-name vnet-hub \
--remote-vnet vnet-spoke \
--allow-forwarded-traffic \
--allow-gateway-transit

az network vnet peering create \
--resource-group rg-routing-lab \
--name spoke-to-hub \
--vnet-name vnet-spoke \
--remote-vnet vnet-hub \
--allow-forwarded-traffic \
--use-remote-gateways false

Step 5: Deploy simulated NVA VMs (Linux with IP forwarding)

az vm create \
--resource-group rg-routing-lab \
--name vm-nva-a \
--image Ubuntu2204 \
--size Standard_B1s \
--vnet-name vnet-hub \
--subnet snet-nva-a \
--private-ip-address 10.0.1.4 \
--public-ip-address pip-nva-a \
--admin-username azureuser \
--generate-ssh-keys \
--no-wait

az vm create \
--resource-group rg-routing-lab \
--name vm-nva-b \
--image Ubuntu2204 \
--size Standard_B1s \
--vnet-name vnet-hub \
--subnet snet-nva-b \
--private-ip-address 10.0.2.4 \
--public-ip-address pip-nva-b \
--admin-username azureuser \
--generate-ssh-keys \
--no-wait

Step 6: Deploy a workload VM in the spoke

az vm create \
--resource-group rg-routing-lab \
--name vm-workload \
--image Ubuntu2204 \
--size Standard_B1s \
--vnet-name vnet-spoke \
--subnet snet-workload \
--private-ip-address 10.1.1.4 \
--public-ip-address pip-workload \
--admin-username azureuser \
--generate-ssh-keys

Task 2: Create route tables with BGP propagation disabled

In enterprise hub-spoke topologies, you typically disable BGP route propagation on spoke subnets so that on-premises routes learned via the VPN/ExpressRoute gateway do not override your UDRs.

Step 1: Create a route table with BGP propagation disabled

az network route-table create \
--resource-group rg-routing-lab \
--name rt-spoke-workload \
--location eastus2 \
--disable-bgp-route-propagation true

The --disable-bgp-route-propagation true parameter prevents BGP-learned routes from being injected into this route table. This is critical when you want UDRs to take full control of routing decisions.

Step 2: Create a second route table for the app subnet

az network route-table create \
--resource-group rg-routing-lab \
--name rt-spoke-app \
--location eastus2 \
--disable-bgp-route-propagation true

Step 3: Verify the route table configuration

az network route-table show \
--resource-group rg-routing-lab \
--name rt-spoke-workload \
--query "{Name:name, DisableBgp:disableBgpRoutePropagation}" \
--output table

Expected output shows DisableBgp: true.

Exam note

When disableBgpRoutePropagation is set to true, BGP routes from VPN Gateway or ExpressRoute are NOT propagated to the subnet. This means the only routes available are system routes and your explicit UDRs. If you still need the subnet to reach on-premises, you must add explicit UDRs for those prefixes.


Task 3: Add UDRs for forced tunneling

Forced tunneling sends all internet-bound traffic (0.0.0.0/0) to an NVA or VPN gateway instead of directly to the internet. This is a compliance requirement for many organizations.

Step 1: Add the forced tunneling route (default route to NVA-A)

az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--name route-forced-tunnel \
--address-prefix 0.0.0.0/0 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.4

This route overrides the system default route (0.0.0.0/0 to Internet) and forces all internet-bound traffic through NVA-A at 10.0.1.4.

Step 2: Add specific routes for different on-premises destinations

Route traffic to different NVAs based on the destination on-premises subnet:

# Traffic to on-prem subnet 192.168.1.0/24 goes via NVA-A
az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--name route-onprem-site-a \
--address-prefix 192.168.1.0/24 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.4

# Traffic to on-prem subnet 192.168.2.0/24 goes via NVA-B
az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--name route-onprem-site-b \
--address-prefix 192.168.2.0/24 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.2.4

Step 3: Add routes to the app subnet route table

az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-app \
--name route-forced-tunnel \
--address-prefix 0.0.0.0/0 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.4

az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-app \
--name route-onprem-site-a \
--address-prefix 192.168.1.0/24 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.4

az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-app \
--name route-onprem-site-b \
--address-prefix 192.168.2.0/24 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.2.4

Step 4: List routes in the table to verify

az network route-table route list \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--output table
Exam note

Valid --next-hop-type values are: VirtualAppliance, VNetGateway, VNetLocal, Internet, and None. The VirtualAppliance type requires --next-hop-ip-address to be specified. The None type drops traffic (blackhole route).


Task 4: Associate route tables with spoke subnets

A route table has no effect until it is associated with one or more subnets. Each subnet can have at most one route table associated.

Step 1: Associate route table with the workload subnet

az network vnet subnet update \
--resource-group rg-routing-lab \
--vnet-name vnet-spoke \
--name snet-workload \
--route-table rt-spoke-workload

Step 2: Associate route table with the app subnet

az network vnet subnet update \
--resource-group rg-routing-lab \
--vnet-name vnet-spoke \
--name snet-app \
--route-table rt-spoke-app

Step 3: Verify the association

az network vnet subnet show \
--resource-group rg-routing-lab \
--vnet-name vnet-spoke \
--name snet-workload \
--query "routeTable.id" \
--output tsv
Important

After associating the forced tunneling route table, VMs in the subnet will lose direct internet access. Outbound internet traffic will be routed to the NVA. If the NVA is not configured to forward or NAT this traffic, connectivity breaks. This is expected behavior for forced tunneling.


Task 5: Enable IP forwarding on NVA NICs

By default, Azure drops packets not addressed to a NIC's own IP. For an NVA to forward traffic between subnets, IP forwarding must be enabled at the Azure platform level (on the NIC resource) and inside the guest OS.

Step 1: Enable IP forwarding on NVA-A NIC (Azure platform level)

az network nic update \
--resource-group rg-routing-lab \
--name vm-nva-aVMNic \
--ip-forwarding true

Step 2: Enable IP forwarding on NVA-B NIC

az network nic update \
--resource-group rg-routing-lab \
--name vm-nva-bVMNic \
--ip-forwarding true
Finding the NIC name

If you are unsure of the NIC name, retrieve it from the VM:

az vm show \
--resource-group rg-routing-lab \
--name vm-nva-a \
--query "networkProfile.networkInterfaces[0].id" \
--output tsv

Step 3: Verify IP forwarding is enabled

az network nic show \
--resource-group rg-routing-lab \
--name vm-nva-aVMNic \
--query "enableIPForwarding" \
--output tsv

Expected output: true

Step 4: Enable IP forwarding inside the guest OS (Linux)

SSH into each NVA and enable kernel-level forwarding:

# On the NVA VM (via SSH):
sudo sysctl -w net.ipv4.ip_forward=1

# Make persistent across reboots:
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Exam note

IP forwarding must be enabled in TWO places: (1) on the Azure NIC resource using az network nic update --ip-forwarding true, and (2) inside the guest operating system. Missing either one causes the NVA to drop forwarded packets silently.


Task 6: Verify effective routes and diagnose with Network Watcher

Effective routes show the combined result of system routes, UDRs, and BGP-learned routes. This is the primary troubleshooting tool for routing issues.

Step 1: View effective routes on the workload VM NIC

az network nic show-effective-route-table \
--resource-group rg-routing-lab \
--name vm-workloadVMNic \
--output table

Expected output should show:

  • 0.0.0.0/0 with next hop VirtualAppliance and IP 10.0.1.4 (source: User)
  • 192.168.1.0/24 with next hop VirtualAppliance and IP 10.0.1.4 (source: User)
  • 192.168.2.0/24 with next hop VirtualAppliance and IP 10.0.2.4 (source: User)
  • 10.1.0.0/16 with next hop VNetLocal (source: Default)

Step 2: Use Network Watcher next-hop to test internet-bound traffic

az network watcher show-next-hop \
--resource-group rg-routing-lab \
--vm vm-workload \
--source-ip 10.1.1.4 \
--dest-ip 8.8.8.8

Expected result: nextHopType: VirtualAppliance, nextHopIpAddress: 10.0.1.4 — confirming forced tunneling is active.

Step 3: Test routing to on-premises site A

az network watcher show-next-hop \
--resource-group rg-routing-lab \
--vm vm-workload \
--source-ip 10.1.1.4 \
--dest-ip 192.168.1.10

Expected: next hop is VirtualAppliance with IP 10.0.1.4 (NVA-A).

Step 4: Test routing to on-premises site B

az network watcher show-next-hop \
--resource-group rg-routing-lab \
--vm vm-workload \
--source-ip 10.1.1.4 \
--dest-ip 192.168.2.10

Expected: next hop is VirtualAppliance with IP 10.0.2.4 (NVA-B).

Step 5: Test routing to a hub VNet address (should use VNet peering directly)

az network watcher show-next-hop \
--resource-group rg-routing-lab \
--vm vm-workload \
--source-ip 10.1.1.4 \
--dest-ip 10.0.1.4

Expected: next hop type is VNetPeering (traffic to the peered VNet uses the peering link, not the UDR, because 10.0.0.0/16 has no explicit UDR and the system route handles it).

Exam note

The az network watcher show-next-hop command requires the VM to be running. It evaluates routing from the perspective of a specific VM's NIC. The --nic parameter is only required if the VM has multiple NICs with IP forwarding enabled.


Break & fix

These scenarios represent common misconfigurations you will encounter in production and on the exam.

Scenario 1: NVA drops forwarded packets

Symptom: VMs in the spoke subnet cannot reach the internet even though the UDR is correctly configured.

Root cause: IP forwarding is not enabled on the NVA NIC at the Azure platform level.

Diagnosis:

az network nic show \
--resource-group rg-routing-lab \
--name vm-nva-aVMNic \
--query "enableIPForwarding"

If the output is false, packets arriving at the NVA that are destined for other IPs are silently dropped.

Fix:

az network nic update \
--resource-group rg-routing-lab \
--name vm-nva-aVMNic \
--ip-forwarding true
![Challenge 08 - Network Topology](/img/az-700/challenge-08-topology.svg)


**Fix:** Start the NVA, or temporarily remove the forced tunneling route:

```bash
az network route-table route delete \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--name route-forced-tunnel

Scenario 3: Asymmetric routing

Symptom: Traffic flows outbound through the NVA but return traffic bypasses it, causing stateful firewall rules to drop the return packets.

Root cause: A UDR exists on the spoke subnet (outbound direction) but no UDR exists on the hub subnet for return traffic from the NVA back to the spoke.

Diagnosis: Check effective routes on the NVA NIC. If the return path to 10.1.0.0/16 uses only the system route (VNet peering), the NVA may route return traffic correctly. However, if the NVA sends traffic to the spoke and there is an intermediate hop, you need UDRs for the return path as well.

Fix: Add a route table to the NVA subnet with routes for return traffic (if needed), or ensure the NVA is the first and last hop for inspected flows.

Scenario 4: BGP route overrides UDR

Symptom: You configured a UDR for 192.168.1.0/24 pointing to NVA-A, but traffic goes via the VPN Gateway instead because a BGP-learned route exists for the same prefix.

Root cause: BGP route propagation is enabled on the route table (disableBgpRoutePropagation: false).

Diagnosis:

az network route-table show \
--resource-group rg-routing-lab \
--name rt-spoke-workload \
--query "disableBgpRoutePropagation"

If false, BGP routes are being propagated. However, note that UDRs should override BGP routes for the same prefix. The actual issue is typically that the BGP route has a MORE SPECIFIC prefix (e.g., 192.168.1.0/25 from BGP vs. 192.168.1.0/24 from UDR).

Fix: Either disable BGP propagation or add a more specific UDR:

# Option 1: Disable BGP propagation
az network route-table update \
--resource-group rg-routing-lab \
--name rt-spoke-workload \
--disable-bgp-route-propagation true

# Option 2: Add a more specific route matching the BGP prefix
az network route-table route create \
--resource-group rg-routing-lab \
--route-table-name rt-spoke-workload \
--name route-onprem-site-a-specific \
--address-prefix 192.168.1.0/25 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.4

Route selection deep dive

Understanding how Azure selects routes is critical for the AZ-700 exam:

PriorityRoute sourceExample
1 (highest)User-defined route (UDR)Custom route in route table
2BGP routeRoute learned from VPN/ExpressRoute gateway
3 (lowest)System routeAzure default routes (VNet, Internet, etc.)

Within the same priority level, longest prefix match wins. A /25 route is more specific than a /24 route and will be preferred regardless of the source.

Special cases:

  • If a UDR and BGP route have the SAME prefix, the UDR wins
  • If BGP advertises a MORE SPECIFIC prefix than your UDR, the BGP route wins due to longest prefix match
  • Disabling BGP propagation removes BGP routes entirely from consideration

Cleanup

Remove all resources created in this challenge:

az group delete \
--name rg-routing-lab \
--yes \
--no-wait

Knowledge check

1. A UDR for 192.168.0.0/16 points to NVA-A, and a BGP-learned route for 192.168.1.0/24 points to the VPN gateway. Where does traffic to 192.168.1.100 go?

2. You configure forced tunneling (0.0.0.0/0 to a VirtualAppliance) on a spoke subnet, but VMs still cannot reach the internet. The NVA is running and has IP forwarding enabled at the OS level. What is the most likely cause?

3. What does setting --disable-bgp-route-propagation true on a route table accomplish?

4. You need traffic from spoke subnet A to reach on-premises network 192.168.1.0/24 via NVA-A, and 192.168.2.0/24 via NVA-B. BGP propagation is disabled. How many routes must be in the route table (minimum) to achieve this plus forced tunneling?

5. Which az CLI command would you use to determine the next hop for traffic leaving a VM destined for 8.8.8.8?

6. A route table has a UDR for 10.0.0.0/8 with next-hop-type None (blackhole). A VM in the associated subnet tries to reach 10.5.1.1. What happens?


Additional resources