Microsoft Azureintermediate

Azure WAF Setup Guide: Application Gateway and Front Door WAF Configuration

Learn how to configure Azure Web Application Firewall on Application Gateway and Front Door to protect web applications from OWASP Top 10 threats, bot attacks, and custom security rules.

17 min readUpdated 2026-01-13

Azure Web Application Firewall (WAF) protects web applications from common exploits and vulnerabilities including SQL injection, cross-site scripting, and other OWASP Top 10 threats. This guide covers deploying WAF on both Application Gateway and Azure Front Door with managed rules, custom rules, and bot protection.

This article is part of our comprehensive cloud security tips guide, focusing specifically on Azure web application protection.

Overview

Azure WAF can be deployed on three services:

  • Application Gateway: Regional layer 7 load balancer with WAF
  • Azure Front Door: Global CDN and load balancer with edge WAF
  • Azure CDN: Content delivery network with WAF capabilities

This guide focuses on Application Gateway and Front Door, the most common deployment options.

Prerequisites

Before deploying Azure WAF:

  • Azure subscription with Contributor access
  • Virtual Network with dedicated subnet for Application Gateway
  • Backend application to protect (App Service, VMs, AKS, etc.)
  • Azure CLI (2.50.0+) or Azure Portal access
  • Public DNS for custom domain configuration (optional)
  • Understanding of HTTP/HTTPS traffic patterns for your application

Part 1: WAF on Application Gateway

Create Application Gateway with WAF

Step 1: Prepare Networking

# Create resource group
az group create \
  --name rg-waf \
  --location eastus

# Create VNet
az network vnet create \
  --name vnet-waf \
  --resource-group rg-waf \
  --location eastus \
  --address-prefix 10.0.0.0/16

# Create subnet for Application Gateway (minimum /24 recommended)
az network vnet subnet create \
  --name snet-appgw \
  --resource-group rg-waf \
  --vnet-name vnet-waf \
  --address-prefix 10.0.1.0/24

# Create public IP
az network public-ip create \
  --name pip-appgw-waf \
  --resource-group rg-waf \
  --location eastus \
  --allocation-method Static \
  --sku Standard \
  --zone 1 2 3

Step 2: Create WAF Policy

# Create WAF policy with OWASP 3.2 rules
az network application-gateway waf-policy create \
  --name waf-policy-appgw \
  --resource-group rg-waf \
  --location eastus

# Configure managed rules
az network application-gateway waf-policy managed-rule rule-set add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --type OWASP \
  --version 3.2

# Add Microsoft Bot Manager rule set
az network application-gateway waf-policy managed-rule rule-set add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --type Microsoft_BotManagerRuleSet \
  --version 1.0

# Set policy to detection mode initially
az network application-gateway waf-policy policy-setting update \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --mode Detection \
  --state Enabled \
  --request-body-check true \
  --max-request-body-size-in-kb 128 \
  --file-upload-limit-in-mb 100

Step 3: Create Application Gateway with WAF v2

# Create Application Gateway WAF v2
az network application-gateway create \
  --name appgw-waf \
  --resource-group rg-waf \
  --location eastus \
  --sku WAF_v2 \
  --capacity 2 \
  --vnet-name vnet-waf \
  --subnet snet-appgw \
  --public-ip-address pip-appgw-waf \
  --http-settings-cookie-based-affinity Disabled \
  --http-settings-port 80 \
  --http-settings-protocol Http \
  --frontend-port 80 \
  --routing-rule-type Basic \
  --servers 10.0.2.4 10.0.2.5 \
  --waf-policy waf-policy-appgw \
  --zones 1 2 3

# Add HTTPS listener (requires certificate)
# First, create Key Vault and upload certificate
az keyvault create \
  --name kv-appgw-certs \
  --resource-group rg-waf \
  --location eastus \
  --enable-soft-delete true \
  --enable-purge-protection true

# Enable managed identity for App Gateway
az network application-gateway identity assign \
  --gateway-name appgw-waf \
  --resource-group rg-waf \
  --identity $(az identity create \
    --name mi-appgw \
    --resource-group rg-waf \
    --query id -o tsv)

