快速入门:使用 ARM 模板在应用程序网关上创建 Azure WAF v2Quickstart: Create an Azure WAF v2 on Application Gateway using an ARM template

在本快速入门中,你将使用 Azure 资源管理器模板(ARM 模板)在应用程序网关上创建 Azure Web 应用程序防火墙 v2。In this quickstart, you use an Azure Resource Manager template (ARM template) to create an Azure Web Application Firewall v2 on Application Gateway.

ARM 模板是定义项目基础结构和配置的 JavaScript 对象表示法 (JSON) 文件。An ARM template is a JavaScript Object Notation (JSON) file that defines the infrastructure and configuration for your project. 该模板使用声明性语法,使你可以声明要部署的内容,而不需要编写一系列编程命令来进行创建。The template uses declarative syntax, which lets you state what you intend to deploy without having to write the sequence of programming commands to create it.

备注

本文已经过更新,以便使用 Azure Az PowerShell 模块。This article has been updated to use the Azure Az PowerShell module. 若要与 Azure 交互,建议使用的 PowerShell 模块是 Az PowerShell 模块。The Az PowerShell module is the recommended PowerShell module for interacting with Azure. 若要开始使用 Az PowerShell 模块,请参阅安装 Azure PowerShellTo get started with the Az PowerShell module, see Install Azure PowerShell. 若要了解如何迁移到 Az PowerShell 模块,请参阅 将 Azure PowerShell 从 AzureRM 迁移到 AzTo learn how to migrate to the Az PowerShell module, see Migrate Azure PowerShell from AzureRM to Az.

如果你的环境满足先决条件,并且你熟悉如何使用 ARM 模板,请选择“部署到 Azure”按钮。If your environment meets the prerequisites and you're familiar with using ARM templates, select the Deploy to Azure button. Azure 门户中会打开模板。The template will open in the Azure portal.

部署到 AzureDeploy to Azure

先决条件Prerequisites

查看模板Review the template

此模板在 Azure 应用程序网关上创建简单的 Web 应用程序防火墙 v2。This template creates a simple Web Application Firewall v2 on Azure Application Gateway. 这包括公共 IP 前端 IP 地址、HTTP 设置、包含端口 80 上的基本侦听器的规则,以及后端池。This includes a public IP frontend IP address, HTTP settings, a rule with a basic listener on port 80, and a backend pool. 将创建一个包含自定义规则的 WAF 策略,以根据 IP 地址匹配类型阻止发往后端池的流量。A WAF policy with a custom rule is created to block traffic to the backend pool based on an IP address match type.

