Skip to content

Lab 04: Azure Firewall

Deploy Azure Firewall with a simple spoke subnet, force egress through the firewall using a route table, and validate both allowed and denied traffic so teams can learn how routing and firewall policy interact in practice.

Lab Metadata

Field Value
Difficulty Advanced
Estimated Duration 75-105 minutes
Focus Azure Firewall deployment, UDR-based egress control, diagnostics, deny troubleshooting
Tooling Azure CLI, Network Watcher, Log Analytics optional

Prerequisites

  • Permission to create Azure Firewall, public IPs, route tables, and a test VM.
  • A workspace ID if you want to stream logs to Log Analytics during the lab.
  • A resource group such as $RG=rg-net-lab04 and location such as $LOCATION=koreacentral.
  • Budget awareness: Azure Firewall incurs hourly and data-processing charges. Tear down promptly after the lab.

Architecture Diagram

mermaid flowchart TD Workload[Spoke VM] --> UDR[Route Table 0.0.0.0/0] UDR --> Firewall[Azure Firewall] Firewall --> Internet[Internet] Firewall --> Logs[Firewall logs] Ops[Operator] --> Firewall

Step-by-Step Instructions

Step 1: Create the VNet, subnets, and public IP

az group create \
    --name $RG \
    --location $LOCATION

az network vnet create \
    --resource-group $RG \
    --name vnet-fw-lab04 \
    --location $LOCATION \
    --address-prefixes 10.140.0.0/16 \
    --subnet-name AzureFirewallSubnet \
    --subnet-prefixes 10.140.1.0/24

az network vnet subnet create \
    --resource-group $RG \
    --vnet-name vnet-fw-lab04 \
    --name workload \
    --address-prefixes 10.140.2.0/24

az network public-ip create \
    --resource-group $RG \
    --name pip-fw04 \
    --sku Standard \
    --allocation-method Static
Command Purpose
az group create Create the resource group that holds all lab resources.
--name Name of the resource group.
--location Azure region for the resource group.
az network vnet create Create the virtual network with the dedicated AzureFirewallSubnet.
--resource-group Resource group that contains the virtual network.
--name Name of the virtual network.
--location Azure region for the virtual network.
--address-prefixes Address space for the virtual network.
--subnet-name Name of the first subnet (must be AzureFirewallSubnet for the firewall).
--subnet-prefixes Address range for the firewall subnet.
az network vnet subnet create Add the workload subnet to the virtual network.
--resource-group Resource group that contains the virtual network.
--vnet-name Virtual network the subnet is added to.
--name Name of the workload subnet.
--address-prefixes Address range for the workload subnet.
az network public-ip create Create the static public IP used by the firewall.
--resource-group Resource group that contains the public IP.
--name Name of the public IP resource.
--sku Public IP SKU (Standard is required by Azure Firewall).
--allocation-method IP allocation method (Static for Azure Firewall).

This layout mirrors the minimum production pattern of firewall plus workload subnet.

Why this step matters

  • Confirm that AzureFirewallSubnet exists with the expected prefix and that the workload subnet is separate.
  • Record the firewall public IP resource now because later diagnostics and provisioning checks depend on it.
  • Saving the initial VNet state gives you a clean baseline before forced tunneling is introduced.

Step 2: Create the firewall and firewall policy

az network firewall policy create \
    --resource-group $RG \
    --name fwp-lab04 \
    --location $LOCATION

az network firewall create \
    --resource-group $RG \
    --name fw-lab04 \
    --location $LOCATION \
    --firewall-policy fwp-lab04

az network firewall ip-config create \
    --resource-group $RG \
    --firewall-name fw-lab04 \
    --name fwconfig \
    --public-ip-address pip-fw04 \
    --vnet-name vnet-fw-lab04
Command Purpose
az network firewall policy create Create the firewall policy that holds rule collections.
--resource-group Resource group that contains the firewall policy.
--name Name of the firewall policy.
--location Azure region for the firewall policy.
az network firewall create Create the Azure Firewall instance and attach the policy.
--resource-group Resource group that contains the firewall.
--name Name of the firewall.
--location Azure region for the firewall.
--firewall-policy Firewall policy to associate with the firewall.
az network firewall ip-config create Create the firewall IP configuration binding the public IP and VNet.
--resource-group Resource group that contains the firewall.
--firewall-name Firewall the IP configuration belongs to.
--name Name of the IP configuration.
--public-ip-address Public IP used by the firewall frontend.
--vnet-name Virtual network that contains the AzureFirewallSubnet.

Wait for provisioning to finish before moving on. Firewall deployment can take several minutes.

