通过警报和 Azure Functions,使用数据包捕获执行主动网络监视Use packet capture for proactive network monitoring with alerts and Azure Functions

网络观察程序数据包捕获功能可以创建捕获会话,跟踪传入和传出虚拟机的流量。Network Watcher packet capture creates capture sessions to track traffic in and out of virtual machines. 可在捕获文件中包含一个定义的筛选器,使其只跟踪要监视的流量。The capture file can have a filter that is defined to track only the traffic that you want to monitor. 然后,将此数据存储在存储 Blob 中或来宾计算机本地。This data is then stored in a storage blob or locally on the guest machine.

可以通过 Azure Functions 等其他自动化方案远程启动此功能。This capability can be started remotely from other automation scenarios such as Azure Functions. 数据包捕获提供基于定义的网络异常运行主动捕获的功能。Packet capture gives you the capability to run proactive captures based on defined network anomalies. 其他用途包括收集网络统计信息、获取有关网络入侵的信息、调试客户端通信等等。Other uses include gathering network statistics, getting information about network intrusions, debugging client-server communications, and more.

Azure 中部署的资源全天候运行。Resources that are deployed in Azure run 24/7. 但你和你的同事无法全天候主动监视所有资源的状态。You and your staff cannot actively monitor the status of all resources 24/7. 例如,如果凌晨 2 点出现问题,会发生什么情况?For example, what happens if an issue occurs at 2 AM?

在 Azure 生态系统中使用网络观察程序、警报和函数,可以主动使用数据和工具做出响应,解决网络中的问题。By using Network Watcher, alerting, and functions from within the Azure ecosystem, you can proactively respond with the data and tools to solve problems in your network.

方案

备注

本文进行了更新,以便使用新的 Azure PowerShell Az 模块。This article has been updated to use the new Azure PowerShell Az module. 你仍然可以使用 AzureRM 模块,至少在 2020 年 12 月之前,它将继续接收 bug 修补程序。You can still use the AzureRM module, which will continue to receive bug fixes until at least December 2020. 若要详细了解新的 Az 模块和 AzureRM 兼容性,请参阅新 Azure Powershell Az 模块简介To learn more about the new Az module and AzureRM compatibility, see Introducing the new Azure PowerShell Az module. 有关 Az 模块安装说明,请参阅安装 Azure PowerShellFor Az module installation instructions, see Install Azure PowerShell.

先决条件Prerequisites

方案Scenario

在本示例中,VM 发送的 TCP 段数比平常多,因此你希望收到相关警报。In this example, your VM is sending more TCP segments than usual, and you want to be alerted. 此处所示的 TCP 段只是用作示例,但可以使用任何警报条件。TCP segments are used as an example here, but you can use any alert condition.

收到警报时,希望收到数据包级别的数据,了解通信量为何提高。When you are alerted, you want to receive packet-level data to understand why communication has increased. 然后,便可以采取措施让虚拟机恢复日常通信。Then you can take steps to return the virtual machine to regular communication.

本方案假设已具有网络观察程序的现有实例,以及一个包含有效虚拟机的资源组。This scenario assumes that you have an existing instance of Network Watcher and a resource group with a valid virtual machine.

以下列表了提供发生的工作流概述:The following list is an overview of the workflow that takes place:

  1. 在 VM 上触发警报。An alert is triggered on your VM.
  2. 该警报通过 Webhook 调用 Azure 函数。The alert calls your Azure function via a webhook.
  3. Azure 函数处理警报,并启动网络观察程序数据包捕获会话。Your Azure function processes the alert and starts a Network Watcher packet capture session.
  4. 数据包捕获在 VM 上运行并收集流量。The packet capture runs on the VM and collects traffic.
  5. 将数据包捕获文件上传到存储帐户进行审查和诊断。The packet capture file is uploaded to a storage account for review and diagnosis.

为了自动完成此过程,我们在 VM 上创建并连接了一个发生事件时要触发的警报。To automate this process, we create and connect an alert on our VM to trigger when the incident occurs. 还创建了用于调入网络观察程序的函数。We also create a function to call into Network Watcher.

此方案执行以下任务:This scenario does the following:

  • 创建一个启动数据包捕获的 Azure 函数。Creates an Azure function that starts a packet capture.
  • 在虚拟机上创建警报规则,并将警报规则配置为调用该 Azure 函数。Creates an alert rule on a virtual machine and configures the alert rule to call the Azure function.

创建 Azure 函数Create an Azure function

