教程:使用 Azure PowerShell 保护虚拟中心

本教程将使用一个区域中的虚拟中心创建一个虚拟 WAN 实例,并在该虚拟中心部署 Azure 防火墙以确保连接安全。 此示例将演示虚拟网络之间的安全连接。 虚拟网络和站点到站点、点到站点或 ExpressRoute 分支之间的流量也受虚拟安全中心支持。

在本教程中,你将了解如何执行以下操作:

  • 部署虚拟 WAN
  • 部署 Azure 防火墙并配置自定义路由
  • 测试连接

重要

虚拟 WAN 是中心以及其中提供的服务的集合。 可以部署所需的任意数量的虚拟 WAN。 虚拟 WAN 中心包含多个服务,例如 VPN、ExpressRoute 等。 如果相应区域支持可用性区域,则每个服务(Azure 防火墙除外)都将跨可用性区域自动部署。 若要将现有 Azure 虚拟 WAN 中心升级为安全中心,并让 Azure 防火墙使用可用性区域,必须使用 Azure PowerShell,具体方法将在本文后面部分介绍。

先决条件

  • 如果没有 Azure 订阅,请在开始前创建一个试用版订阅

  • PowerShell 7 或更高版本

    本教程要求在本地 PowerShell 7 或更高版本上运行 Azure PowerShell。 若要安装 PowerShell 7,请参阅从 Windows PowerShell 5.1 迁移到 PowerShell 7

  • “Az.Network”模块版本必须为 4.17.0 或更高。

登录 Azure

Connect-AzAccount -Environment AzureChinaCloud
Select-AzSubscription -Subscription "<sub name>"

初始虚拟 WAN 部署

首先,需要设置变量并创建资源组、虚拟 WAN 实例和虚拟中心:

# Variable definition
$RG = "vwan-rg"
$Location = "chinaeast2"
$VwanName = "vwan"
$HubName =  "hub1"
$FirewallTier = "Standard" # or "Premium"

# Create Resource Group, Virtual WAN and Virtual Hub using the New-AzVirtualWan and New-AzVirtualHub cmdlets
New-AzResourceGroup -Name $RG -Location $Location
$Vwan = New-AzVirtualWan -Name $VwanName -ResourceGroupName $RG -Location $Location -AllowVnetToVnetTraffic -AllowBranchToBranchTraffic -VirtualWANType "Standard"
$Hub = New-AzVirtualHub -Name $HubName -ResourceGroupName $RG -VirtualWan $Vwan -Location $Location -AddressPrefix "192.168.1.0/24" -Sku "Standard"
  • 使用 New-AzVirtualHubVnetConnection cmdlet 创建两个虚拟网络,并将其作为辐条连接到枢纽。 虚拟网络是使用地址前缀10.1.1.0/24创建的,10.1.2.0/24
# Create Virtual Network
$Spoke1 = New-AzVirtualNetwork -Name "spoke1" -ResourceGroupName $RG -Location $Location -AddressPrefix "10.1.1.0/24"
$Spoke2 = New-AzVirtualNetwork -Name "spoke2" -ResourceGroupName $RG -Location $Location -AddressPrefix "10.1.2.0/24"
# Connect Virtual Network to Virtual WAN
$Spoke1Connection = New-AzVirtualHubVnetConnection -ResourceGroupName $RG -ParentResourceName  $HubName -Name "spoke1" -RemoteVirtualNetwork $Spoke1 -EnableInternetSecurityFlag $True
$Spoke2Connection = New-AzVirtualHubVnetConnection -ResourceGroupName $RG -ParentResourceName  $HubName -Name "spoke2" -RemoteVirtualNetwork $Spoke2 -EnableInternetSecurityFlag $True

在此阶段,虚拟 WAN 已完全投入运行,并提供任意互联。 若要保护此环境,请在每个虚拟中心部署 Azure 防火墙。 可以使用防火墙策略集中管理这些防火墙。

在此示例中,还将创建防火墙策略,以使用 New-AzFirewallPolicy cmdlet 在虚拟 WAN 中心管理 Azure 防火墙实例。 Azure 防火墙将在枢纽中使用 New-AzFirewall cmdlet 部署。