Why this step matters

  • Wait for firewall provisioning to finish and record the policy and IP configuration objects that were created.
  • Capture deployment timestamps because Azure Firewall provisioning time can otherwise be mistaken for a policy failure.
  • If the firewall IP configuration is incomplete here, do not move on to UDR work yet.

Step 3: Deploy a test VM and forced-tunnel route table

az vm create \
    --resource-group $RG \
    --name vm-egress04 \
    --image Ubuntu2204 \
    --size Standard_B1s \
    --vnet-name vnet-fw-lab04 \
    --subnet workload \
    --admin-username azureuser \
    --generate-ssh-keys \
    --public-ip-address ""

FW_PRIVATE_IP=$(az network firewall ip-config list --resource-group $RG --firewall-name fw-lab04 --query "[0].privateIpAddress" --output tsv)
az network route-table create \
    --resource-group $RG \
    --name rt-workload04 \
    --location $LOCATION

az network route-table route create \
    --resource-group $RG \
    --route-table-name rt-workload04 \
    --name default-to-firewall \
    --address-prefix 0.0.0.0/0 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $FW_PRIVATE_IP

az network vnet subnet update \
    --resource-group $RG \
    --vnet-name vnet-fw-lab04 \
    --name workload \
    --route-table rt-workload04
Command Purpose
az vm create Create the workload test virtual machine.
--resource-group Resource group that contains the virtual machine.
--name Name of the virtual machine.
--image Operating system image for the virtual machine.
--size Virtual machine SKU size.
--vnet-name Virtual network the virtual machine joins.
--subnet Subnet the virtual machine joins (the workload subnet).
--admin-username Administrator user name for the virtual machine.
--generate-ssh-keys Generate SSH key pair for authentication if not present.
--public-ip-address Public IP for the virtual machine; empty string disables a public IP.
az network firewall ip-config list List firewall IP configurations to read the firewall private IP.
--resource-group Resource group that contains the firewall.
--firewall-name Firewall to query.
--query JMESPath expression selecting the private IP address.
--output Output format (tsv for scripting).
az network route-table create Create the route table used for forced tunneling.
--resource-group Resource group that contains the route table.
--name Name of the route table.
--location Azure region for the route table.
az network route-table route create Add a default route that sends all traffic to the firewall.
--resource-group Resource group that contains the route table.
--route-table-name Route table the route is added to.
--name Name of the route.
--address-prefix Destination prefix for the route (0.0.0.0/0 for all traffic).
--next-hop-type Next hop type (VirtualAppliance for the firewall).
--next-hop-ip-address Firewall private IP the traffic is forwarded to.
az network vnet subnet update Associate the route table with the workload subnet.
--resource-group Resource group that contains the virtual network.
--vnet-name Virtual network that contains the subnet.
--name Name of the workload subnet.
--route-table Route table to associate with the subnet.

This is the critical forced-tunneling pattern to validate in later steps.

Why this step matters

  • Save the firewall private IP and the route-table association result because both are required to prove forced tunneling.
  • Re-check the workload subnet attachment before running any firewall-policy tests.
  • If the route-table association is wrong here, every later allow or deny result is untrustworthy.

Step 4: Create allow and deny rule collections

az network firewall policy rule-collection-group create \
    --resource-group $RG \
    --policy-name fwp-lab04 \
    --name rcg-egress \
    --priority 100

az network firewall policy rule-collection-group collection add-filter-collection \
    --resource-group $RG \
    --policy-name fwp-lab04 \
    --rule-collection-group-name rcg-egress \
    --name allow-web \
    --priority 100 \
    --action Allow

az network firewall policy rule-collection-group collection rule add \
    --resource-group $RG \
    --policy-name fwp-lab04 \
    --rule-collection-group-name rcg-egress \
    --collection-name allow-web \
    --name allow-https \
    --rule-type NetworkRule \
    --ip-protocols TCP \
    --source-addresses 10.140.2.0/24 \
    --destination-addresses 20.42.0.0/16 \
    --destination-ports 443
Command Purpose
az network firewall policy rule-collection-group create Create a rule collection group inside the firewall policy.
--resource-group Resource group that contains the firewall policy.
--policy-name Firewall policy the rule collection group belongs to.
--name Name of the rule collection group.
--priority Priority of the rule collection group.
az network firewall policy rule-collection-group collection add-filter-collection Add a filter collection to the rule collection group.
--resource-group Resource group that contains the firewall policy.
--policy-name Firewall policy the collection belongs to.
--rule-collection-group-name Rule collection group the collection is added to.
--name Name of the filter collection.
--priority Priority of the filter collection.
--action Action for the collection (Allow or Deny).
az network firewall policy rule-collection-group collection rule add Add an individual rule to the filter collection.
--resource-group Resource group that contains the firewall policy.
--policy-name Firewall policy the rule belongs to.
--rule-collection-group-name Rule collection group that contains the collection.
--collection-name Filter collection the rule is added to.
--name Name of the rule.
--rule-type Type of rule (NetworkRule for IP/port filtering).
--ip-protocols Protocols the rule matches.
--source-addresses Source address prefixes the rule matches.
--destination-addresses Destination address prefixes the rule matches.
--destination-ports Destination ports the rule matches.

