这是本节的多页面打印视图。 单击此处打印.

返回此页的常规视图.

使用示例

这里你可以找到在实际场景中如何使用该模块的实用示例。这些示例旨在帮助你理解如何应用模块的功能。

这些示例提供了更多的深度和背景。如果你只想了解模块命令的用法,请查看命令参考

1 - 域环境中的实际应用(基于 GPO 的收集与转换)

本示例演示如何在域控制器上实现基于 GPO 的 DNS 调试日志收集与转换工作流。

本文档概述了在 Active Directory 域环境中运行 DNSServer.DebugLogParser 的一个实际端到端示例,重点是转换域控制器上的 Windows DNS 服务器调试日志。

本示例附带一个 ZIP 压缩包,其中包含用于实现本文描述工作流的策略工件。
最相关的工件包括 备份清单GPO 报告Files.xmlSet-DNSServerDebugLogging.ps1 以及 ScheduledTasks.xml

场景

  • 多个域控制器(DC)承载 DNS 服务器角色。
  • 通过计划任务在每个 DC 上启用并统一配置 DNS 调试日志(日志文件写入路径为 C:\Administration\Logs\DNSServer)。
  • 集中管理的进程将日志转换为 CSV,用于:
    • 安全分析
    • 运营报告
    • 故障排查
    • 合规/保留

目标结果

  • 所有 DC 上的转换设置保持一致
  • 输出位置和命名可预测
  • 可选压缩以减少存储占用
  • 可选统计输出以实现快速的每日汇总
  • 主机端风险最小,明确重跑和清理策略

建议架构

收集模型:本地转换 + 中央拉取

  1. 每个 DC 将 DNS 调试日志写入磁盘,并启用日志轮转。
  2. 每个 DC 将轮转的 *.log 文件转换成数据 CSV 和统计 CSV,然后通过计划任务压缩输出为 *.zip
  3. 输出文件与日志文件写在同一目录,简化管道流程。
  4. 中央服务器收集 *.zip 输出,例如通过文件共享导入、定时复制、SIEM 转发器或基于代理的收集器。

该模型最大限度减少了对大型原始日志文件的网络读取,将解析工作保持在数据近旁。

GPO 工作流

该工作流通过组策略(计算机配置)实现,确保所有域控制器的设置一致。

本仓库中包含参考实现(GPO 报告):

  • 归档/报告名称:T0-C-Analytics-DNSDebugLogging
  • 备份 ID:{2B6F16BC-0E7C-4787-83D7-2854FED882EE}
  • GPO 目标链接:corp.company.com/Domain Controllers
  • 项目筛选器(用于文件部署和计划任务):仅当存在 C:\Windows\System32\dns.exe 时应用

1) 前置条件(文件夹 + 模块)

提供的备份假定以下文件夹已存在。如果希望部署时自动创建,请添加单独的 GPP 项目:

  • C:\Administration\Scripts
  • C:\Administration\Logs\DNSServer

备份还假定 Convert-DNSDebugLogFile 模块已在 DC 上可用。转换任务启动 Windows PowerShell 5.1,使用 -NoProfile,且不显式导入模块,因此模块必须安装在对 LocalSystem 可见的机器范围 Windows PowerShell 模块路径中。推荐做法:

  • 在 DC 上安装 DNSServer.DebugLogParser,例如从 PowerShell Gallery(如果策略允许)。
  • 通过内部仓库或文件共享部署模块,使其可在 $env:PSModulePath 中被发现。
  • 如果需要确定性加载行为,可在任务动作中显式添加 Import-Module

2) 部署调试日志配置脚本(GPP 文件)

GPO 部署以下脚本:

  • 源(SYSVOL 中的 GPP):%GptPath%\Preferences\Files\Set-DNSServerDebugLogging.ps1
  • 目标(每个 DC 上):C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1

此项在 Files.xml 的 GPP 文件首选项中实现。

3) 计划任务:配置 DNS 调试日志

GPO 创建名为 Set-DNSServerDebugLogging 的计划任务。

  • 备份中安全上下文:SYSTEM,登录类型为 S4U
  • 备份中触发器:每日(起始时间 2025-03-01T00:00:01
  • 动作在 ScheduledTasks.xml 中:
    • powershell.exe -ExecutionPolicy RemoteSigned -command " & { C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1 }"
    • 工作目录:C:\Administration\Scripts

链接的 Set-DNSServerDebugLogging.ps1 脚本通过 Get-DnsServerDiagnostics / Set-DnsServerDiagnostics 配置 DNS 调试日志,重点包括:

  • 启用文件日志及轮转
  • 写入路径:C:\Administration\Logs\DNSServer\DnsDebugLog_<COMPUTERNAME>.<Domain>_.log
  • 每个文件轮转大小为 10 MB
  • 主要捕获查询相关活动(查询、通知、更新、查询事务),排除完整数据包日志

4) 计划任务:转换轮转的调试日志为压缩 CSV