# Grant Key Vault access to App Gateway identity
APPGW_IDENTITY=$(az network application-gateway show \
  --name appgw-waf \
  --resource-group rg-waf \
  --query "identity.userAssignedIdentities.*.principalId" -o tsv)

az keyvault set-policy \
  --name kv-appgw-certs \
  --object-id $APPGW_IDENTITY \
  --secret-permissions get

# Add SSL certificate from Key Vault
az network application-gateway ssl-cert create \
  --gateway-name appgw-waf \
  --resource-group rg-waf \
  --name ssl-cert-main \
  --key-vault-secret-id $(az keyvault secret show \
    --vault-name kv-appgw-certs \
    --name my-ssl-cert \
    --query id -o tsv)

# Add HTTPS frontend port
az network application-gateway frontend-port create \
  --gateway-name appgw-waf \
  --resource-group rg-waf \
  --name https-port \
  --port 443

# Add HTTPS listener
az network application-gateway http-listener create \
  --gateway-name appgw-waf \
  --resource-group rg-waf \
  --name https-listener \
  --frontend-port https-port \
  --frontend-ip appGatewayFrontendIP \
  --ssl-cert ssl-cert-main

Configure Custom WAF Rules

# Create custom rule to block specific countries
az network application-gateway waf-policy custom-rule create \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --name BlockHighRiskCountries \
  --priority 10 \
  --rule-type MatchRule \
  --action Block

az network application-gateway waf-policy custom-rule match-condition add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --name BlockHighRiskCountries \
  --match-variables RemoteAddr \
  --operator GeoMatch \
  --values CN RU KP IR

# Create rate limiting rule
az network application-gateway waf-policy custom-rule create \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --name RateLimitRule \
  --priority 20 \
  --rule-type RateLimitRule \
  --action Block \
  --rate-limit-threshold 100 \
  --rate-limit-duration OneMin \
  --group-by-user-session "[{\"groupByVariables\":[{\"variableName\":\"ClientAddr\"}]}]"

# Block requests with suspicious headers
az network application-gateway waf-policy custom-rule create \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --name BlockSuspiciousHeaders \
  --priority 30 \
  --rule-type MatchRule \
  --action Block

az network application-gateway waf-policy custom-rule match-condition add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --name BlockSuspiciousHeaders \
  --match-variables "RequestHeaders['User-Agent']" \
  --operator Contains \
  --values "sqlmap" "nikto" "nmap" "masscan" \
  --transforms Lowercase

Configure Exclusions

Handle false positives by excluding specific request attributes:

# Exclude specific request header from all rules
az network application-gateway waf-policy managed-rule exclusion add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --match-variable RequestHeaderNames \
  --selector-match-operator Equals \
  --selector "X-Custom-Token"

# Exclude request body field from specific rule
az network application-gateway waf-policy managed-rule exclusion add \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --match-variable RequestBodyPostArgNames \
  --selector-match-operator Contains \
  --selector "message" \
  --exclusion-rule-set-type OWASP \
  --exclusion-rule-set-version 3.2 \
  --exclusion-rule-group REQUEST-942-APPLICATION-ATTACK-SQLI \
  --exclusion-rule-ids 942130 942430

Enable Prevention Mode

After tuning in Detection mode:

# Switch to Prevention mode
az network application-gateway waf-policy policy-setting update \
  --policy-name waf-policy-appgw \
  --resource-group rg-waf \
  --mode Prevention

Part 2: WAF on Azure Front Door

Create Front Door with WAF

Step 1: Create WAF Policy for Front Door

# Create Front Door WAF policy
az network front-door waf-policy create \
  --name waf-policy-fd \
  --resource-group rg-waf \
  --mode Detection \
  --redirect-url "https://www.yoursite.com/blocked" \
  --custom-block-response-status-code 403 \
  --custom-block-response-body "VGhpcyByZXF1ZXN0IGhhcyBiZWVuIGJsb2NrZWQgYnkgV0FG"

# Add managed rules
az network front-door waf-policy managed-rule-definition list
# Lists available rule sets

az network front-door waf-policy managed-rules add \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --type DefaultRuleSet \
  --version "2.1"