本快速入门中使用的模板来自 Azure 快速启动模板The template used in this quickstart is from Azure Quickstart Templates.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminUsername": {
            "type": "String",
            "metadata": {
                "description": "Admin username for the backend servers"
            }
        },
        "adminPassword": {
            "type": "SecureString",
            "metadata": {
                "description": "Password for the admin account on the backend servers"
            }
        },
        "location": {
            "defaultValue": "[resourceGroup().location]",
            "type": "String",
            "metadata": {
                "description": "Location for all resources."
            }
        },
        "vmSize": {
            "defaultValue": "Standard_B2ms",
            "type": "String",
            "metadata": {
                "description": "Size of the virtual machine."
            }
        }
    },
    "variables": {
        "virtualMachines_myVM_name": "myVM",
        "virtualNetworks_myVNet_name": "myVNet",
        "net_interface": "net-int",
        "ipconfig_name": "ipconfig",
        "publicIPAddress": "public_ip",
        "nsg_name": "vm-nsg",
        "applicationGateways_myAppGateway_name": "myAppGateway",
        "vnet_prefix": "10.0.0.0/16",
        "ag_subnet_prefix": "10.0.0.0/24",
        "backend_subnet_prefix": "10.0.1.0/24",
        "AGWafPol01": "WafPol01"
    },
    "resources": [
        {
            "type": "Microsoft.Network/networkSecurityGroups",
            "apiVersion": "2019-11-01",
            "name": "[concat(variables('nsg_name'), copyIndex(1))]",
            "location": "[parameters('location')]",
            "copy": {
                "name": "nsg-loop",
                "count": 2
            },
            "properties": {
                "securityRules": [
                    {
                        "name": "RDP",
                        "properties": {
                            "protocol": "TCP",
                            "sourcePortRange": "*",
                            "destinationPortRange": "3389",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 300,
                            "direction": "Inbound"
                        }
                    }
                ]
            }

        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "apiVersion": "2019-11-01",
            "name": "[concat(variables('publicIPAddress'), copyIndex())]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "Standard"
            },
            "copy": {
                "name": "publicip-loop",
                "count": 3
            },
            "properties": {
                "publicIPAddressVersion": "IPv4",
                "publicIPAllocationMethod": "Static",
                "idleTimeoutInMinutes": 4
            }

        },
        {
            "type": "Microsoft.Network/virtualNetworks",
            "apiVersion": "2019-11-01",
            "name": "[variables('virtualNetworks_myVNet_name')]",
            "location": "[parameters('location')]",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[variables('vnet_prefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "myAGSubnet",
                        "properties": {
                            "addressPrefix": "[variables('ag_subnet_prefix')]",
                            "privateEndpointNetworkPolicies": "Enabled",
                            "privateLinkServiceNetworkPolicies": "Enabled"
                        }
                    },
                    {
                        "name": "myBackendSubnet",
                        "properties": {
                            "addressPrefix": "[variables('backend_subnet_prefix')]",
                            "privateEndpointNetworkPolicies": "Enabled",
                            "privateLinkServiceNetworkPolicies": "Enabled"
                        }
                    }
                ],
                "enableDdosProtection": false,
                "enableVmProtection": false
            }
        },
        {
            "type": "Microsoft.Compute/virtualMachines",
            "apiVersion": "2019-07-01",
            "name": "[concat(variables('virtualMachines_myVM_name'), copyIndex(1))]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('net_interface'), copyIndex(1)))]"
            ],
            "copy": {
                "name": "vm-loop",
                "count": 2
            },
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[parameters('vmSize')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "MicrosoftWindowsServer",
                        "offer": "WindowsServer",
                        "sku": "2016-Datacenter",
                        "version": "latest"
                    },
                    "osDisk": {
                        "osType": "Windows",
                        "createOption": "FromImage",
                        "caching": "ReadWrite",
                        "managedDisk": {
                            "storageAccountType": "StandardSSD_LRS"
                        },
                        "diskSizeGB": 127
                    }
                },
                "osProfile": {
                    "computerName": "[concat(variables('virtualMachines_myVM_name'), copyIndex(1))]",
                    "adminUsername": "[parameters('adminUsername')]",
                    "adminPassword": "[parameters('adminPassword')]",
                    "windowsConfiguration": {
                        "provisionVMAgent": true,
                        "enableAutomaticUpdates": true
                    },
                    "allowExtensionOperations": true
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('net_interface'), copyIndex(1)))]"
                        }
                    ]
                }
            }

        },
        {
            "type": "Microsoft.Compute/virtualMachines/extensions",
            "apiVersion": "2019-07-01",
            "name": "[concat(variables('virtualMachines_myVM_name'), copyIndex(1),'/IIS')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Compute/virtualMachines', concat(variables('virtualMachines_myVM_name'), copyIndex(1)))]"
            ],
            "properties": {
                "autoUpgradeMinorVersion": true,
                "publisher": "Microsoft.Compute",
                "type": "CustomScriptExtension",
                "typeHandlerVersion": "1.4",
                "settings": {
                    "commandToExecute": "powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\Default.htm\" -Value $($env:computername)"
                }
            },
            "copy": {
                "name": "ext-loop",
                "count": 2
            }
        },
        {
            "type": "Microsoft.Network/applicationGateways",
            "apiVersion": "2019-11-01",
            "name": "[variables('applicationGateways_myAppGateway_name')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworks_myVNet_name'))]",
                "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddress'), '0'))]",
                "[resourceId('Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies', variables('AGWafPol01'))]"
            ],
            "properties": {
                "sku": {
                    "name": "WAF_v2",
                    "tier": "WAF_v2",
                    "capacity": "2"
                },
                "gatewayIPConfigurations": [
                    {
                        "name": "appGatewayIpConfig",
                        "properties": {
                            "subnet": {
                                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworks_myVNet_name'), 'myAGSubnet')]"
                            }
                        }
                    }
                ],
                "frontendIPConfigurations": [
                    {
                        "name": "appGwPublicFrontendIp",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddress'), '0'))]"
                            }
                        }
                    }
                ],
                "frontendPorts": [
                    {
                        "name": "port_80",
                        "properties": {
                            "port": 80
                        }
                    }
                ],
                "backendAddressPools": [
                    {
                        "name": "myBackendPool",
                        "properties": {}
                    }
                ],
                "backendHttpSettingsCollection": [
                    {
                        "name": "myHTTPSetting",
                        "properties": {
                            "port": 80,
                            "protocol": "Http",
                            "cookieBasedAffinity": "Disabled",
                            "pickHostNameFromBackendAddress": false,
                            "requestTimeout": 20
                        }
                    }
                ],
                "httpListeners": [
                    {
                        "name": "myListener",
                        "properties": {
                            "firewallPolicy": {
                                "id": "[resourceId('Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies', variables('AGWafPol01'))]"
                            },
                            "frontendIPConfiguration": {
                                "id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', variables('applicationGateways_myAppGateway_name'), 'appGwPublicFrontendIp')]"
                            },
                            "frontendPort": {
                                "id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts', variables('applicationGateways_myAppGateway_name'), 'port_80')]"
                            },
                            "protocol": "Http",
                            "requireServerNameIndication": false
                        }
                    }
                ],
                "requestRoutingRules": [
                    {
                        "name": "myRoutingRule",
                        "properties": {
                            "ruleType": "Basic",
                            "httpListener": {
                                "id": "[resourceId('Microsoft.Network/applicationGateways/httpListeners', variables('applicationGateways_myAppGateway_name'), 'myListener')]"
                            },
                            "backendAddressPool": {
                                "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools', variables('applicationGateways_myAppGateway_name'), 'myBackendPool')]"
                            },
                            "backendHttpSettings": {
                                "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection', variables('applicationGateways_myAppGateway_name'), 'myHTTPSetting')]"
                            }
                        }
                    }
                ],
                "enableHttp2": false,
                "webApplicationFirewallConfiguration": {
                    "enabled": true,
                    "firewallMode": "Prevention",
                    "ruleSetType": "OWASP",
                    "ruleSetVersion": "3.1",
                    "requestBodyCheck": true,
                    "maxRequestBodySizeInKb": 128,
                    "fileUploadLimitInMb": 100
                },
                "firewallPolicy": {
                    "id": "[resourceId('Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies', variables('AGWafPol01'))]"
                }
            }
        },
        {
            "type": "Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies",
            "apiVersion": "2019-11-01",
            "name": "[variables('AGWafPol01')]",
            "location": "[parameters('location')]",
            "properties": {
                "customRules": [
                    {
                        "name": "CustRule01",
                        "priority": 100,
                        "ruleType": "MatchRule",
                        "action": "Block",
                        "matchConditions": [
                            {
                                "matchVariables": [
                                    {
                                        "variableName": "RemoteAddr"
                                    }
                                ],
                                "operator": "IPMatch",
                                "negationConditon": true,
                                "matchValues": [
                                    "10.10.10.0/24"
                                ]
                            }
                        ]
                    }
                ],
                "policySettings": {
                    "requestBodyCheck": true,
                    "maxRequestBodySizeInKb": 128,
                    "fileUploadLimitInMb": 100,
                    "state": "Enabled",
                    "mode": "Prevention"
                },
                "managedRules": {
                    "managedRuleSets": [
                        {
                            "ruleSetType": "OWASP",
                            "ruleSetVersion": "3.1"
                        }
                    ]
                }
            }
        },
        {
            "type": "Microsoft.Network/networkInterfaces",
            "apiVersion": "2019-11-01",
            "name": "[concat(variables('net_interface'), copyIndex(1))]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddress'), copyIndex(1)))]",
                "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworks_myVNet_name'))]",
                "[resourceId('Microsoft.Network/applicationGateways', variables('applicationGateways_myAppGateway_name'))]",
                "[resourceId('Microsoft.Network/networkSecurityGroups', concat(variables('nsg_name'), copyIndex(1)))]"
            ],
            "copy": {
                "name": "int-loop",
                "count": 2
            },
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "[concat(variables('ipconfig_name'), copyIndex(1))]",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddress'), copyIndex(1)))]"
                            },
                            "subnet": {
                                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworks_myVNet_name'), 'myBackendSubnet')]"
                            },
                            "primary": true,
                            "privateIPAddressVersion": "IPv4",
                            "applicationGatewayBackendAddressPools": [
                                {
                                    "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools', variables('applicationGateways_myAppGateway_name'), 'myBackendPool')]"
                                }
                            ]
                        }
                    }
                ],
                "enableAcceleratedNetworking": false,
                "enableIPForwarding": false,
                "networkSecurityGroup": {
                    "id": "[resourceId('Microsoft.Network/networkSecurityGroups', concat(variables('nsg_name'), copyIndex(1)))]"
                }
            }
        }
    ]
}

