如何监视虚拟 WAN 的点到站点连接

本部分介绍如何创建一个 Azure 工作簿,用于显示连接到 Azure 虚拟 WAN 的用户 VPN 客户的相关数据。

准备阶段

若要完成本文中的步骤,需要具有一个虚拟 WAN、一个虚拟中心和一个用户 VPN 网关。 若要创建这些资源,请按照以下文章中的步骤进行操作:创建虚拟 WAN、虚拟中心和网关

工作簿解决方案体系结构

显示工作簿体系结构的屏幕截图。

为了配置上述体系结构,我们将使用以下 P2S VPN 日志和 PowerShell 命令。

  • AzureDiagnostics:通过为用户 VPN 网关创建诊断设置并启用以下日志来接收这些日志:GatewayDiagnosticLog、IKEDiagnosticLog、P2SDiagnosticLog 和 AllMetrics。

  • Get-AzP2sVpnGatewayDetailedConnectionHealth:这是一个 PowerShell 命令(在函数应用中运行),用于获取活动会话详细信息。 此命令仅支持将数据存储在基于 SAS 密钥的存储帐户中,并提供有关活动 P2S VPN 连接的其他详细信息。

创建 Azure 存储帐户并上传 Blob

  1. 创建 Azure 存储帐户
  2. 创建容器并将 Blob 上传到容器
    1. Blob 应该是扩展名为 .json 的空文本文件
    2. 上传 Blob 时,请为帐户密钥授予以下权限:读取、添加、创建和写入
    3. 确保将“Blob SAS 令牌”和“Blob SAS URL”复制到安全位置。