GPO 创建名为 Convert-DNSDebugLogs 的计划任务。

  • 备份中安全上下文:SYSTEM,登录类型为 InteractiveToken
  • 备份中触发器:每日(起始时间 2026-01-01T00:30:00
  • 工作目录:C:\Administration\Logs\DNSServer
  • 动作在 ScheduledTasks.xml(格式化以便阅读):
Get-ChildItem .\*.log |
  Sort-Object lastwritetime, Name -Descending |
  Select-Object -Skip 1 |
  Convert-DNSDebugLogFile `
    -ComputerName $env:COMPUTERNAME `
    -Delimiter ';' `
    -OutputType Both `
    -ContextFilter Packet `
    -OutputCulture sv-SE `
    -CompressOutput

设计说明:

  • Select-Object -Skip 1 有意跳过最新(活动)日志文件。
  • 这意味着当前数据仅在轮转后导出;在低流量 DC 上,活动日志可能超过一天未处理。
  • 由于 Convert-DNSDebugLogFile 默认 -OutputFile 为“同一文件夹,同名,扩展名为 .csv”,输出文件与 *.log 输入文件并列。
  • 使用 -CompressOutput 时,每个处理的日志生成一个 *.zip,并删除中间 CSV 文件。
  • 除非归档或删除已处理的 *.log 文件,否则后续运行会再次处理所有非活动日志。
  • 任务在 $Error.Count -gt 0 时抛出异常,表示运行失败。

5) 中央采集

选项(任选其一):

  • 文件共享采集:DC 写入(或复制)C:\Administration\Logs\DNSServer\*.zip\\fileserver\share\dns\$env:COMPUTERNAME\...(为 DC 计算机账户或域控制器组授予共享和 NTFS 权限,若任务以 SYSTEM 运行)
  • 拉取模型:中央作业读取 \\dc\C$\Administration\Logs\DNSServer\*.zip(最不推荐,需管理员共享)
  • 代理转发:SIEM / 日志管道转发 *.zip 输出

运营注意事项

  • 最小权限:任务以 SYSTEM 运行;确保本地文件夹可写,且任何 UNC 目标对计算机账户开放访问(如使用)。
  • 签名策略:两个任务均使用 -ExecutionPolicy RemoteSigned;根据策略签署或解除阻止部署的脚本和模块。
  • 磁盘使用:-CompressOutput 显著减少空间,但该工作流不删除源日志;请规划保留和清理策略。
  • 重复处理行为:除非归档或删除已处理的日志,转换任务会在后续运行时再次处理所有非活动 *.log 文件。此方法简单且稳健,但可能覆盖输出并在收集器不去重时产生重复数据。
  • 多 DC 合并:包含 -ComputerName $env:COMPUTERNAME,确保合并数据集可追溯。
  • 验证:头部验证保持启用,因为任务未使用 -SkipHeaderValidation(推荐做法)。

使用 ZIP 进行验证和调整

使用 ZIP 压缩包 作为参考实现,然后根据环境调整以下方面:

  • 目标范围:哪些 DC / OU 接收该策略
  • 执行身份:确认两个计划任务使用预期的登录类型(S4UInteractiveToken),或统一为标准
  • 文件夹创建:决定是否预先创建 C:\Administration\ScriptsC:\Administration\Logs\DNSServer,或由额外 GPP 项目创建
  • 路径:确认 C:\Administration\ScriptsC:\Administration\Logs\DNSServer 符合标准
  • 保留:决定是否保留原始日志及保留时长(尤其启用清理选项时)
  • 采集:确认 CSV/ZIP 输出的写入位置及中央采集方式

如果想在不导入的情况下验证 GPO 配置,仓库中的权威资源包括:

2 - 使用 SQL Server 的安全分析工作流

使用 DNSServer.DebugLogParser 将 DNS 调试日志转换为 CSV,导入 SQL Server, 并运行简单查询检测可疑的 TXT 记录活动。

此示例展示了一个实用的安全分析工作流:使用 Convert-DNSDebugLogFile 解析 DNS 调试日志,将生成的 CSV 导入 SQL Server,并运行查询以突出显示异常大量的 TXT 记录查询。

为了最佳的互操作性,此示例通过使用 -OutputCulture 'sv-SE' 以类似 ISO 的格式写入时间戳。

所需模块

此示例使用以下 PowerShell 模块:

  • DNSServer.DebugLogParser
  • SqlServer

如有需要,请安装它们:

Install-Module -Name DNSServer.DebugLogParser -Scope CurrentUser
Install-Module -Name SqlServer -Scope CurrentUser

场景

当你想将解析后的 DNS 调试日志数据移入 SQL Server,以便你可以:

  • 高效搜索大数据集
  • 构建可重复使用的检测查询
  • 关联多个 DNS 服务器的活动
  • 保留规范化数据以供后续调查

时,请使用此工作流。

转换步骤的输出

Convert-DNSDebugLogFile 不直接写入 SQL Server。它首先创建一个 CSV 文件。该 CSV 文件即为导入数据库的数据集。

在此示例中:

  • 输入日志:C:\Administration\Logs\DNS\dns.log
  • 生成的 CSV:C:\Administration\Logs\DNS\dns.csv
  • 目标表:dbo.DNSQueries