模板中定义了多个 Azure 资源:Multiple Azure resources are defined in the template:

部署模板Deploy the template

将 ARM 模板部署到 Azure:Deploy the ARM template to Azure:

  1. 选择“部署到 Azure”,登录到 Azure 并打开模板。Select Deploy to Azure to sign in to Azure and open the template. 该模板在运行 IIS 的后端池中创建应用程序网关、网络基础结构和两个虚拟机。The template creates an application gateway, the network infrastructure, and two virtual machines in the backend pool running IIS.

    部署到 AzureDeploy to Azure

  2. 选择或创建资源组。Select or create your resource group.

  3. 选择“我同意上述条款和条件”,然后选择“购买” 。Select I agree to the terms and conditions stated above and then select Purchase. 部署可能需要 10 分钟或更长时间才能完成。The deployment can take 10 minutes or longer to complete.

验证部署Validate the deployment

虽然无需 IIS 即可创建应用程序网关,但在后端服务器上安装 IIS 可以验证 Azure 是否已在应用程序网关上成功创建 WAF v2。Although IIS isn't required to create the application gateway, it's installed on the backend servers to verify if Azure successfully created a WAF v2 on the application gateway.

使用 IIS 测试应用程序网关:Use IIS to test the application gateway:

  1. 在“概述”页面上查找应用程序网关的公共 IP 地址记录应用程序网关公共 IP 地址或者,可以选择“所有资源”,在搜索框中输入“myAGPublicIPAddress”,然后在搜索结果中选择该地址 。Find the public IP address for the application gateway on its Overview page.Record application gateway public IP address Or, you can select All resources, enter myAGPublicIPAddress in the search box, and then select it in the search results. Azure 会在“概览”页上显示公共 IP 地址。Azure displays the public IP address on the Overview page.

  2. 复制公共 IP 地址,然后将其粘贴到浏览器的地址栏中,以便浏览该 IP 地址。Copy the public IP address, and then paste it into the address bar of your browser to browse that IP address.

  3. 检查响应。Check the response. “403 禁止”响应表示 WAF 已成功创建,并正在阻止与后端池建立连接。A 403 Forbidden response verifies that the WAF was successfully created and is blocking connections to the backend pool.

  4. 将自定义规则更改为“允许流量”。Change the custom rule to Allow traffic. 运行以下 Azure PowerShell 脚本(请替换资源组名称):Run the following Azure PowerShell script, replacing your resource group name:

    $rg = "<your resource group name>"
    $AppGW = Get-AzApplicationGateway -Name myAppGateway -ResourceGroupName $rg
    $pol = Get-AzApplicationGatewayFirewallPolicy -Name WafPol01 -ResourceGroupName $rg
    $pol[0].customrules[0].action = "allow"
    $rule = $pol.CustomRules
    Set-AzApplicationGatewayFirewallPolicy -Name WafPol01 -ResourceGroupName $rg -CustomRule $rule
    $AppGW.FirewallPolicy = $pol
    Set-AzApplicationGateway -ApplicationGateway $AppGW
    

    多次刷新浏览器就会看到与 myVM1 和 myVM2 的连接。Refresh your browser multiple times and you should see connections to both myVM1 and myVM2.

清理资源Clean up resources

如果不再需要通过应用程序网关创建的资源,请删除资源组。When you no longer need the resources that you created with the application gateway, delete the resource group. 这样会删除应用程序网关和所有相关的资源。This removes the application gateway and all the related resources.

若要删除资源组,请调用 Remove-AzResourceGroup cmdlet:To delete the resource group, call the Remove-AzResourceGroup cmdlet:

Remove-AzResourceGroup -Name "<your resource group name>"

后续步骤Next steps