Adjust the destination to a test target you control, or use an application-rule variant for FQDN-based allowlists.

Why this step matters

  • Record which rule collection group, collection, and rule names you created so log entries are easy to interpret later.
  • Confirm that the destination and source ranges match your test plan before assuming the firewall should allow traffic.
  • These objects are the policy baseline for the allow and deny evidence you capture in the final steps.

Step 5: Enable diagnostics and inspect evidence

az monitor diagnostic-settings create \
    --name send-fw-logs \
    --resource $(az network firewall show --resource-group $RG --name fw-lab04 --query id --output tsv) \
    --workspace $WORKSPACE_ID \
    --logs '[{"category":"AzureFirewallNetworkRule","enabled":true},{"category":"AzureFirewallApplicationRule","enabled":true}]'

az network nic show-effective-route-table \
    --resource-group $RG \
    --name $(az vm show --resource-group $RG --name vm-egress04 --query "networkProfile.networkInterfaces[0].id" --output tsv | awk -F/ '{print $NF}')
Command Purpose
az monitor diagnostic-settings create Send firewall network and application rule logs to Log Analytics.
--name Name of the diagnostic setting.
--resource Resource ID of the firewall to collect logs from.
--workspace Log Analytics workspace that receives the logs.
--logs JSON array of log categories to enable.
az network nic show-effective-route-table Show the effective routes on the workload NIC to prove forced tunneling.
--resource-group Resource group that contains the network interface.
--name Name of the network interface to inspect.

The route check proves the workload really sends internet traffic to the firewall, not directly to the internet.

Why this step matters

  • Verify that diagnostics are enabled and that the workload NIC now shows a VirtualAppliance route for internet-bound traffic.
  • Save the effective-route output because it proves whether traffic is actually traversing the firewall.
  • Without this evidence, a later connectivity failure could be misread as a firewall-rule issue instead of a routing issue.

Step 6: Test an allow and a deny case

az network watcher test-connectivity \
    --resource-group $RG \
    --source-resource $(az vm show --resource-group $RG --name vm-egress04 --query id --output tsv) \
    --dest-address 20.42.10.10 \
    --dest-port 443

az monitor log-analytics query \
    --workspace $WORKSPACE_ID \
    --analytics-query 'AzureDiagnostics | where TimeGenerated > ago(30m) | where Category has "AzureFirewall" | project TimeGenerated, action_s, msg_s | order by TimeGenerated desc' \
    --timespan PT30M
Command Purpose
az network watcher test-connectivity Test reachability from the workload VM to a destination through the firewall.
--resource-group Resource group that contains the source resource.
--source-resource Resource ID of the source virtual machine.
--dest-address Destination address to test connectivity to.
--dest-port Destination port to test connectivity to.
az monitor log-analytics query Query firewall diagnostic logs for allow and deny decisions.
--workspace Log Analytics workspace to query.
--analytics-query KQL query selecting recent firewall actions.
--timespan Time range for the query.

The goal is to see both routing evidence and firewall decision evidence in one workflow.

Why this step matters

  • Capture the connectivity test result and the corresponding firewall log query in the same time window.
  • Compare the routing evidence from the previous step with the allow or deny decision here so you can pinpoint the failure layer.
  • A good lab outcome is not just "traffic worked" or "traffic failed" but a clear explanation of why the firewall made that decision.

Validation Steps

  • [ ] The workload subnet uses a route table with 0.0.0.0/0 pointing to the firewall private IP.
  • [ ] Effective routes on the workload NIC show VirtualAppliance for internet-bound traffic.
  • [ ] Firewall diagnostics record allow or deny actions during your tests.
  • [ ] You can explain whether a failure was caused by routing, rule logic, or the destination service.

Cleanup Instructions

az group delete --name $RG --yes --no-wait
Command Purpose
az group delete Delete the resource group and all lab resources.
--name Name of the resource group to delete.
--yes Skip the interactive confirmation prompt.
--no-wait Return immediately without waiting for deletion to finish.

Before cleanup, record any private IPs, route table names, or diagnostic screenshots you want to reuse in troubleshooting notes.

See Also

Sources