az network front-door waf-policy managed-rules add \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --type Microsoft_BotManagerRuleSet \
  --version "1.0"

Step 2: Create Front Door Profile

# Create Front Door Standard/Premium
az afd profile create \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --sku Premium_AzureFrontDoor

# Create endpoint
az afd endpoint create \
  --endpoint-name fd-endpoint \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --enabled-state Enabled

# Create origin group
az afd origin-group create \
  --origin-group-name og-webapp \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --probe-request-type GET \
  --probe-protocol Https \
  --probe-path "/health" \
  --probe-interval-in-seconds 30 \
  --sample-size 4 \
  --successful-samples-required 3 \
  --additional-latency-in-milliseconds 50

# Add origin
az afd origin create \
  --origin-name origin-webapp \
  --origin-group-name og-webapp \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --host-name mywebapp.azurewebsites.net \
  --origin-host-header mywebapp.azurewebsites.net \
  --http-port 80 \
  --https-port 443 \
  --priority 1 \
  --weight 1000 \
  --enabled-state Enabled

# Create route
az afd route create \
  --route-name route-default \
  --endpoint-name fd-endpoint \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --origin-group og-webapp \
  --supported-protocols Https Http \
  --patterns-to-match "/*" \
  --forwarding-protocol HttpsOnly \
  --https-redirect Enabled

Step 3: Create Security Policy

# Get WAF policy ID
WAF_POLICY_ID=$(az network front-door waf-policy show \
  --name waf-policy-fd \
  --resource-group rg-waf \
  --query id -o tsv)

# Create security policy (links WAF to Front Door)
az afd security-policy create \
  --security-policy-name sec-policy-waf \
  --profile-name fd-waf \
  --resource-group rg-waf \
  --waf-policy $WAF_POLICY_ID \
  --domains "/subscriptions/{sub-id}/resourcegroups/rg-waf/providers/Microsoft.Cdn/profiles/fd-waf/afdEndpoints/fd-endpoint"

Configure Front Door Custom Rules

# Create custom rule for geo-blocking
az network front-door waf-policy rule create \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --name GeoBlockRule \
  --priority 100 \
  --action Block \
  --rule-type MatchRule \
  --match-conditions '[{
    "matchVariable": "RemoteAddr",
    "operator": "GeoMatch",
    "matchValue": ["CN", "RU", "KP"]
  }]'

# Create rate limiting rule
az network front-door waf-policy rule create \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --name RateLimitByIP \
  --priority 200 \
  --action Block \
  --rule-type RateLimitRule \
  --rate-limit-duration-in-minutes 1 \
  --rate-limit-threshold 100 \
  --match-conditions '[{
    "matchVariable": "RequestUri",
    "operator": "RegEx",
    "matchValue": ["/api/.*"]
  }]'

# Allow trusted IPs (whitelist)
az network front-door waf-policy rule create \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --name AllowTrustedIPs \
  --priority 50 \
  --action Allow \
  --rule-type MatchRule \
  --match-conditions '[{
    "matchVariable": "RemoteAddr",
    "operator": "IPMatch",
    "matchValue": ["203.0.113.0/24", "198.51.100.0/24"]
  }]'

# Block specific user agents
az network front-door waf-policy rule create \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --name BlockBadBots \
  --priority 150 \
  --action Block \
  --rule-type MatchRule \
  --match-conditions '[{
    "matchVariable": "RequestHeader",
    "selector": "User-Agent",
    "operator": "Contains",
    "transforms": ["Lowercase"],
    "matchValue": ["sqlmap", "nikto", "masscan", "nmap"]
  }]'

Configure Bot Protection

# Enable bot manager with specific actions
az network front-door waf-policy managed-rules add \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --type Microsoft_BotManagerRuleSet \
  --version "1.0"

# Override specific bot rule actions
az network front-door waf-policy managed-rules override add \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --type Microsoft_BotManagerRuleSet \
  --rule-group-id GoodBots \
  --action Log

az network front-door waf-policy managed-rules override add \
  --policy-name waf-policy-fd \
  --resource-group rg-waf \
  --type Microsoft_BotManagerRuleSet \
  --rule-group-id BadBots \
  --action Block