# New Firewall Policy
$FWPolicy = New-AzFirewallPolicy -Name "VwanFwPolicy" -ResourceGroupName $RG -Location $Location
# New Firewall Public IP
$AzFWPIPs = New-AzFirewallHubPublicIpAddress -Count 1
$AzFWHubIPs = New-AzFirewallHubIpAddress -PublicIP $AzFWPIPs
# New Firewall
$AzFW = New-AzFirewall -Name "azfw1" -ResourceGroupName $RG -Location $Location `
            -VirtualHubId $Hub.Id -FirewallPolicyId $FWPolicy.Id `
            -SkuName "AZFW_Hub" -HubIPAddress $AzFWHubIPs `
            -SkuTier $FirewallTier

注意

以下防火墙创建命令不使用可用性区域。 如果你想要使用此功能,需要添加一个附加参数 -Zone。 本文末尾的“升级”部分提供了示例。

启用从 Azure 防火墙到 Azure Monitor 的日志记录是可选的。 在此示例中,你将使用防火墙日志来验证流量是否通过防火墙。 首先,创建 Log Analytics 工作区来存储日志。 然后,使用 Set-AzDiagnosticSetting cmdlet 配置诊断设置并将日志发送到工作区。

# Optionally, enable logging of Azure Firewall to Azure Monitor
$LogWSName = "vwan-" + (Get-Random -Maximum 99999) + "-" + $RG
$LogWS = New-AzOperationalInsightsWorkspace -Location $Location -Name $LogWSName -Sku Standard -ResourceGroupName $RG
Set-AzDiagnosticSetting -ResourceId $AzFW.Id -Enabled $True -Category AzureFirewallApplicationRule, AzureFirewallNetworkRule -WorkspaceId $LogWS.ResourceId

部署 Azure 防火墙并配置自定义路由

注意

这是在使用 Azure 防火墙管理器保护来自 Azure 门户的连接并且“中心间”设置设为“已禁用”时部署的配置。

现在中心已具有 Azure 防火墙,但仍需要修改路由,以便让虚拟 WAN 通过防火墙发送来自虚拟网络和分支的流量。 可以通过两个步骤达到此目的:

  1. 配置要传播到 None 路由表的所有虚拟网络连接(以及存在的所有分支连接)。 此配置的效果是,其他虚拟网络和分支不会学习其前缀,因此没有路由来访问它们。
  2. 现在可以在 Default 路由表(默认情况下关联所有虚拟网络和分支)中插入静态路由,以便将所有流量发送到 Azure 防火墙。

从第一步开始,将虚拟网络连接配置为传播到 None 路由表:

# Configure Virtual Network connections in hub to propagate to None
$VnetRoutingConfig = $Spoke1Connection.RoutingConfiguration    # We take $Spoke1Connection as baseline for the future vnet config, all vnets will have an identical config
$NoneRT = Get-AzVhubRouteTable -ResourceGroupName $RG -HubName $HubName -Name "noneRouteTable"
$NewPropRT = @{}
$NewPropRT.Add('Id', $NoneRT.Id)
$PropRTList = @()
$PropRTList += $NewPropRT
$VnetRoutingConfig.PropagatedRouteTables.Ids = $PropRTList
$VnetRoutingConfig.PropagatedRouteTables.Labels = @()
$Spoke1Connection = Update-AzVirtualHubVnetConnection -ResourceGroupName $RG -ParentResourceName  $HubName -Name "spoke1" -RoutingConfiguration $VnetRoutingConfig
$Spoke2Connection = Update-AzVirtualHubVnetConnection -ResourceGroupName $RG -ParentResourceName  $HubName -Name "spoke2" -RoutingConfiguration $VnetRoutingConfig

接下来,继续执行第二步:将静态路由添加到 Default 路由表。 以下示例使用 Azure 防火墙管理器在保护虚拟 WAN 中的连接时应用的默认配置。 您可以根据需要使用 New-AzVHubRoute cmdlet 自定义静态路由的前缀列表。 在此示例中,所有流量都通过 Azure 防火墙进行路由,这是建议的默认值。

# Create static routes in default Route table
$AzFWId = $(Get-AzVirtualHub -ResourceGroupName $RG -name  $HubName).AzureFirewall.Id
$AzFWRoute = New-AzVHubRoute -Name "all_traffic" -Destination @("0.0.0.0/0", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16") -DestinationType "CIDR" -NextHop $AzFWId -NextHopType "ResourceId"
$DefaultRT = Update-AzVHubRouteTable -Name "defaultRouteTable" -ResourceGroupName $RG -VirtualHubName  $HubName -Route @($AzFWRoute)

注意

上述 New-AzVHubRoute 命令中参数“-Name”的字符串“all_traffic”具有特殊含义:如果使用此确切字符串,本文中应用的配置将正确反映在 Azure 门户(防火墙管理器 --> 虚拟中心 --> [中心] --> 安全配置) 中。 如果使用其他名称,则会应用所需的配置,但不会反映在 Azure 门户中。

测试连接

当您的安全集线器完全正常运行后,您可以通过在连接到集线器的每个轮辐虚拟网络中部署虚拟机来测试连接。

# Create VMs in spokes for testing
$VMLocalAdminUser = "lab-user"
$VMLocalAdminSecurePassword = ConvertTo-SecureString -AsPlainText -Force
$VMCredential = New-Object System.Management.Automation.PSCredential ($VMLocalAdminUser, $VMLocalAdminSecurePassword);
$VMSize = "Standard_B2ms"
# Spoke1
$Spoke1 = Get-AzVirtualNetwork -ResourceGroupName $RG -Name "spoke1"
Add-AzVirtualNetworkSubnetConfig -Name "vm" -VirtualNetwork $Spoke1 -AddressPrefix "10.1.1.0/26"
$Spoke1 | Set-AzVirtualNetwork
$VM1 = New-AzVM -Name "spoke1-vm" -ResourceGroupName $RG -Location $Location `
            -Image "UbuntuLTS" -credential $VMCredential `
            -VirtualNetworkName "spoke1" -SubnetName "vm" -PublicIpAddressName "spoke1-pip"
$NIC1 = Get-AzNetworkInterface -ResourceId $($VM1.NetworkProfile.NetworkInterfaces[0].Id)
$Spoke1VMPrivateIP = $NIC1.IpConfigurations[0].PrivateIpAddress
$Spoke1VMPIP = $(Get-AzPublicIpAddress -ResourceGroupName $RG -Name "spoke1-pip")
# Spoke2
$Spoke2 = Get-AzVirtualNetwork -ResourceGroupName $RG -Name "spoke2"
Add-AzVirtualNetworkSubnetConfig -Name "vm" -VirtualNetwork $Spoke2 -AddressPrefix "10.1.2.0/26"
$Spoke2 | Set-AzVirtualNetwork
$VM2 = New-AzVM -Name "spoke2-vm" -ResourceGroupName $RG -Location $Location `
            -Image "UbuntuLTS" -credential $VMCredential `
            -VirtualNetworkName "spoke2" -SubnetName "vm" -PublicIpAddressName "spoke2-pip"
$NIC2 = Get-AzNetworkInterface -ResourceId $($VM2.NetworkProfile.NetworkInterfaces[0].Id)
$Spoke2VMPrivateIP = $NIC2.IpConfigurations[0].PrivateIpAddress
$Spoke2VMPIP = $(Get-AzPublicIpAddress -ResourceGroupName $RG -Name "spoke2-pip")

默认情况下,防火墙策略会阻止所有流量。 若要允许访问测试虚拟机,必须配置 DNAT(目标网络地址转换)规则。 通过这些规则,可以通过 Azure 防火墙的公共 IP 地址连接到 VM:

# Adding DNAT rules for virtual machines in the spokes
$AzFWPublicAddress = $AzFW.HubIPAddresses.PublicIPs.Addresses[0].Address
$NATRuleSpoke1 = New-AzFirewallPolicyNatRule -Name "Spoke1SSH" -Protocol "TCP" `
        -SourceAddress "*" -DestinationAddress $AzFWPublicAddress -DestinationPort 10001 `
        -TranslatedAddress $Spoke1VMPrivateIP -TranslatedPort 22
$NATRuleSpoke2 = New-AzFirewallPolicyNatRule -Name "Spoke2SSH" -Protocol "TCP" `
        -SourceAddress "*" -DestinationAddress $AzFWPublicAddress -DestinationPort 10002 `
        -TranslatedAddress $Spoke2VMPrivateIP -TranslatedPort 22
$NATCollection = New-AzFirewallPolicyNatRuleCollection -Name "SSH" -Priority 100 `
        -Rule @($NATRuleSpoke1, $NATRuleSpoke2) -ActionType "Dnat"