创建 Azure 函数应用

  1. 创建 Azure 函数应用并选择 PowerShell Core 作为运行时堆栈

  2. 向函数应用分配系统分配的托管标识

  3. 通过输入名称创建包含以下 7 个条目的应用程序设置,然后在每个值后选择“确定”。

    名称
    “resourcegroup” 你的资源组
    “sasuri” @Microsoft.KeyVault(SecretUri=https://\<keyvaultname>.vault.azure.cn/secrets/sasuri/<version>)
    -->在下一部分创建 keyvault 后进行相应地更新。
    “subscription” 你的订阅 ID
    “tenantname” 你的租户 ID
    “vpngw” 此名称与 <guid>-chinaeast2-ps2-gw 类似。 可以从“vWAN 中心用户 VPN”设置获取此名称。
  4. 创建计时器触发的函数

  5. 在左侧面板中,选择“代码 + 测试”,然后在“run.ps1”文件中键入以下代码。 选择“保存”。

    # Input bindings are passed in via param block.
    param($Timer)
    
    # Get the current universal time in the default string format.
    $currentUTCtime = (Get-Date).ToUniversalTime()
    
    # The 'IsPastDue' property is "true" when the current function invocation is later than scheduled.
    if($Timer.IsPastDue){
    Write-Host "PowerShell timer is running late!"
    }
    
    ## Write an information log with current time.
    Write-Host "PowerShell timer trigger function ran! TIME:$currentUTCtime"
    
    $tenantname = $env:appsetting_tenantname
    $subscription = $env:appsetting_subscription
    $resourceGroup = $env:appsetting_resourcegroup
    $vpngw = $env:appsetting_vpngw
    $sasuri = $env:appsetting_sasuri
    
    Write-Host "Connecting to Managed Identity..."
    connect-azaccount -tenant $tenantname -identity -subscription $subscription
    
    Write-Host "Executing File Update..."
    Get-AzP2sVpnGatewayDetailedConnectionHealth -name $vpngw -ResourceGroupName $resourceGroup -OutputBlobSasUrl $sasuri
    
    Write-Host "Function Execution Completed!"
    
  6. 导航回“函数应用”页,在左侧面板中,选择“开发工具”下的“应用服务编辑器”。 然后,选择“转到 --”。

  7. 转到“requirements.psd1”,取消注释以 'Az'... 开头的行,如下所示。

    显示函数应用的需求文件的屏幕截图。

  8. 若要使 get-AzP2sVpnGatewayDetailedConnectionHealth 命令成功,你需要具有正确的信息权限。 导航到你的资源组,然后在左侧面板中选择“访问控制(IAM)”。 这对应于标识和访问管理。 为 FunctionApp 分配对资源组的读取访问权限。

创建 Azure Key Vault

  1. 创建 Azure Key Vault

    1. 对于“权限模型”,请选择“保管库访问策略” 。
    2. 将“资源访问”下的选项保留为“已禁用”。
    3. 在“访问策略”下,选择“+ 创建”。

    屏幕截图:创建访问策略时的起始屏幕。

    1. 选择“下一步”以转到“主体”选项卡。键入你的函数应用的名称并选择它。
    2. 选择两次“下一步”以转到第四个选项卡:“查看 + 创建”,然后选择底部的“创建”。
    3. 现在,应会在“访问策略”部分下看到新创建的访问策略。 修改“网络”选项卡下的默认值是可选操作,因此,请选择左下角的“查看 + 创建”。
  2. 转到密钥保管库资源左侧面板下“对象”下的“机密”。 选择“+ 生成/导入”并添加机密,如下所示:

    • 名称:sasuri
    • 值:SASURI>
    • 已启用:是
  3. 返回到函数应用的“配置”选项卡,并修改以下条目。 值来自单击机密后出现的“机密标识符”字段:

    • 名称:“sasuri”
    • @Microsoft.KeyVault(SecretUri=https://\<keyvaultname>.vault.azure.cn/secrets/sasuri/<version>)

创建 Azure 工作簿

现已可以创建 Azure 工作簿。 我们将混合使用内置功能以及从我们的函数应用解决方案添加的会话详细信息。

  1. 导航到你的虚拟 WAN 资源,在左侧面板中,选择“监视”下的“见解”。 选择“工作簿”,然后选择“+ 新建”。 屏幕截图:创建 Azure 工作簿的第一步。

  2. 将以下查询添加到工作簿中。 将“SASURI”替换为你的 sas uri。

     let P2Svpnconnections = (externaldata (resource:string, UserNameVpnConnectionHealths: dynamic) [
         @"SASURI"
     ] with(format="multijson"));
    
     P2Svpnconnections
     | mv-expand UserNameVpnConnectionHealths
     | extend Username = parse_json(UserNameVpnConnectionHealths).UserName
     | extend VpnConnectionHealths = parse_json(parse_json(UserNameVpnConnectionHealths).VpnConnectionHealths)
     | mv-expand VpnConnectionHealths
     | extend VpnConnectionId = parse_json(VpnConnectionHealths).VpnConnectionId, VpnConnectionDuration = parse_json(VpnConnectionHealths).VpnConnectionDuration, VpnConnectionTime = parse_json(VpnConnectionHealths).VpnConnectionTime, PublicIpAddress = parse_json(VpnConnectionHealths).PublicIpAddress, PrivateIpAddress = parse_json(VpnConnectionHealths).PrivateIpAddress, MaxBandwidth = parse_json(VpnConnectionHealths).MaxBandwidth, EgressPacketsTransferred = parse_json(VpnConnectionHealths).EgressPacketsTransferred, EgressBytesTransferred = parse_json(VpnConnectionHealths).EgressBytesTransferred, IngressPacketsTransferred = parse_json(VpnConnectionHealths).IngressPacketsTransferred, IngressBytesTransferred = parse_json(VpnConnectionHealths).IngressBytesTransferred, MaxPacketsPerSecond = parse_json(VpnConnectionHealths).MaxPacketsPerSecond
     | extend PubIp = tostring(split(PublicIpAddress, ":").[0])
     | project Username, VpnConnectionId, VpnConnectionDuration, VpnConnectionTime, PubIp, PublicIpAddress, PrivateIpAddress, MaxBandwidth, EgressPacketsTransferred, EgressBytesTransferred, IngressPacketsTransferred, IngressBytesTransferred, MaxPacketsPerSecond;
    
    
  3. 若要查看结果,请选择蓝色按钮“运行查询”以查看结果。

  4. 如果看到以下错误,请导航回存储容器的 Blob 中的文件 (vpnstatfile.json),并重新生成 SAS URL。 然后将更新的 SAS URL 粘贴到查询中。

    屏幕截图:在工作簿中运行查询时出现的错误。

  5. 保存工作簿,稍后将返回到该工作簿。

查询示例

以下部分演示了在 Log Analytics 工作区中运行的示例日志查询。

P2S 成功连接了 IP

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful" and Message has "Username={UserName}"
| project splitted=split(Message, "Username=")
| mv-expand col1=splitted[0], col2=splitted[1], col3=splitted[2]
| project user=split(col2, " ")
| mv-expand username=user[0]
| project ['user']

注意

对于其中一些查询,由于隐私原因,用户名可能会被模糊处理。

EAP(可扩展身份验证协议)身份验证成功

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "EAP authentication succeeded" and Message has "Username={UserName}"
| project Message, MessageFields = split(Message, " "), Userinfo = split (Message, "Username=")
| mv-expand MessageId=MessageFields[2], user=split(Userinfo[1]," ")
| project MessageId, Message, Userinfo[1]

P2S VPN 用户信息

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Username={UserName}"
| project Message, MessageFields = split(Message, " "), Userinfo = split (Message, "Username=")
| mv-expand MessageId=MessageFields[2], Username=Userinfo[1]
| project MessageId, Message, Username;

每个用户的 P2S VPN 成功连接数

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful"
| project splitted=split(Message, "Username=")
| mv-expand col1=splitted[0], col2=splitted[1], col3=splitted[2]
| project user=split(col2, " ")
| mv-expand username=user[0]
| project-away ['user']
| summarize count() by tostring(username)
| sort by count_ desc

P2S VPN 连接

AzureDiagnostics
| where Category == "P2SDiagnosticLog"
| project TimeGenerated, OperationName, Message, Resource, ResourceGroup
| sort by TimeGenerated asc

成功的 P2S VPN 连接

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful"
| project TimeGenerated, Resource, Message

失败的 P2S VPN 连接

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection failed"
| project TimeGenerated, Resource, Message

按 P2SDiagnosticLog 统计的 VPN 连接计数

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful" and Message has "Username={UserName}"| count

IKEDiagnosticLog

AzureDiagnostics
| where Category == "IKEDiagnosticLog"
| project TimeGenerated, OperationName, Message, Resource, ResourceGroup
| sort by TimeGenerated asc 

其他 IKE 诊断详细信息

AzureDiagnostics
| where Category == "IKEDiagnosticLog"
| extend Message1=Message
| parse Message with * "Remote " RemoteIP ":" * "500: Local " LocalIP ":" * "500: " Message2
| extend Event = iif(Message has "SESSION_ID", Message2, Message1)
| project TimeGenerated, RemoteIP, LocalIP, Event, Level
| sort by TimeGenerated asc

P2S VPN 统计信息

AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Statistics"
| project Message, MessageFields = split (Message, " ")
| mv-expand MessageId=MessageFields[2]
| project MessageId, Message;

后续步骤

若要详细了解常见问题,请参阅虚拟 WAN 常见问题解答页。