Part 3: Monitoring and Logging

Enable Diagnostic Logs

# For Application Gateway WAF
az monitor diagnostic-settings create \
  --name appgw-waf-logs \
  --resource $(az network application-gateway show \
    --name appgw-waf \
    --resource-group rg-waf \
    --query id -o tsv) \
  --logs '[
    {"category": "ApplicationGatewayAccessLog", "enabled": true},
    {"category": "ApplicationGatewayPerformanceLog", "enabled": true},
    {"category": "ApplicationGatewayFirewallLog", "enabled": true}
  ]' \
  --workspace $(az monitor log-analytics workspace show \
    --name law-security \
    --resource-group rg-waf \
    --query id -o tsv)

# For Front Door WAF
az monitor diagnostic-settings create \
  --name fd-waf-logs \
  --resource $(az afd profile show \
    --profile-name fd-waf \
    --resource-group rg-waf \
    --query id -o tsv) \
  --logs '[
    {"category": "FrontDoorAccessLog", "enabled": true},
    {"category": "FrontDoorHealthProbeLog", "enabled": true},
    {"category": "FrontDoorWebApplicationFirewallLog", "enabled": true}
  ]' \
  --workspace $(az monitor log-analytics workspace show \
    --name law-security \
    --resource-group rg-waf \
    --query id -o tsv)

Log Analytics Queries

// WAF blocked requests by rule
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK"
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize count() by ruleId_s, ruleGroup_s
| order by count_ desc

// Top blocked IPs
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize BlockCount = count() by clientIp_s
| order by BlockCount desc
| take 20

// WAF attack patterns over time
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize count() by bin(TimeGenerated, 1h), ruleGroup_s
| render timechart

// Potential SQL injection attempts
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleGroup_s == "REQUEST-942-APPLICATION-ATTACK-SQLI"
| project TimeGenerated, clientIp_s, requestUri_s, Message
| take 100

// Bot traffic analysis
AzureDiagnostics
| where Category == "FrontDoorWebApplicationFirewallLog"
| where ruleName_s contains "Bot"
| summarize count() by ruleName_s, action_s
| order by count_ desc

Create Alerts

# Alert on high block rate
az monitor scheduled-query create \
  --name "WAF High Block Rate" \
  --resource-group rg-waf \
  --scopes $(az network application-gateway show \
    --name appgw-waf \
    --resource-group rg-waf \
    --query id -o tsv) \
  --condition "count > 100" \
  --condition-query "AzureDiagnostics
    | where Category == 'ApplicationGatewayFirewallLog'
    | where action_s == 'Blocked'
    | where TimeGenerated > ago(5m)" \
  --description "High WAF block rate detected" \
  --evaluation-frequency "5m" \
  --window-size "5m" \
  --severity 2 \
  --action-groups "/subscriptions/{sub-id}/resourceGroups/rg-waf/providers/microsoft.insights/actionGroups/SecurityAlerts"

# Alert on potential attack from single IP
az monitor scheduled-query create \
  --name "WAF Single IP Attack" \
  --resource-group rg-waf \
  --scopes $(az network application-gateway show \
    --name appgw-waf \
    --resource-group rg-waf \
    --query id -o tsv) \
  --condition "count > 50" \
  --condition-query "AzureDiagnostics
    | where Category == 'ApplicationGatewayFirewallLog'
    | where action_s == 'Blocked'
    | where TimeGenerated > ago(5m)
    | summarize count() by clientIp_s
    | where count_ > 50" \
  --description "Potential attack from single IP" \
  --evaluation-frequency "5m" \
  --window-size "5m" \
  --severity 1

Part 4: Terraform Configuration

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.85"
    }
  }
}

provider "azurerm" {
  features {}
}

# Variables
variable "location" {
  default = "eastus"
}

# Resource Group
resource "azurerm_resource_group" "waf" {
  name     = "rg-waf"
  location = var.location
}