第一步是创建一个 Azure 函数来处理警报并创建数据包捕获。The first step is to create an Azure function to process the alert and create a packet capture.

  1. Azure 门户中,选择“创建资源” > “计算” > “Function App” 。In the Azure portal, select Create a resource > Compute > Function App.

    创建一个函数应用

  2. 在“Function App”边栏选项卡中输入以下值,然后选择“确定”以创建应用 :On the Function App blade, enter the following values, and then select OK to create the app:

    设置Setting Value 详细信息Details
    应用名称App name PacketCaptureExamplePacketCaptureExample 函数应用的名称。The name of the function app.
    订阅Subscription [订阅]要为其创建函数应用的订阅。[Your subscription]The subscription for which to create the function app.
    资源组Resource Group PacketCaptureRGPacketCaptureRG 包含函数应用的资源组。The resource group to contain the function app.
    托管计划Hosting Plan 消耗计划Consumption Plan 函数应用使用的计划类型。The type of plan your function app uses. 选项包括“使用计划”或“Azure 应用服务计划”。Options are Consumption or Azure App Service plan.
    位置Location 中国北部China North 要在其中创建函数应用的区域。The region in which to create the function app.
    存储帐户Storage Account {autogenerated}{autogenerated} Azure Functions 需用于常规存储的存储帐户。The storage account that Azure Functions needs for general-purpose storage.
  3. 在 Function Apps 的“PacketCaptureExample”边栏选项卡上,选择“函数” > “自定义函数” >“+” 。On the PacketCaptureExample Function Apps blade, select Functions > Custom function >+.

  4. 选择“HttpTrigger-Powershell”,然后输入其余信息。Select HttpTrigger-Powershell, and then enter the remaining information. 最后,选择“创建”以创建函数。Finally, to create the function, select Create.

    设置Setting Value 详细信息Details
    方案Scenario 实验Experimental 方案的类型Type of scenario
    为函数命名Name your function AlertPacketCapturePowerShellAlertPacketCapturePowerShell 函数的名称Name of the function
    授权级别Authorization level 函数Function 函数的授权级别Authorization level for the function

函数示例

备注

PowerShell 模板处于试验阶段且没有完全支持。The PowerShell template is experimental and does not have full support.

自定义项是此示例所必需的,并在以下步骤中说明。Customizations are required for this example and are explained in the following steps.

添加模块Add modules

若要使用网络观察程序 PowerShell cmdlet,将最新 PowerShell 模块上传到函数应用。To use Network Watcher PowerShell cmdlets, upload the latest PowerShell module to the function app.

  1. 在已安装最新 Azure PowerShell 模块的本地计算机上,运行以下 PowerShell 命令:On your local machine with the latest Azure PowerShell modules installed, run the following PowerShell command:

    (Get-Module Az.Network).Path
    

    该示例提供 Azure PowerShell 模块的本地路径。This example gives you the local path of your Azure PowerShell modules. 在稍后的步骤中将使用这些文件夹。These folders are used in a later step. 此方案中使用的模块包括:The modules that are used in this scenario are:

    • Az.NetworkAz.Network

    • Az.AccountsAz.Accounts

    • Az.ResourcesAz.Resources

      PowerShell 文件夹

  2. 选择“函数应用设置” > “转到应用服务编辑器” 。Select Function app settings > Go to App Service Editor.

    函数应用设置

  3. 右键单击 AlertPacketCapturePowershell 文件夹,然后创建一个名为 azuremodules 的文件夹 。Right-click the AlertPacketCapturePowershell folder, and then create a folder called azuremodules.

  4. 为每个所需模块创建子文件夹。Create a subfolder for each module that you need.

    文件夹和子文件夹

    • Az.NetworkAz.Network

    • Az.AccountsAz.Accounts

    • Az.ResourcesAz.Resources

  5. 右键单击“Az.Network”子文件夹,然后选择“上传文件” 。Right-click the Az.Network subfolder, and then select Upload Files.

  6. 转到 Azure 模块。Go to your Azure modules. 在本地“Az.Network”文件夹中,选择文件夹中的所有文件。In the local Az.Network folder, select all the files in the folder. 然后选择“确定”。Then select OK.

  7. Az.AccountsAz.Resources 重复执行上述步骤。Repeat these steps for Az.Accounts and Az.Resources.

    上传文件

  8. 完成后,每个文件夹应具有来自本地计算机的 PowerShell 模块文件。After you've finished, each folder should have the PowerShell module files from your local machine.

    PowerShell 文件

身份验证Authentication

