本部分介绍如何创建一个 Azure 工作簿,用于显示连接到 Azure 虚拟 WAN 的用户 VPN 客户的相关数据。
若要完成本文中的步骤,需要具有一个虚拟 WAN、一个虚拟中心和一个用户 VPN 网关。 若要创建这些资源,请按照以下文章中的步骤进行操作:创建虚拟 WAN、虚拟中心和网关
为了配置上述体系结构,我们将使用以下 P2S VPN 日志和 PowerShell 命令。
AzureDiagnostics:通过为用户 VPN 网关创建诊断设置并启用以下日志来接收这些日志:GatewayDiagnosticLog、IKEDiagnosticLog、P2SDiagnosticLog 和 AllMetrics。
Get-AzP2sVpnGatewayDetailedConnectionHealth:这是一个 PowerShell 命令(在函数应用中运行),用于获取活动会话详细信息。 此命令仅支持将数据存储在基于 SAS 密钥的存储帐户中,并提供有关活动 P2S VPN 连接的其他详细信息。
- 创建 Azure 存储帐户。
- 创建容器并将 Blob 上传到容器
- Blob 应该是扩展名为 .json 的空文本文件
- 上传 Blob 时,请为帐户密钥授予以下权限:读取、添加、创建和写入。
- 确保将“Blob SAS 令牌”和“Blob SAS URL”复制到安全位置。
创建 Azure 函数应用并选择 PowerShell Core 作为运行时堆栈
通过输入名称和值,创建包含以下 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”设置获取此名称。 在左侧面板中,选择“代码 + 测试”,然后在“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!"
导航回“函数应用”页,在左侧面板中,选择“开发工具”下的“应用服务编辑器”。 然后,选择“转到 --”。
转到“requirements.psd1”,取消注释以 'Az'... 开头的行,如下所示。
若要使 get-AzP2sVpnGatewayDetailedConnectionHealth 命令成功,你需要具有正确的信息权限。 导航到你的资源组,然后在左侧面板中选择“访问控制(IAM)”。 这对应于标识和访问管理。 为 FunctionApp 分配对资源组的读取访问权限。
创建 Azure Key Vault。
- 对于“权限模型”,请选择“保管库访问策略” 。
- 将“资源访问”下的选项保留为“已禁用”。
- 在“访问策略”下,选择“+ 创建”。
- 选择“下一步”以转到“主体”选项卡。键入你的函数应用的名称并选择它。
- 选择两次“下一步”以转到第四个选项卡:“查看 + 创建”,然后选择底部的“创建”。
- 现在,应会在“访问策略”部分下看到新创建的访问策略。 修改“网络”选项卡下的默认值是可选操作,因此,请选择左下角的“查看 + 创建”。
转到密钥保管库资源左侧面板下“对象”下的“机密”。 选择“+ 生成/导入”并添加机密,如下所示:
- 名称:sasuri
- 值:SASURI>
- 已启用:是
返回到函数应用的“配置”选项卡,并修改以下条目。 值来自单击机密后出现的“机密标识符”字段:
- 名称:“sasuri”
- 值:
@Microsoft.KeyVault(SecretUri=https://\<keyvaultname>.vault.azure.cn/secrets/sasuri/<version>)
现已可以创建 Azure 工作簿。 我们将混合使用内置功能以及从我们的函数应用解决方案添加的会话详细信息。
将以下查询添加到工作簿中。 将“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;
若要查看结果,请选择蓝色按钮“运行查询”以查看结果。
如果看到以下错误,请导航回存储容器的 Blob 中的文件 (vpnstatfile.json),并重新生成 SAS URL。 然后将更新的 SAS URL 粘贴到查询中。
保存工作簿,稍后将返回到该工作簿。
以下部分演示了在 Log Analytics 工作区中运行的示例日志查询。
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']
注意
对于其中一些查询,由于隐私原因,用户名可能会被模糊处理。
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]
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;
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
AzureDiagnostics
| where Category == "P2SDiagnosticLog"
| project TimeGenerated, OperationName, Message, Resource, ResourceGroup
| sort by TimeGenerated asc
AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful"
| project TimeGenerated, Resource, Message
AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection failed"
| project TimeGenerated, Resource, Message
AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Connection successful" and Message has "Username={UserName}"| count
AzureDiagnostics
| where Category == "IKEDiagnosticLog"
| project TimeGenerated, OperationName, Message, Resource, ResourceGroup
| sort by TimeGenerated asc
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
AzureDiagnostics
| where Category == "P2SDiagnosticLog" and Message has "Statistics"
| project Message, MessageFields = split (Message, " ")
| mv-expand MessageId=MessageFields[2]
| project MessageId, Message;
若要详细了解常见问题,请参阅虚拟 WAN 常见问题解答页。