创建目标表

在 SQL Server 中运行以下语句一次,创建目标表。

IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END;

转换日志并导入 CSV

以下 PowerShell 示例执行完整工作流:

  1. 导入所需模块
  2. 将 DNS 调试日志转换为 CSV
  3. 加载生成的 CSV
  4. 批量导入行到 SQL Server
# Requires -Modules DNSServer.DebugLogParser, SqlServer

Import-Module -Name DNSServer.DebugLogParser -ErrorAction Stop
Import-Module -Name SqlServer -ErrorAction Stop

$logPath = 'C:\Administration\Logs\DNS\dns.log'
$csvPath = 'C:\Administration\Logs\DNS\dns.csv'
$serverInstance = 'SQLServer'
$databaseName = 'DNSLogs'
$delimiter = ';'

$createTableSql = @'
IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END
'@

Convert-DNSDebugLogFile `
    -InputFile $logPath `
    -ComputerName 'DNS01' `
    -OutputType CSV `
    -OutputFile $csvPath `
    -Delimiter $delimiter `
    -OutputCulture 'sv-SE'

$rows = Import-Csv -Path $csvPath -Delimiter $delimiter

if (-not $rows) {
    throw "生成的 CSV 文件 '$csvPath' 不包含任何行。"
}

$dataTable = [System.Data.DataTable]::new()
foreach ($columnName in $rows[0].PSObject.Properties.Name) {
    $null = $dataTable.Columns.Add($columnName, [string])
}

foreach ($row in $rows) {
    $dataRow = $dataTable.NewRow()
    foreach ($column in $dataTable.Columns) {
        $columnName = $column.ColumnName
        $dataRow[$columnName] = $row.$columnName
    }

    $null = $dataTable.Rows.Add($dataRow)
}

$connectionString = "Server=$serverInstance;Database=$databaseName;Integrated Security=True"
$connection = [System.Data.SqlClient.SqlConnection]::new($connectionString)

try {
    $connection.Open()

    $command = $connection.CreateCommand()
    $command.CommandText = $createTableSql
    $null = $command.ExecuteNonQuery()

    $bulkCopy = [System.Data.SqlClient.SqlBulkCopy]::new($connection)
    $bulkCopy.DestinationTableName = 'dbo.DNSQueries'

    foreach ($column in $dataTable.Columns) {
        $null = $bulkCopy.ColumnMappings.Add($column.ColumnName, $column.ColumnName)
    }

    $bulkCopy.WriteToServer($dataTable)
}
finally {
    $connection.Dispose()
}

查询可疑的 TXT 记录活动

数据进入 SQL Server 后,你可以搜索发出异常大量 TXT 记录查询的客户端。

SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;

如果你更喜欢从 PowerShell 运行查询,可以使用 SqlServer 模块中的 Invoke-Sqlcmd

$query = @'
SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;
'@

Invoke-Sqlcmd `
    -ServerInstance 'SQLServer' `
    -Database 'DNSLogs' `
    -Query $query

为什么 TXT 查询很有意义

大量的 TXT 记录查询值得关注,因为它们可能表明:

  • DNS 隧道
  • 通过 DNS 进行数据外泄
  • 恶意软件或工具滥用 TXT 记录
  • 异常嘈杂或配置错误的客户端

此查询只是一个起点。在生产环境中,你应调整阈值并添加符合你环境的过滤条件。

运行注意事项

  • Import-Csv 会将整个文件读入内存。对于非常大的日志导出,考虑使用流式处理而非构建完整的 DataTable
  • 在转换步骤中保留 -ComputerName,以便在集中摄取后仍能归属记录。
  • 导出和导入时使用一致的分隔符和文化设置。
  • 在将此工作流用于长期存储前,验证 SQL Server 中的保留策略、索引和访问控制。

3 - 计划任务示例

本示例演示如何创建一个 Windows 计划任务,该任务每天运行一个 PowerShell 脚本来处理 DNS 调试日志。

此脚本创建了一个每天凌晨 2:00 运行的 Windows 计划任务。它导入模块并处理脚本执行所在文件夹中的所有日志文件(本例中为 “C:\Administration\Logs\DNS”)。该过程会将输出压缩成 ZIP 文件,并删除原始文件以保持整洁。

$actionParams = @{
    Execute = "powershell.exe"
    Argument = '-ExecutionPolicy RemoteSigned -Command "Import-Module DNSServer.DebugLogParser; Get-ChildItem .\*.log | Sort-Object lastwritetime, Name -Descending | Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME -Delimiter \";\" -OutputType Both -ContextFilter Packet -OutputCulture sv-SE -CompressOutput"'
    WorkingDirectory = "C:\Administration\Logs\DNS"
}
$Action = New-ScheduledTaskAction @actionParams

$Trigger = New-ScheduledTaskTrigger -Daily -At "2:00AM"

Register-ScheduledTask -TaskName "Process DNS Logs" -Action $Action -Trigger $Trigger -Description "Convert DNS debug logs to CSV daily"