若要使用 PowerShell cmdlet,必须进行身份验证。To use the PowerShell cmdlets, you must authenticate. 配置函数应用中的身份验证。You configure authentication in the function app. 若要配置身份验证,必须配置环境变量,并将加密密钥文件上传到函数应用。To configure authentication, you must configure environment variables and upload an encrypted key file to the function app.

备注

此方案仅提供如何使用 Azure Functions 实现身份验证的一个示例。This scenario provides just one example of how to implement authentication with Azure Functions. 还可以通过其他方法执行此操作。There are other ways to do this.

加密凭据Encrypted credentials

以下 PowerShell 脚本创建名为 PassEncryptKey.key 的密钥文件。The following PowerShell script creates a key file called PassEncryptKey.key. 它还提供所提供密码的加密版本。It also provides an encrypted version of the password that's supplied. 此密码是为用于身份验证的 Azure Active Directory 应用程序定义的同一密码。This password is the same password that is defined for the Azure Active Directory application that's used for authentication.

#Variables
$keypath = "C:\temp\PassEncryptKey.key"
$AESKey = New-Object Byte[] 32
$Password = "<insert a password here>"

#Keys
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey) 
Set-Content $keypath $AESKey

#Get encrypted password
$secPw = ConvertTo-SecureString -AsPlainText $Password -Force
$AESKey = Get-content $KeyPath
$Encryptedpassword = $secPw | ConvertFrom-SecureString -Key $AESKey
$Encryptedpassword

在函数应用的应用服务编辑器中,在 AlertPacketCapturePowerShell 下创建一个名为 keys 的文件夹 。In the App Service Editor of the function app, create a folder called keys under AlertPacketCapturePowerShell. 然后上传在之前的 PowerShell 示例中创建的 PassEncryptKey.key。Then upload the PassEncryptKey.key file that you created in the previous PowerShell sample.

函数密钥

检索环境变量的值Retrieve values for environment variables

最后一项要求是设置访问用于身份验证的值所必需的环境变量。The final requirement is to set up the environment variables that are necessary to access the values for authentication. 以下列表显示创建的环境变量:The following list shows the environment variables that are created:

  • AzureClientIDAzureClientID

  • AzureTenantAzureTenant

  • AzureCredPasswordAzureCredPassword

AzureClientIDAzureClientID

客户端 ID 是 Azure Active Directory 中应用程序的应用程序 ID。The client ID is the Application ID of an application in Azure Active Directory.

  1. 如果还没有可使用的应用程序,请运行以下示例创建应用程序。If you don't already have an application to use, run the following example to create an application.

    $app = New-AzADApplication -DisplayName "ExampleAutomationAccount_MF" -HomePage "https://exampleapp.com" -IdentifierUris "https://exampleapp1.com/ExampleFunctionsAccount" -Password "<same password as defined earlier>"
    New-AzADServicePrincipal -ApplicationId $app.ApplicationId
    Start-Sleep 15
    New-AzRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $app.ApplicationId
    

    备注

    创建应用程序时使用的密码应与先前在保存密钥文件时创建的密码相同。The password that you use when creating the application should be the same password that you created earlier when saving the key file.

  2. 在 Azure 门户中,选择“订阅”。In the Azure portal, select Subscriptions. 选择要使用的订阅,然后选择“访问控制(IAM)”。Select the subscription to use, and then select Access control (IAM).

    函数 IAM

  3. 选择要使用的帐户,然后选择“属性”。Choose the account to use, and then select Properties. 复制应用程序 ID。Copy the Application ID.

    函数应用程序 ID

AzureTenantAzureTenant

通过运行以下 PowerShell 示例获取租户 ID:Obtain the tenant ID by running the following PowerShell sample:

(Get-AzSubscription -SubscriptionName "<subscriptionName>").TenantId

AzureCredPasswordAzureCredPassword

AzureCredPassword 环境变量的值是通过运行以下 PowerShell 示例获得的值。The value of the AzureCredPassword environment variable is the value that you get from running the following PowerShell sample. 此示例是前面的“加密凭据”部分中显示的同一示例。This example is the same one that's shown in the preceding Encrypted credentials section. 所需的值是 $Encryptedpassword 变量的输出。The value that's needed is the output of the $Encryptedpassword variable. 这是使用 PowerShell 脚本加密的服务主体密码。This is the service principal password that you encrypted by using the PowerShell script.

#Variables
$keypath = "C:\temp\PassEncryptKey.key"
$AESKey = New-Object Byte[] 32
$Password = "<insert a password here>"

#Keys
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey) 
Set-Content $keypath $AESKey

