← Back to Portal
AZ-700 Case Studies
Troubleshooting Case Studies
Six real-world Azure networking scenarios — symptoms, systematic investigation steps, root cause, fix, and exam takeaways. Work through each case before your exam to sharpen scenario-based question skills.
Scenario
A hub-spoke network has Azure Firewall (10.0.1.4) in the hub. Spoke-A (10.1.0.0/16) and Spoke-B (10.2.0.0/16) are peered to the hub. Spoke-A VMs can ping Azure Firewall and reach the Internet. Spoke-B VMs can also ping Azure Firewall and reach the Internet. However, Spoke-A VMs cannot reach Spoke-B VMs, and vice versa.
Symptoms
- ICMP from Spoke-A VMs to Spoke-B VMs times out
- Firewall logs show NO traffic from 10.1.x.x → 10.2.x.x (traffic never arrives at Firewall)
- Effective routes on Spoke-A NIC show system route to 10.2.0.0/16 → VNet peering (direct to hub, not via Firewall)
Investigation Steps
1Check effective routes on a Spoke-A VM NIC. Run
az network nic show-effective-route-table. If 10.2.0.0/16 shows as "VNet peering" next hop rather than "VirtualAppliance", the UDR is missing.2Check Spoke-A route table. Verify it has a UDR for 10.2.0.0/16 → VirtualAppliance → 10.0.1.4 (Firewall). If no route table or missing route, that's the cause.
3Check BGP route propagation. If BGP propagation is enabled on the spoke route table, on-premises BGP routes may be injecting conflicting paths. Should be disabled.
4Check Firewall network/application rules. Even if traffic reaches the Firewall, a missing allow rule causes a drop. Check Firewall logs for allowed/denied flows.
Root Cause
Missing UDR on Spoke-A's subnet route table. Without the UDR, the system route for 10.2.0.0/16 routes directly to the peering (hub VNet), but the hub VNet routes it directly back without going through Firewall. The packet takes a path that the Firewall never inspects, and since there's no NVA to forward it from hub to Spoke-B's gateway, it is dropped.
Fix
Add a UDR on Spoke-A's route table: prefix 10.2.0.0/16, next hop type VirtualAppliance, next hop IP 10.0.1.4. Also add a UDR on Spoke-B's route table for 10.1.0.0/16 → 10.0.1.4 (for return traffic). Ensure BGP propagation is disabled on both spoke route tables.
az network route-table route create -g RG --route-table-name Spoke-A-RT \ -n ToSpokeB --address-prefix 10.2.0.0/16 \ --next-hop-type VirtualAppliance --next-hop-ip-address 10.0.1.4 az network route-table route create -g RG --route-table-name Spoke-B-RT \ -n ToSpokeA --address-prefix 10.1.0.0/16 \ --next-hop-type VirtualAppliance --next-hop-ip-address 10.0.1.4
Exam Takeaways
- VNet peering is non-transitive — Spoke-A to Spoke-B always requires explicit routing via an NVA/Firewall in the hub.
- Firewall logs not showing traffic = traffic never reached the Firewall = UDR problem (not a Firewall rule problem).
- Check effective routes first — they reveal the actual next hop being used, not the intended one.
- Both spokes need symmetric UDRs (Spoke-A → Spoke-B AND Spoke-B → Spoke-A). Missing either one breaks bidirectional communication.
Scenario
Azure SQL Database has a Private Endpoint configured. VMs in the hub VNet resolve mysqlserver.database.windows.net to a private IP (10.0.5.4) correctly. VMs in Spoke-A (10.1.0.0/16) resolve the same FQDN to a public IP (52.x.x.x). No other networking changes have been made. The Private DNS Zone (privatelink.database.windows.net) exists and has an A record for the private endpoint.
Symptoms
- Spoke-A VMs:
nslookup mysqlserver.database.windows.netreturns 52.x.x.x (public) - Hub VMs: same command returns 10.0.5.4 (private) — working correctly
- Private DNS Zone exists with A record: mysqlserver → 10.0.5.4
- Connection to SQL from Spoke-A fails with connection timeout
Investigation Steps
1Check Private DNS Zone VNet links. Go to privatelink.database.windows.net → Virtual network links. Hub VNet is linked — Spoke-A VNet is NOT linked.
2Confirm DNS resolution from Spoke-A VM. Run
nslookup mysqlserver.privatelink.database.windows.net directly. If this resolves to public IP, the Private DNS Zone lookup is not happening for Spoke-A.3Check custom DNS server configuration. If Spoke-A VNet uses a custom DNS server (e.g., on-prem), ensure that server also forwards privatelink.database.windows.net queries to Azure DNS (168.63.129.16).
Root Cause
Missing VNet link for Spoke-A on the Private DNS Zone. Without a VNet link, Azure DNS does not consult the Private DNS Zone when resolving queries from Spoke-A VMs. They fall through to the public DNS record and get the public IP.
Fix
Add a VNet link to privatelink.database.windows.net for Spoke-A VNet. Registration-enabled should be false (auto-registration not needed for Private Endpoint zones). This does not require any VM or network changes — DNS resolves correctly immediately after the link is added.
az network private-dns link vnet create \ -g RG \ --zone-name "privatelink.database.windows.net" \ --name "Spoke-A-Link" \ --virtual-network Spoke-A-VNet \ --registration-enabled false
Exam Takeaways
- Every VNet that needs Private Endpoint DNS resolution requires its own VNet link to the Private DNS Zone.
- The Private DNS Zone VNet link is NOT automatically shared through peering — peered VNets need their own links.
- symptom "hub works, spoke doesn't" for DNS almost always = missing VNet link on spoke.
- Registration-enabled=false is correct for most Private Endpoint zones (auto-registration creates A records for VMs, not needed here).
Scenario
A Site-to-Site VPN connection between on-premises (Cisco ASA) and Azure VPN Gateway shows as "Connecting" (not "Connected") in the Azure portal. This worked yesterday but failed after the on-premises team performed a "security hardening" change on the ASA, updating cipher suites. IKE Phase 1 completes successfully (authentication passes), but Phase 2 fails.
Symptoms
- Connection status: "Connecting" in Azure portal
- Azure VPN Gateway diagnostic logs show "IKE Phase 2 failed"
- On-premises ASA logs show "No transform set match" or "IPsec proposal rejected"
- IKE Phase 1 completes (authentication is fine — shared key and certificates are valid)
Investigation Steps
1Confirm IKE Phase 1 vs Phase 2 failure. Phase 1 = authentication (shared key, certificates). Phase 2 = IPsec SA negotiation (encryption, integrity, DH group, lifetime). Logs confirm Phase 2.
2Compare IPsec/IKE policy on Azure Gateway vs ASA. After hardening, the ASA may now require AES-256-GCM or SHA-384 which differs from the Azure default. Azure default: AES-256, SHA256, DH Group 2.
3Check if a custom IPsec policy is needed. Azure VPN Gateway (VpnGw1+) supports custom IPsec/IKE policies. Match exactly: encryption, integrity, DH group, SA lifetime.
Root Cause
IPsec Phase 2 (Quick Mode) parameter mismatch. The on-premises ASA hardening changed the IPsec transform set to a cipher Azure's default policy doesn't offer. Azure and ASA cannot agree on encryption/integrity/DH group for the IPsec SA, so Phase 2 never completes.
Fix
Apply a custom IPsec/IKE policy on the Azure VPN connection that exactly matches the on-premises ASA configuration. Both ends must specify identical parameters for IKE Phase 2: encryption algorithm, integrity (hash) algorithm, PFS group, and SA lifetime.
# Example: custom IPsec policy matching ASA hardened config az network vpn-connection ipsec-policy add \ -g RG --connection-name MyS2SConn \ --ike-encryption AES256 \ --ike-integrity SHA384 \ --dh-group DHGroup14 \ --ipsec-encryption GCMAES256 \ --ipsec-integrity GCMAES256 \ --pfs-group PFS2048 \ --sa-lifetime 27000 \ --sa-data-size 102400000
Exam Takeaways
- Phase 1 failure = authentication problem (wrong shared key, expired cert, mismatched IKE version).
- Phase 2 failure = IPsec parameter mismatch (encryption, hash, DH group, SA lifetime, PFS).
- Azure VPN Gateway Basic SKU does NOT support custom IPsec policies — requires VpnGw1+.
- Both sides must have identical Phase 2 parameters — a single mismatch prevents tunnel establishment.
Scenario
An Azure Standard Load Balancer's TCP health probe (port 443) reports all three backend VMs as "Unhealthy". The VMs are confirmed to be running, the web service is listening on port 443, and VMs in the same VNet can successfully connect to the backends on port 443. The backend subnet NSG has an inbound rule allowing TCP 443 from 10.0.0.0/16.
Symptoms
- Load Balancer shows 0 of 3 backend instances as Healthy
- Client connections via VIP return intermittent "Connection refused" or "No response"
- Direct SSH to VMs confirms web service running and listening on 443
- Connections from other VMs in 10.0.x.x succeed on port 443
Investigation Steps
1Identify health probe source IP. Azure Standard LB probes originate from 168.63.129.16. This IP is NOT in 10.0.0.0/16, so the existing NSG rule does not match it.
2Check NSG effective rules on backend subnet. Use
az network nsg show-effective-rules. Confirm there is NO rule allowing 168.63.129.16 or the AzureLoadBalancer service tag on port 443.3Confirm probe port and protocol match service configuration. Verify the web service actually listens on TCP 443 (not just HTTP on 80). Mismatched probe port = all backends unhealthy.
Root Cause
NSG rule does not match the health probe source IP. Azure Standard Load Balancer health probes originate from 168.63.129.16, which is outside the 10.0.0.0/16 range allowed by the NSG rule. The probe TCP SYN packets are dropped by the NSG before reaching the VM's network stack, causing all backends to appear unhealthy.
Fix
Add an NSG inbound rule allowing the AzureLoadBalancer service tag on TCP 443. The AzureLoadBalancer service tag covers 168.63.129.16 and any future probe IPs, making this the recommended approach over specifying the IP directly.
az network nsg rule create \ -g RG --nsg-name Backend-NSG \ -n AllowLBProbe \ --priority 110 \ --direction Inbound \ --access Allow \ --protocol Tcp \ --source-address-prefixes AzureLoadBalancer \ --destination-port-ranges 443
Exam Takeaways
- LB health probes always originate from 168.63.129.16 — NSG rules based on VNet IP ranges do NOT cover probe traffic.
- Standard LB requires explicit NSG allow rules — it does NOT have implicit open ports like Basic LB.
- Use the AzureLoadBalancer service tag, not the IP, for probe rules (future-proof and Microsoft best practice).
- "VMs healthy, LB shows unhealthy" = NSG blocking probe traffic (not application issue).
Scenario
An organisation has ExpressRoute as primary connectivity and a S2S VPN as backup (coexistence). When ExpressRoute is disconnected during a failover test, on-premises traffic does NOT automatically switch to the VPN tunnel. The VPN tunnel status shows "Connected". BGP is configured on both gateways. On-premises routing shows the ER route with a lower AS path length than the VPN route to Azure prefixes.
Symptoms
- VPN tunnel status: Connected, but no traffic flows over it when ER is down
- On-premises router BGP table: ER prefix for 10.0.0.0/16 with AS path length 1, VPN prefix with AS path length 2
- After ER failure, on-premises router BGP table no longer shows the ER prefix but takes several minutes before using VPN path
- Traffic restores after BGP hold timer expiry (default 90 seconds)
Investigation Steps
1Check BGP route preference on on-premises router. ER routes have shorter AS path, so they are preferred. When ER fails, on-premises must wait for BGP hold timer before withdrawing the route and installing the VPN path.
2Check if VPN is advertising the same prefixes with lower preference. Use AS path prepending on VPN-learned routes on Azure side, or set a lower local preference on on-premises for VPN routes to ensure ER is preferred but VPN is ready immediately.
3Check BFD (Bidirectional Forwarding Detection) is configured. BFD reduces failure detection to under 1 second. Without BFD, BGP relies on hold timer (90 seconds default) to detect ER failure.
Root Cause
BGP hold timer delay and no BFD configured. Without BFD, the on-premises router waits up to 90 seconds after ER failure to withdraw the BGP route. Only then does it install the VPN path from BGP. The VPN is functioning, but BGP path selection has not yet activated it due to the hold timer.
Fix
Enable BFD on the ExpressRoute circuit to reduce failure detection to milliseconds. Also review on-premises route policy to ensure VPN routes are in the BGP table as backup paths (not suppressed) before ER fails. Azure VPN Gateway supports BFD for coexistence scenarios.
Exam Takeaways
- ER + VPN coexistence requires BGP on both gateways. VPN Basic SKU does not support BGP.
- ER routes are always preferred over VPN routes to the same prefix by default (shorter AS path via Microsoft backbone).
- BFD enables sub-second ER failure detection — without it, failover depends on the BGP hold timer (default 90 seconds).
- "VPN Connected but no traffic" in a coexistence scenario = BGP path selection has not yet switched (ER still in BGP table).
Scenario
An Azure Application Gateway v2 (WAF_v2 SKU) is returning 502 Bad Gateway for all requests. The backend VMs are confirmed running and the web application works when accessed directly via VM IP. A new NSG was attached to the App Gateway subnet and the backend subnet yesterday as part of a security hardening exercise.
Symptoms
- All HTTP/HTTPS requests to Application Gateway return "502 Bad Gateway"
- App Gateway Metrics: "Unhealthy host count" = 3 (all backends)
- Backend health diagnostics in portal show: "Received invalid status code in the response" or "Connection refused"
- VMs are healthy and the app responds on port 80 directly
- NSG was added to AppGW subnet and backend subnet in last 24 hours
Investigation Steps
1Check App Gateway subnet NSG. App Gateway v2 requires inbound TCP 65200-65535 from GatewayManager service tag (infrastructure communication). Without this rule, App Gateway infrastructure fails and returns 502.
2Check backend subnet NSG. App Gateway health probes originate from the App Gateway subnet IP range. NSG on backend subnet must allow inbound TCP from the App Gateway subnet prefix (or use AppGatewaySubnet service tag).
3Check App Gateway backend health in portal. Diagnostics → Backend health. Error message distinguishes between "TCP connection refused" (NSG blocking) vs "HTTP 5xx from backend" (application error).
Root Cause
Two NSG misconfigurations in combination:
1. App Gateway subnet NSG blocking TCP 65200-65535 from GatewayManager — required for App Gateway v2 infrastructure health.
2. Backend subnet NSG blocking health probe traffic from App Gateway subnet — probes originate from App Gateway's private IPs, not 168.63.129.16 (unlike Azure Load Balancer).
1. App Gateway subnet NSG blocking TCP 65200-65535 from GatewayManager — required for App Gateway v2 infrastructure health.
2. Backend subnet NSG blocking health probe traffic from App Gateway subnet — probes originate from App Gateway's private IPs, not 168.63.129.16 (unlike Azure Load Balancer).
Fix
Fix 1 — App Gateway subnet NSG: Allow inbound TCP 65200-65535 from GatewayManager service tag.
Fix 2 — Backend subnet NSG: Allow inbound TCP on app port (80/443) from the App Gateway subnet IP range (e.g., 10.0.2.0/24).
Fix 2 — Backend subnet NSG: Allow inbound TCP on app port (80/443) from the App Gateway subnet IP range (e.g., 10.0.2.0/24).
# Fix 1: AppGW subnet — allow infrastructure ports az network nsg rule create -g RG --nsg-name AppGW-Subnet-NSG \ -n AllowGatewayManager \ --priority 100 --direction Inbound --access Allow \ --protocol Tcp --source-address-prefixes GatewayManager \ --destination-port-ranges "65200-65535" # Fix 2: Backend subnet — allow health probes from AppGW subnet az network nsg rule create -g RG --nsg-name Backend-NSG \ -n AllowFromAppGW \ --priority 110 --direction Inbound --access Allow \ --protocol Tcp --source-address-prefixes "10.0.2.0/24" \ --destination-port-ranges 80 443
Exam Takeaways
- App Gateway v2 ALWAYS requires inbound TCP 65200-65535 from GatewayManager on its subnet NSG — this is a hard requirement, not optional.
- App Gateway health probes originate from its own subnet IPs — unlike Azure Load Balancer (168.63.129.16), they use the AppGW private IPs.
- 502 = App Gateway cannot reach backends (probe failure or connection refused). 504 = App Gateway reached the backend but got no response in time.
- "Everything worked until we added an NSG" is a classic exam scenario — always check 65200-65535 GatewayManager first for App Gateway issues.