$NATGroup = New-AzFirewallPolicyRuleCollectionGroup -Name "NAT" -Priority 100 -RuleCollection $NATCollection -FirewallPolicyObject $FWPolicy

接下来,为防火墙策略配置示例规则。 首先,创建一个网络规则,以允许虚拟网络之间的 SSH 流量。 然后,添加应用程序规则以仅允许 Internet 访问完全限定的域名(FQDN), ifconfig.co该规则返回 HTTP 请求中显示的源 IP 地址:

# Add Network Rule
$SSHRule = New-AzFirewallPolicyNetworkRule -Name PermitSSH -Protocol TCP `
        -SourceAddress "10.0.0.0/8" -DestinationAddress "10.0.0.0/8" -DestinationPort 22
$NetCollection = New-AzFirewallPolicyFilterRuleCollection -Name "Management" -Priority 100 -ActionType Allow -Rule $SSHRule
$NetGroup = New-AzFirewallPolicyRuleCollectionGroup -Name "Management" -Priority 200 -RuleCollection $NetCollection -FirewallPolicyObject $FWPolicy
# Add Application Rule
$ifconfigRule = New-AzFirewallPolicyApplicationRule -Name PermitIfconfig -SourceAddress "10.0.0.0/8" -TargetFqdn "ifconfig.co" -Protocol "http:80","https:443"
$AppCollection = New-AzFirewallPolicyFilterRuleCollection -Name "TargetURLs" -Priority 300 -ActionType Allow -Rule $ifconfigRule
$NetGroup = New-AzFirewallPolicyRuleCollectionGroup -Name "TargetURLs" -Priority 300 -RuleCollection $AppCollection -FirewallPolicyObject $FWPolicy

在发送任何流量之前,请检查每个虚拟机的有效路由。 路由表应该显示从虚拟 WAN(0.0.0.0/0 和 RFC1918 范围)中学习的前缀,但不应包含其他分支虚拟网络的地址前缀。

# Check effective routes in the VM NIC in spoke 1
# Note that 10.1.2.0/24 (the prefix for spoke2) should not appear
Get-AzEffectiveRouteTable -ResourceGroupName $RG -NetworkInterfaceName $NIC1.Name | ft
# Check effective routes in the VM NIC in spoke 2
# Note that 10.1.1.0/24 (the prefix for spoke1) should not appear
Get-AzEffectiveRouteTable -ResourceGroupName $RG -NetworkInterfaceName $NIC2.Name | ft

现在,生成从一个虚拟机到另一个虚拟机的流量,然后验证 Azure 防火墙中是否已删除该流量。 在以下 SSH 命令中,需要接受虚拟机指纹,并提供在创建虚拟机时定义的密码。 在此示例中,将从 spoke1 中的虚拟机向 spoke2 发送五个 ICMP 回显请求数据包,并使用 Linux 实用工具 nc 在端口 22 上尝试 TCP 连接(使用 -vz 标志,只发送连接请求并显示结果)。 结果应为 ping 失败,而端口 22 上的 TCP 连接尝试成功,因为之前配置的网络规则允许该连接:

# Connect to one VM and ping the other. It should not work, because the firewall should drop the traffic, since no rule for ICMP is configured
ssh $AzFWPublicAddress -p 10001 -l $VMLocalAdminUser "ping $Spoke2VMPrivateIP -c 5"
# Connect to one VM and send a TCP request on port 22 to the other. It should work, because the firewall is configured to allow SSH traffic (port 22)
ssh $AzFWPublicAddress -p 10001 -l $VMLocalAdminUser "nc -vz $Spoke2VMPrivateIP 22"

还可以通过防火墙测试 Internet 访问。 对允许的 FQDN (curl) 使用ifconfig.co实用工具的 HTTP 请求应成功,而对其他目标(例如bing.com)的请求应被防火墙策略阻止:

# This HTTP request should succeed, since it is allowed in an app rule in the AzFW, and return the public IP of the FW
ssh $AzFWPublicAddress -p 10001 -l $VMLocalAdminUser "curl -s4 ifconfig.co"
# This HTTP request should fail, since the FQDN bing.com is not in any app rule in the firewall policy
ssh $AzFWPublicAddress -p 10001 -l $VMLocalAdminUser "curl -s4 bing.com"

若要确认防火墙正在按预期删除数据包,请查看发送到 Azure Monitor 的日志。 由于 Azure 防火墙配置为将诊断日志发送到 Azure Monitor,因此可以使用 Kusto 查询语言(KQL)来查询和分析相关的日志条目:

注意

可能需要大约 1 分钟的时间才能看到日志被发送到 Azure Monitor

# Getting Azure Firewall network rule Logs
$LogWS = Get-AzOperationalInsightsWorkspace -ResourceGroupName $RG
$LogQuery = 'AzureDiagnostics
| where Category == "AzureFirewallNetworkRule"
| where TimeGenerated >= ago(5m)
| parse msg_s with Protocol " request from " SourceIP ":" SourcePortInt:int " to " TargetIP ":" TargetPortInt:int *
| parse msg_s with * ". Action: " Action1a
| parse msg_s with * " was " Action1b " to " NatDestination
| parse msg_s with Protocol2 " request from " SourceIP2 " to " TargetIP2 ". Action: " Action2
| extend SourcePort = tostring(SourcePortInt),TargetPort = tostring(TargetPortInt)
| extend Action = case(Action1a == "", case(Action1b == "",Action2,Action1b), Action1a),Protocol = case(Protocol == "", Protocol2, Protocol),SourceIP = case(SourceIP == "", SourceIP2, SourceIP),TargetIP = case(TargetIP == "", TargetIP2, TargetIP),SourcePort = case(SourcePort == "", "N/A", SourcePort),TargetPort = case(TargetPort == "", "N/A", TargetPort),NatDestination = case(NatDestination == "", "N/A", NatDestination)
| project TimeGenerated, Protocol, SourceIP,SourcePort,TargetIP,TargetPort,Action, NatDestination, Resource
| take 25 '
$(Invoke-AzOperationalInsightsQuery -Workspace $LogWS -Query $LogQuery).Results | ft

在前面的命令中,应看到不同的条目:

  • 正在对 SSH 连接应用 DNAT 规则
  • 已删除分支(10.1.1.4 和 10.1.2.4)中 VM 之间的 ICMP 数据包
  • 允许在分支中的 VM 之间建立 SSH 连接

下面是上述命令生成的输出示例:

TimeGenerated            Protocol    SourceIP       SourcePort TargetIP      TargetPort Action  NatDestination Resource
------------- --------    -------- ---------- -------- ---------- ------ -------------- --------
2020-10-04T20:53:02.41Z  TCP         109.125.122.99 62281      51.105.224.44 10001      DNAT'ed 10.1.1.4:22    AZFW1
2020-10-04T20:53:07.045Z TCP         10.1.1.4       35932      10.1.2.4      22         Allow   N/A            AZFW1
2020-10-04T20:53:50.119Z TCP         109.125.122.99 62293      51.105.224.44 10001      DNAT'ed 10.1.2.4:22    AZFW1
2020-10-04T20:52:47.475Z TCP         109.125.122.99 62273      51.105.224.44 10001      DNAT'ed 10.1.2.4:22    AZFW1
2020-10-04T20:51:04.682Z TCP         109.125.122.99 62200      51.105.224.44 10001      DNAT'ed 10.1.2.4:22    AZFW1
2020-10-04T20:51:17.031Z ICMP Type=8 10.1.1.4       N/A        10.1.2.4      N/A        Deny    N/A            AZFW1
2020-10-04T20:51:18.049Z ICMP Type=8 10.1.1.4       N/A        10.1.2.4      N/A        Deny    N/A            AZFW1
2020-10-04T20:51:19.075Z ICMP Type=8 10.1.1.4       N/A        10.1.2.4      N/A        Deny    N/A            AZFW1
2020-10-04T20:51:20.097Z ICMP Type=8 10.1.1.4       N/A        10.1.2.4      N/A        Deny    N/A            AZFW1
2020-10-04T20:51:21.121Z ICMP Type=8 10.1.1.4       N/A        10.1.2.4      N/A        Deny    N/A            AZFW1
2020-10-04T20:52:52.356Z TCP         10.1.1.4       53748      10.1.2.4      22         Allow   N/A            AZFW1

若要查看应用程序规则(描述允许和拒绝的 HTTP 连接)的日志或更改日志显示方式,可以尝试使用其他 KQL 查询。 可以在 Azure 防火墙的 Azure Monitor 日志中找到一些示例。

若要清理测试环境,请使用 Remove-AzResourceGroup cmdlet 删除资源组和所有关联的资源。 这将删除在本教程中创建的虚拟 WAN、虚拟中心、Azure 防火墙和任何其他资源。

# Delete resource group and all contained resources
Remove-AzResourceGroup -Name $RG

将具有可用性区域的新 Azure 防火墙部署到现有中心

前面的步骤演示了如何使用 Azure PowerShell 创建新的 Azure 虚拟 WAN 中心并使用 Azure 防火墙保护它。 还可以使用类似的基于脚本的方法保护 现有的 Azure 虚拟 WAN 中心。 虽然防火墙管理器可以将中心转换为安全中心,但它不支持通过门户跨可用性区域部署 Azure 防火墙。 若要在所有三个可用性区域中部署 Azure 防火墙,请使用以下 PowerShell 脚本将现有虚拟 WAN 中心转换为安全中心。

注意

此过程会部署新的 Azure 防火墙。 在没有可用性区域的情况下,无法将现有 Azure 防火墙升级到具有可用性区域的防火墙。 必须先删除中心中的现有 Azure 防火墙,然后使用此过程再次创建它。

# Variable definition
$RG = "vwan-rg"
$Location = "chinanorth"
$VwanName = "vwan"
$HubName =  "hub1"
$FirewallName = "azfw1"
$FirewallTier = "Standard" # or "Premium"
$FirewallPolicyName = "VwanFwPolicy"

# Get references to vWAN and vWAN Hub to convert #
$Vwan = Get-AzVirtualWan -ResourceGroupName $RG -Name $VwanName
$Hub = Get-AzVirtualHub -ResourceGroupName  $RG -Name $HubName

# Create a new Firewall Policy #
$FWPolicy = New-AzFirewallPolicy -Name $FirewallPolicyName -ResourceGroupName $RG -Location $Location

# Create a new Firewall Public IP #
$AzFWPIPs = New-AzFirewallHubPublicIpAddress -Count 1
$AzFWHubIPs = New-AzFirewallHubIpAddress -PublicIP $AzFWPIPs

# Create Firewall instance #
$AzFW = New-AzFirewall -Name $FirewallName -ResourceGroupName $RG -Location $Location `
            -VirtualHubId $Hub.Id -FirewallPolicyId $FWPolicy.Id `
            -SkuName "AZFW_Hub" -HubIPAddress $AzFWHubIPs `
            -SkuTier $FirewallTier `
            -Zone 1,2,3

运行此脚本后,可用性区域应显示在安全中心属性中,如以下屏幕截图所示:

安全虚拟中心可用性区域的屏幕截图。

部署 Azure 防火墙后,必须完成前面 部署 Azure 防火墙中所述的配置步骤,并配置自定义路由 部分,以确保正确的路由和安全性。

后续步骤