#Get encrypted password
$secPw = ConvertTo-SecureString -AsPlainText $Password -Force
$AESKey = Get-content $KeyPath
$Encryptedpassword = $secPw | ConvertFrom-SecureString -Key $AESKey
$Encryptedpassword

存储环境变量Store the environment variables

  1. 转到函数应用。Go to the function app. 然后选择“函数应用设置” > “配置应用设置” 。Then select Function app settings > Configure app settings.

    配置应用设置

  2. 将环境变量及其值添加到应用设置,然后选择“保存”。Add the environment variables and their values to the app settings, and then select Save.

    应用设置

将 PowerShell 添加到函数Add PowerShell to the function

现可从 Azure 函数内部调用网络观察程序。It's now time to make calls into Network Watcher from within the Azure function. 根据要求,此函数的实现有所不同。Depending on the requirements, the implementation of this function can vary. 但是,代码的常规流程如下所示:However, the general flow of the code is as follows:

  1. 处理输入参数。Process input parameters.
  2. 查询现有的数据包捕获,验证限制并解决名称冲突。Query existing packet captures to verify limits and resolve name conflicts.
  3. 使用适当的参数创建数据包捕获。Create a packet capture with appropriate parameters.
  4. 定期轮询数据包捕获,直到完成。Poll packet capture periodically until it's complete.
  5. 通知用户数据包捕获会话已完成。Notify the user that the packet capture session is complete.

以下示例为 PowerShell 代码,可在函数中使用。The following example is PowerShell code that can be used in the function. 存在需要为 subscriptionId、resourceGroupName 和 storageAccountName 替换的值 。There are values that need to be replaced for subscriptionId, resourceGroupName, and storageAccountName.

            #Import Azure PowerShell modules required to make calls to Network Watcher
            Import-Module "D:\home\site\wwwroot\AlertPacketCapturePowerShell\azuremodules\Az.Accounts\Az.Accounts.psd1" -Global
            Import-Module "D:\home\site\wwwroot\AlertPacketCapturePowerShell\azuremodules\Az.Network\Az.Network.psd1" -Global
            Import-Module "D:\home\site\wwwroot\AlertPacketCapturePowerShell\azuremodules\Az.Resources\Az.Resources.psd1" -Global

            #Process alert request body
            $requestBody = Get-Content $req -Raw | ConvertFrom-Json

            #Storage account ID to save captures in
            $storageaccountid = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}"

            #Packet capture vars
            $packetcapturename = "PSAzureFunction"
            $packetCaptureLimit = 10
            $packetCaptureDuration = 10

            #Credentials
            $tenant = $env:AzureTenant
            $pw = $env:AzureCredPassword
            $clientid = $env:AzureClientId
            $keypath = "D:\home\site\wwwroot\AlertPacketCapturePowerShell\keys\PassEncryptKey.key"

            #Authentication
            $secpassword = $pw | ConvertTo-SecureString -Key (Get-Content $keypath)
            $credential = New-Object System.Management.Automation.PSCredential ($clientid, $secpassword)
            Connect-AzAccount -Environment AzureChinaCloud -ServicePrincipal -Tenant $tenant -Credential $credential #-WarningAction SilentlyContinue | out-null

            #Get the VM that fired the alert
            if($requestBody.context.resourceType -eq "Microsoft.Compute/virtualMachines")
            {
                Write-Output ("Subscription ID: {0}" -f $requestBody.context.subscriptionId)
                Write-Output ("Resource Group:  {0}" -f $requestBody.context.resourceGroupName)
                Write-Output ("Resource Name:  {0}" -f $requestBody.context.resourceName)
                Write-Output ("Resource Type:  {0}" -f $requestBody.context.resourceType)

                #Get the Network Watcher in the VM's region
                $networkWatcher = Get-AzResource | Where {$_.ResourceType -eq "Microsoft.Network/networkWatchers" -and $_.Location -eq $requestBody.context.resourceRegion}

                #Get existing packetCaptures
                $packetCaptures = Get-AzNetworkWatcherPacketCapture -NetworkWatcher $networkWatcher

                #Remove existing packet capture created by the function (if it exists)
                $packetCaptures | %{if($_.Name -eq $packetCaptureName)
                { 
                    Remove-AzNetworkWatcherPacketCapture -NetworkWatcher $networkWatcher -PacketCaptureName $packetCaptureName
                }}

                #Initiate packet capture on the VM that fired the alert
                if ((Get-AzNetworkWatcherPacketCapture -NetworkWatcher $networkWatcher).Count -lt $packetCaptureLimit){
                    echo "Initiating Packet Capture"
                    New-AzNetworkWatcherPacketCapture -NetworkWatcher $networkWatcher -TargetVirtualMachineId $requestBody.context.resourceId -PacketCaptureName $packetCaptureName -StorageAccountId $storageaccountid -TimeLimitInSeconds $packetCaptureDuration
                    Out-File -Encoding Ascii -FilePath $res -inputObject "Packet Capture created on ${requestBody.context.resourceID}"
                }
            } 

