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

返回此页的常规视图.

使用示例

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

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

1 - 使用 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 中的保留策略、索引和访问控制。

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

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

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

本示例附带一个 ZIP 压缩包,其中包含用于实现本文所述工作流的策略工件。
最相关的工件包括 备份清单GPO 报告Files.xmlSet-DNSServerDebugLogging.ps1ScheduledTasks.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 有意跳过最新(活动)日志文件。Convert-DNSDebugLogFile 能读取 DNS 服务器当前打开的日志,但该文件在读取时会变化:输出可能缺失最新条目或以截断记录结尾,两次运行结果不一致。跳过活动文件保证计划输出可复现。
  • 这意味着当前数据仅在轮换后导出;在低流量 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,确保合并数据集可追溯。注意 -ComputerName 仅标记输出,不执行远程连接。
  • 网络共享:Convert-DNSDebugLogFile 可读取 SMB/UNC 路径的源日志,但本地转换并传输压缩结果是处理大型原始日志的更佳方案。如果使用 UNC 路径,记住以 SYSTEM 运行的任务在网络上以计算机账户身份认证,需要共享和 NTFS 权限。
  • 日期格式:故意使用 -OutputCulture sv-SE,使时间戳写为 2026-01-20 23:00:16。该格式被 SQL Server、Power BI 及大多数导入工具无提示识别,无论生成日志的 DC 区域设置如何。
  • 验证:保持启用标题验证,因为任务未使用 -SkipHeaderValidation(推荐做法)。

使用 ZIP 进行验证和调整

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

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

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

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"