# WAF Policy for Application Gateway
resource "azurerm_web_application_firewall_policy" "appgw" {
  name                = "waf-policy-appgw"
  resource_group_name = azurerm_resource_group.waf.name
  location            = var.location

  policy_settings {
    enabled                     = true
    mode                        = "Detection"  # Change to "Prevention" after tuning
    request_body_check          = true
    file_upload_limit_in_mb     = 100
    max_request_body_size_in_kb = 128
  }

  managed_rules {
    managed_rule_set {
      type    = "OWASP"
      version = "3.2"
    }

    managed_rule_set {
      type    = "Microsoft_BotManagerRuleSet"
      version = "1.0"
    }

    exclusion {
      match_variable          = "RequestHeaderNames"
      selector               = "X-Auth-Token"
      selector_match_operator = "Equals"
    }
  }

  custom_rules {
    name      = "BlockHighRiskCountries"
    priority  = 10
    rule_type = "MatchRule"
    action    = "Block"

    match_conditions {
      match_variables {
        variable_name = "RemoteAddr"
      }
      operator           = "GeoMatch"
      negation_condition = false
      match_values       = ["CN", "RU", "KP", "IR"]
    }
  }

  custom_rules {
    name      = "RateLimitRule"
    priority  = 20
    rule_type = "RateLimitRule"
    action    = "Block"

    rate_limit_duration_in_minutes = 1
    rate_limit_threshold           = 100

    match_conditions {
      match_variables {
        variable_name = "RemoteAddr"
      }
      operator           = "IPMatch"
      negation_condition = true
      match_values       = ["127.0.0.1"]  # Exclude localhost
    }
  }

  custom_rules {
    name      = "AllowTrustedIPs"
    priority  = 5
    rule_type = "MatchRule"
    action    = "Allow"

    match_conditions {
      match_variables {
        variable_name = "RemoteAddr"
      }
      operator           = "IPMatch"
      negation_condition = false
      match_values       = ["203.0.113.0/24", "198.51.100.0/24"]
    }
  }
}

# Virtual Network
resource "azurerm_virtual_network" "waf" {
  name                = "vnet-waf"
  resource_group_name = azurerm_resource_group.waf.name
  location            = var.location
  address_space       = ["10.0.0.0/16"]
}