检索函数 URLRetrieve the function URL

  1. 创建函数后,请将警报配置为调用与该函数相关联的 URL。After you've created your function, configure your alert to call the URL that's associated with the function. 若要获取此值,请从 Function App 中复制函数 URL。To get this value, copy the function URL from your function app.

    查找函数 URL

  2. 复制函数应用的函数 URL。Copy the function URL for your function app.

    复制函数 URL

如果需要在 webhook POST 请求的有效负载中使用自定义属性,请参阅针对 Azure 指标警报配置 webhookIf you require custom properties in the payload of the webhook POST request, refer to Configure a webhook on an Azure metric alert.

在 VM 上配置警报Configure an alert on a VM

可以配置警报,以便在特定的指标超过分配的阈值时通知相关人员。Alerts can be configured to notify individuals when a specific metric crosses a threshold that's assigned to it. 在本示例中,警报是针对 TCP 段发送的,但也可以从其他许多指标触发该警报。In this example, the alert is on the TCP segments that are sent, but the alert can be triggered for many other metrics. 在本示例中,已将某个警报配置为调用 Webhook 来调用函数。In this example, an alert is configured to call a webhook to call the function.

创建警报规则Create the alert rule

转到现有虚拟机,然后添加警报规则。Go to an existing virtual machine, and then add an alert rule. 有关配置警报的更详细文档,请参阅在 Azure Monitor 中为 Azure 服务创建警报 - Azure 门户More detailed documentation about configuring alerts can be found at Create alerts in Azure Monitor for Azure services - Azure portal. 在“警报规则”边栏选项卡中输入以下值,然后选择“确定” 。Enter the following values in the Alert rule blade, and then select OK.

设置Setting Value 详细信息Details
名称Name TCP_Segments_Sent_ExceededTCP_Segments_Sent_Exceeded 警报规则的名称。Name of the alert rule.
说明Description 发送的 TCP 段已超出阈值TCP segments sent exceeded threshold 警报规则的说明。The description for the alert rule.
指标Metric 发送的 TCP 段TCP segments sent 用于触发警报的指标。The metric to use to trigger the alert.
条件Condition 大于Greater than 评估指标时要使用的条件。The condition to use when evaluating the metric.
阈值Threshold 100100 触发警报的指标值。The value of the metric that triggers the alert. 此值应设置为环境的有效值。This value should be set to a valid value for your environment.
时间段Period 过去五分钟Over the last five minutes 确定要在其中查找指标阈值的时间段。Determines the period in which to look for the threshold on the metric.
WebhookWebhook [函数应用中的 Webhook URL][webhook URL from function app] 来自前面步骤创建的函数应用的 Webhook URL。The webhook URL from the function app that was created in the previous steps.

备注

默认情况下不启用 TCP 段计量。The TCP segments metric is not enabled by default. 请访问启用监视和诊断,详细了解如何启用其他指标。Learn more about how to enable additional metrics by visiting Enable monitoring and diagnostics.

查看结果Review the results

在警报触发器条件的后面,会创建一个数据包捕获。After the criteria for the alert triggers, a packet capture is created. 转到网络观察程序,然后选择“数据包捕获”。Go to Network Watcher, and then select Packet capture. 在此页面上,可以选择数据包捕获文件链接,下载数据包捕获。On this page, you can select the packet capture file link to download the packet capture.

查看数据包捕获

如果捕获文件存储在本地,可以通过登录到虚拟机,检索捕获文件。If the capture file is stored locally, you can retrieve it by signing in to the virtual machine.

有关从 Azure 存储帐户下载文件的说明,请参阅通过 .NET 开始使用 Azure Blob 存储For instructions about downloading files from Azure storage accounts, see Get started with Azure Blob storage using .NET. 另一个可以使用的工具是存储资源管理器Another tool you can use is Storage Explorer.

下载捕获后,可以使用能够读取 .cap 文件的任何工具来查看捕获。After your capture has been downloaded, you can view it by using any tool that can read a .cap file. 下面提供了其中两个工具的链接:Following are links to two of these tools:

后续步骤Next steps

访问使用 Wireshark 分析数据包捕获,了解如何查看数据包捕获Learn how to view your packet captures by visiting Packet capture analysis with Wireshark.