resource "azurerm_subnet" "appgw" {
  name                 = "snet-appgw"
  resource_group_name  = azurerm_resource_group.waf.name
  virtual_network_name = azurerm_virtual_network.waf.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Public IP
resource "azurerm_public_ip" "appgw" {
  name                = "pip-appgw-waf"
  resource_group_name = azurerm_resource_group.waf.name
  location            = var.location
  allocation_method   = "Static"
  sku                 = "Standard"
  zones               = ["1", "2", "3"]
}

# Application Gateway with WAF
resource "azurerm_application_gateway" "waf" {
  name                = "appgw-waf"
  resource_group_name = azurerm_resource_group.waf.name
  location            = var.location
  zones               = ["1", "2", "3"]

  sku {
    name = "WAF_v2"
    tier = "WAF_v2"
  }

  autoscale_configuration {
    min_capacity = 2
    max_capacity = 10
  }

  gateway_ip_configuration {
    name      = "gateway-ip-config"
    subnet_id = azurerm_subnet.appgw.id
  }

  frontend_ip_configuration {
    name                 = "frontend-ip-config"
    public_ip_address_id = azurerm_public_ip.appgw.id
  }

  frontend_port {
    name = "http-port"
    port = 80
  }

  frontend_port {
    name = "https-port"
    port = 443
  }

  backend_address_pool {
    name = "backend-pool"
  }

  backend_http_settings {
    name                  = "backend-http-settings"
    cookie_based_affinity = "Disabled"
    port                  = 80
    protocol              = "Http"
    request_timeout       = 30
  }

  http_listener {
    name                           = "http-listener"
    frontend_ip_configuration_name = "frontend-ip-config"
    frontend_port_name             = "http-port"
    protocol                       = "Http"
  }

  request_routing_rule {
    name                       = "routing-rule"
    priority                   = 100
    rule_type                  = "Basic"
    http_listener_name         = "http-listener"
    backend_address_pool_name  = "backend-pool"
    backend_http_settings_name = "backend-http-settings"
  }

  firewall_policy_id = azurerm_web_application_firewall_policy.appgw.id

  depends_on = [azurerm_public_ip.appgw]
}

# Front Door WAF Policy
resource "azurerm_cdn_frontdoor_firewall_policy" "fd" {
  name                = "wafpolicyfd"
  resource_group_name = azurerm_resource_group.waf.name
  sku_name            = "Premium_AzureFrontDoor"
  enabled             = true
  mode                = "Detection"

  managed_rule {
    type    = "DefaultRuleSet"
    version = "2.1"
    action  = "Block"
  }

  managed_rule {
    type    = "Microsoft_BotManagerRuleSet"
    version = "1.0"
    action  = "Block"
  }

  custom_rule {
    name     = "RateLimitByIP"
    enabled  = true
    priority = 100
    type     = "RateLimitRule"
    action   = "Block"

    rate_limit_duration_in_minutes = 1
    rate_limit_threshold           = 100

    match_condition {
      match_variable = "RequestUri"
      operator       = "RegEx"
      match_values   = ["/api/.*"]
    }
  }
}

# Front Door Profile
resource "azurerm_cdn_frontdoor_profile" "main" {
  name                = "fd-waf"
  resource_group_name = azurerm_resource_group.waf.name
  sku_name            = "Premium_AzureFrontDoor"
}

# Front Door Endpoint
resource "azurerm_cdn_frontdoor_endpoint" "main" {
  name                     = "fd-endpoint"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
}

# Security Policy (links WAF to Front Door)
resource "azurerm_cdn_frontdoor_security_policy" "waf" {
  name                     = "security-policy-waf"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id

  security_policies {
    firewall {
      cdn_frontdoor_firewall_policy_id = azurerm_cdn_frontdoor_firewall_policy.fd.id

      association {
        domain {
          cdn_frontdoor_domain_id = azurerm_cdn_frontdoor_endpoint.main.id
        }
        patterns_to_match = ["/*"]
      }
    }
  }
}

# Outputs
output "appgw_public_ip" {
  value = azurerm_public_ip.appgw.ip_address
}

output "frontdoor_endpoint" {
  value = azurerm_cdn_frontdoor_endpoint.main.host_name
}

Best Practices Summary

  1. Start in Detection mode - Tune for 2-4 weeks before Prevention
  2. Use the latest rule sets - OWASP 3.2 or DRS 2.1 for best protection
  3. Enable bot protection - Microsoft Bot Manager catches malicious bots
  4. Implement rate limiting - Protect APIs and login endpoints
  5. Create exclusions carefully - Document each exclusion with justification
  6. Monitor actively - Set up alerts for anomalous traffic patterns
  7. Use geo-blocking judiciously - Consider business requirements
  8. Combine with other controls - WAF is one layer of defense
  9. Regular rule review - Update exclusions and custom rules periodically
  10. Test your WAF - Use security scanners to validate protection

Troubleshooting

Issue: Legitimate Traffic Being Blocked

# Check WAF logs for specific blocked requests
az monitor log-analytics query \
  --workspace law-security \
  --analytics-query "AzureDiagnostics
    | where Category == 'ApplicationGatewayFirewallLog'
    | where action_s == 'Blocked'
    | where TimeGenerated > ago(1h)
    | project TimeGenerated, clientIp_s, requestUri_s, ruleId_s, Message
    | take 100"

Issue: WAF Not Blocking Known Threats

# Verify WAF policy is attached
az network application-gateway show \
  --name appgw-waf \
  --resource-group rg-waf \
  --query "firewallPolicy.id"

# Verify policy is in Prevention mode
az network application-gateway waf-policy show \
  --name waf-policy-appgw \
  --resource-group rg-waf \
  --query "policySettings.mode"

Frequently Asked Questions

Find answers to common questions

Azure WAF on Application Gateway is a regional layer 7 load balancer with WAF capabilities, ideal for applications hosted in a single Azure region. Azure WAF on Front Door is a global edge service that provides WAF at Microsoft's edge locations worldwide, offering lower latency, DDoS protection, and global load balancing. Use Application Gateway for regional apps and Front Door for global applications requiring the lowest latency and highest availability.

Azure Infrastructure Experts

Comprehensive Azure management including architecture, migration, security, and 24/7 operations.