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

返回此页的常规视图.

关于本说明文档

这是 DNSServer.DebugLogParser 的官方文档站点,这是一个 PowerShell 模块,用于将 Windows DNS 服务器调试日志文件转换为结构化、可分析的 CSV 数据。

关于该模块

DNSServer.DebugLogParser 源于一个现实需求:Windows DNS 服务器调试日志是人类可读的文本,但不适合进行分析或报告。该模块弥合了这一差距,将原始日志文件转换为结构化的 CSV 格式,可与 Excel、Power BI、SQL 数据库和 SIEM 系统等常用工具集成。

主要设计原则:

  • 性能优先 — 使用流式 I/O 和字符串操作,针对 100MB 以上文件进行优化
  • 跨版本兼容 — 支持 PowerShell Desktop (5.1+) 和 Core (7.x)
  • 生产就绪 — 包含头部验证、错误处理和可选压缩功能
  • 管道友好 — 自然集成 PowerShell 的管道架构

资源

贡献

欢迎贡献。如果你发现问题、错误或有改进建议,请在 GitHub 仓库 上提交 issue 或 pull request。

1 - 概述

DNSServer.DebugLogParser 是一个 PowerShell 模块,可将 Windows DNS 服务器调试日志文件转换为结构化、可分析的 CSV 数据,用于安全分析、性能监控、故障排除和合规报告。

什么是 DNS 调试日志?

DNS 调试日志是 Windows DNS 服务器的一项功能,用于记录有关 DNS 操作的详细信息。启用后,DNS 服务器会将日志条目写入文本文件(通常为 dns.log),该文件位于 DNS 服务器的目录中。

每条日志记录包含最多 16 个字段,包括:

  • 查询的日期和时间
  • 使用的协议(UDP 或 TCP)
  • 方向(发送或接收)
  • 客户端 IP 地址
  • 查询类型(A、AAAA、MX、PTR 等)
  • 查询的域名
  • 响应代码(NOERROR、NXDOMAIN 等)
  • 查询标志和选项
  • 响应中的 IP 地址(针对成功查询)
  • 端口号及其他技术细节

为什么要解析 DNS 调试日志?

DNS 日志对于以下方面至关重要:

故障排除

  • 诊断名称解析失败
  • 识别配置错误的客户端或应用程序
  • 追踪问题查询的来源
  • 验证正确的 DNS 配置和区域传送

性能监控

  • 识别高流量查询来源
  • 分析查询类型和模式以优化 DNS 基础设施
  • 发现导致查询过多的配置问题
  • 跟踪响应时间和成功率
  • 监控 DNS 服务器负载和容量

安全分析

  • 发现 DNS 隧道和数据外泄尝试
  • 识别与恶意软件及命令与控制服务器相关的域名
  • 跟踪可能表明系统被攻陷的可疑查询模式
  • 监控 DNS 放大攻击
  • 调查安全事件并追踪攻击者活动

合规与审计

  • 满足日志记录和保留的法规要求
  • 记录网络活动以备审计
  • 为管理层和合规官生成报告
  • 展示安全监控的尽职调查

模块工作原理(高层次)

该模块针对大文件进行了优化,将 DNS 调试日志处理为结构化的 CSV 输出。它支持多行记录(例如 PACKET 详细信息块和缩进的续行),确保事件/诊断消息和数据包详细信息附着在正确的记录上。

主要功能:

  • 解析原生 DNS 调试日志字段,生成一致的 CSV 布局
  • 支持多个 DNS 服务器版本(2012 R2 到 2025)
  • 支持 PowerShell Desktop(5.1+)和 Core(7.x)
  • 处理任意大小的文件(已测试 100MB+ 文件)
  • 验证日志文件头以确保数据完整性
  • 生成可选的统计摘要
  • 支持通过 PowerShell 管道批量处理
  • 可选压缩输出文件以节省磁盘空间
  • 可在成功处理后自动删除源文件
  • 支持国际 DNS 服务器日志的文化感知日期解析
  • 支持国际输出需求的文化感知日期格式化

许可与支持

该模块采用 MIT 许可证发布。社区支持通过 GitHub Issues 提供。

  • GitHub 仓库:https://github.com/AndiBellstedt/DNSServer.DebugLogParser
  • PowerShell Gallery:https://www.powershellgallery.com/packages/DNSServer.DebugLogParser

2 - 输出格式

DNSServer.DebugLogParser 可以生成两种类型的输出:

  • 包含所有解析条目的 CSV 数据文件
  • 用于每日汇总的可选统计文件

要查看每种输出类型的实际示例,请查看本文中的示例。

CSV 数据文件

示例输出文件:

CSV 数据文件包含所有解析的日志条目,包含以下列:

  • DateTime:DNS 查询/响应的日期和时间
  • ThreadId:内部 DNS 服务器线程标识符
  • Context:操作上下文(例如 Packet、Event、Note、DSPoll、Init、Lookup、Recurse、Remote、Tombstone)
  • PacketId:DNS 数据包标识符
  • Protocol:UDP 或 TCP
  • DirectionRcv(接收/查询)或 Snd(发送/响应)
  • ClientIP:客户端 IP 地址
  • Xid:事务 ID(十六进制)
  • Type:查询或响应
  • Opcode:Standard、Notify、Update 或 Unknown
  • FlagsHex:查询/响应标志(十六进制)
  • FlagsChar:标志解码(权威、截断、递归请求、递归可用)
  • ResponseCode:NOERROR、NXDOMAIN、SERVFAIL 等
  • QuestionType:DNS 记录类型(A、AAAA、MX、PTR 等)
  • QuestionName:查询的域名
  • Information:附加信息(针对 Event/Note 等;针对数据包详细块,包含 TCP/UDP 详细头行)
  • Details:包含详细块的数据包条目的 JSON 数据(否则为空)
  • ComputerName:源服务器名称(始终存在;未指定时为空)

注意:ComputerName 列始终包含在每条记录的末尾,以确保输出结构一致。这有助于多服务器日志合并场景。

统计文件(可选)

示例输出文件:

生成统计时,会创建两个独立的文件:

1) 上下文统计(*_Statistic.csv

列:

  • Date:日期(yyyy-MM-dd
  • Context:上下文名称(例如 Packet、Event、Note)
  • Count:记录数量
  • ComputerName:源服务器名称

2) 数据包统计(*_PacketStatistic.csv

列:

  • Date:日期(yyyy-MM-dd
  • ClientIP:客户端 IP 地址
  • Protocol:UDP 或 TCP
  • DirectionRcvSnd
  • QuestionType:DNS 记录类型
  • Count:记录数量
  • ComputerName:源服务器名称

3 - 运营最佳实践

在生产环境中使用 DNSServer.DebugLogParser 时:

  1. 定期安排处理

    • 使用任务计划程序自动每日或每周转换新的日志文件。
  2. 适当轮换日志

    • DNS 调试日志可能快速增长;配置在可管理的大小轮换(例如 100MB)。
  3. 验证输出

    • 在完全自动化之前,先验证前几个转换的文件。
  4. 规划存储需求

    • 即使有压缩,也要根据 DNS 流量和保留时间规划存储。
  5. 保护敏感数据

    • DNS 日志可能包含敏感信息;使用适当的访问控制保护输出。
  6. 记录工作流程

    • 记录处理计划、存储位置和分析用途。
  7. 使用样本文件测试

    • 在处理关键日志前,验证参数和输出格式。
  8. 监控错误

    • 注意日志损坏、访问问题或磁盘空间不足。

4 - 故障排除

常见问题及解决方案

“该文件不是有效的 DNS 调试日志文件”

  • 确保你正在转换的是实际的 DNS 服务器调试日志。
  • 文件应以 Message logging started at 开头或包含 DNS 查询条目。
  • 如果你确定文件有效但头部不同,请使用 -SkipHeaderValidation

输出文件为空或不完整

  • 确认输入文件包含有效的日志条目。
  • 如果没有发生查询,有些日志可能只包含头部信息。
  • 验证日志文件未损坏且包含实际的查询数据。

处理速度非常慢

  • 确保有足够的内存且磁盘负载不高。
  • 考虑处理较小的日志文件。
  • 考虑使用 -CompressOutput 并结合计划任务处理较小批次。

“访问被拒绝”错误

  • 以具有读取源日志文件和写入目标目录权限的身份运行 PowerShell。
  • DNS 日志文件可能需要管理员权限。

压缩后的输出文件比预期大

  • 含有许多唯一值的日志压缩效率较低;这是正常现象。
  • ZIP 压缩通常仍能大幅减小文件大小。

统计文件与预期不符

  • 确认你使用了 -OutputType Both-OutputType Statistic
  • 统计数据是汇总计数(按天分组),因此值表示总计。

报告问题

如果遇到此处未涵盖的问题:

  1. 确认你使用的是模块的最新版本。
  2. 检查 GitHub Issues 是否有类似问题。
  3. 收集诊断信息:
    • PowerShell 版本($PSVersionTable
    • 模块版本(Get-Module DNSServer.DebugLogParser
    • 示例日志文件(如果可能)
    • 完整的错误信息和堆栈跟踪
  4. 在 GitHub 上新建 issue 并提供详细信息。

5 - 模块命令参考

在这里,你可以找到模块中所有命令的参考资料。此参考旨在帮助你快速找到所需命令,并了解如何有效使用它。

点击命令后,你将进入一个详细页面,提供该命令的全面信息,包括语法、参数、示例以及任何额外的使用说明或技巧。

5.1 - Convert-DNSDebugLogFile

SYNOPSIS

将 Windows DNS 服务器调试日志转换为结构化的 CSV 格式,便于分析和报告。

SYNTAX

__AllParameterSets

Convert-DNSDebugLogFile [-InputFile] <string[]> [[-OutputFile] <string>] [[-Delimiter] <string>]
 [[-ComputerName] <string>] [[-OutputType] <string>] [[-ContextFilter] <string[]>]
 [[-InputCulture] <cultureinfo>] [[-OutputCulture] <cultureinfo>] [-SkipHeaderValidation]
 [-RemoveSourceFile] [-CompressOutput] [-NoDetailsParsing] [-WhatIf] [-Confirm] [<CommonParameters>]

ALIASES

此 cmdlet 具有以下别名,

DESCRIPTION

将 Windows DNS 服务器调试日志文件转换为结构化的 CSV 数据,可在 Excel、Power BI、SQL 数据库或 SIEM 工具中进行分析。
设计用于安全分析、性能监控、故障排除和合规报告。

该 cmdlet 解析 DNS 调试日志并输出一致的 CSV 格式以供分析。
CSV 输出包含 18 列,包括用于事件/诊断文本的 Information 列、可选的用于数据包详细信息块的 JSON 格式 Details 列,以及始终存在的 ComputerName 列(除非指定,否则为空)。

主要特性:

  • 流式处理,避免将整个文件加载到内存(适合超大日志)
  • 针对大文件(100MB+)优化的高性能解析
  • 可自定义 CSV 分隔符(默认分号)
  • 可选的统计汇总,包含聚合指标
  • 上下文过滤(数据包、事件、注释及其他上下文),聚焦特定日志条目类型
  • 支持文化感知的日期解析和格式化,适用于国际服务器
  • 支持管道批量处理多个文件
  • 可选输出文件压缩(ZIP 格式)
  • 可选处理后自动删除源文件
  • 头部验证确保数据完整性

输出格式:
ComputerName 列始终包含在每条记录末尾。
如果未指定 -ComputerName 参数,该列为空。
确保多服务器合并场景下输出结构一致。

性能:
使用 StreamReader/StreamWriter 64KB 缓冲区优化,流式处理实现内存高效,使用字符串操作替代正则表达式,手动生成 CSV,基于哈希表高效收集统计数据。

兼容性:

  • PowerShell 5.1+(桌面版和核心版)
  • Windows Server 2016+
  • 支持 DNS Server 2012 R2 至 2025 日志格式

EXAMPLES

示例 1

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log"

使用默认设置转换 DNS 调试日志(数据文件和统计文件均用分号分隔符)。
输出:

  • C:\Logs\dns.csv
  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

示例 2

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputType CSV

仅生成数据文件,不生成统计文件。
输出:C:\Logs\dns.csv

示例 3

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputType Statistic

仅生成带聚合指标的统计文件。
输出:

  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

示例 4

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputFile "C:\Output\parsed.csv"

将日志转换到自定义输出位置。
输出:C:\Output\parsed.csv

示例 5

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -Delimiter "," -ComputerName "DNS01" -OutputType Both

使用逗号分隔符转换,并添加值为 “DNS01” 的 ComputerName 列。
输出:

  • C:\Logs\dns.csv
  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

示例 6

PS C:\> Get-ChildItem "C:\Logs\*.log" | Convert-DNSDebugLogFile -OutputType Both

通过管道批量处理多个 DNS 调试日志文件。
输出:每个 .log 文件生成对应的 .csv 和 _statistic.csv 文件

示例 7

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -CompressOutput

转换并压缩输出为 ZIP 归档。
输出:C:\Logs\dns.zip(包含 dns.csv 及统计文件)

示例 8

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -RemoveSourceFile -Verbose

转换日志并在成功处理后删除源文件。
详细输出确认文件已删除。

示例 9

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -InputCulture 'de-DE' -OutputCulture 'en-US'

解析德国日期格式(DD.MM.YYYY),输出为美国格式(MM/DD/YYYY)。
适用于处理来自不同区域设置服务器的日志。

示例 10

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter 'Packet'

仅转换 DNS 查询/响应数据包条目,排除 EVENT 和 Note 条目。
用于聚焦实际 DNS 流量分析。

示例 11

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter 'Packet','Event'

转换 DNS 查询/响应数据包和服务器事件,排除 Note 及其他条目。
用于分析 DNS 流量及服务器事件上下文。

示例 12

PS C:\> Get-ChildItem "C:\Logs\*.log" | Convert-DNSDebugLogFile -RemoveSourceFile -CompressOutput

自动化日志归档:处理所有日志,压缩输出,并删除源文件。
适合计划任务的日志处理流水线。

示例 13

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\large-dns.log" -NoDetailsParsing

处理大型日志文件,禁用详细解析以获得最大性能。
跳过 PACKET 详细块,Details 列保持为空。
适用于处理非常大文件且不需要详细数据包结构的场景。

PARAMETERS

-CompressOutput

在创建后将输出的 CSV 文件压缩为 ZIP 归档。

创建一个包含生成的 CSV 文件的 .zip 文件,然后删除未压缩的 CSV 文件。
ZIP 文件与输出 CSV 位于同一目录,使用相同的基本文件名。

优点:

  • 显著减少磁盘空间(CSV 文件通常压缩率超过 90%)
  • 简化文件管理和归档
  • 适合长期存储

示例:输入 ‘dns.log’ 生成 ‘dns.csv’,压缩为 ‘dns.zip’,然后删除 ‘dns.csv’。

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-ComputerName

指定 CSV 输出中 ComputerName 列的值。
ComputerName 列始终存在于输出中——如果未指定此参数,该列为空。

合并来自多个 DNS 服务器的日志时,使用此参数标识源服务器。

注意:这不是远程参数。
它仅用于标记输出。
如果 -InputFile 指向 UNC 路径,文件将直接从该路径读取(不执行 WinRM/远程操作)。

Type: String
DefaultValue: ''
SupportsWildcards: false
Aliases:
- Server
- DNSServer
- HostName
ParameterSets:
- Name: (All)
  Position: 3
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-Confirm

在运行 cmdlet 前提示确认。

指定后,会在以下操作前提示确认:

  • 处理每个 DNS 调试日志文件
  • 删除源文件(当指定 -RemoveSourceFile 时)
  • 覆盖已存在的输出文件

适合交互式处理时控制处理文件。

Type: SwitchParameter
DefaultValue: ''
SupportsWildcards: false
Aliases:
- cf
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-ContextFilter

过滤输出中包含的日志条目类型。
支持单个或多个值。

DNS 调试日志包含不同上下文类型:

  • PACKET:DNS 查询和响应数据包信息(主要数据)
  • EVENT:DNS 服务器事件(例如,“DNS 服务器已启动。”)
  • Note:诊断注释和警告(例如,套接字错误、内部状态)
  • DSPoll、Init、Lookup、Recurse、Remote、Tombstone:其他上下文类型

有效值:

  • ‘All’:包含所有上下文类型(默认)
  • ‘Packet’:仅包含 PACKET 条目(DNS 查询/响应)
  • ‘Event’:仅包含 EVENT 条目(服务器事件)
  • ‘Note’:仅包含 Note 条目(诊断信息)
  • 任意组合:指定多个值以包含特定上下文类型

默认:All

示例:

  • ‘Packet’ 仅过滤 DNS 流量
  • ‘Packet’,‘Event’ 包含 DNS 流量和服务器事件
  • ‘Note’,‘Event’ 包含诊断注释和服务器事件

注意:过滤为 ‘Event’ 或 ‘Note’ 时,仅 DateTime、ThreadId、Context 和 Information 列有数据,其他列(Protocol、ClientIP 等)为空。

Type: String[]
DefaultValue: "@('All')"
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 5
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-Delimiter

指定 CSV 输出的分隔符字符。

默认:分号(;)

常用替代:逗号(,)、制表符(`t)、管道符(|)

在使用逗号作为小数点分隔符的地区(欧洲)使用分号。
对于标准 CSV 工具和数据库,使用逗号分隔。

Type: String
DefaultValue: ;
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 2
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-InputCulture

指定用于解析 DNS 调试日志中日期/时间值的文化/区域设置。

DNS 服务器调试日志使用生成日志的服务器 Windows 区域设置的日期格式。
处理来自不同区域设置服务器的日志时使用此参数。

默认:当前文化

常见示例:

  • ‘de-DE’ 或 ‘de-AT’:德国格式(DD.MM.YYYY 或 DD/MM/YYYY)
  • ’en-US’:美国格式(MM/DD/YYYY,含 AM/PM)
  • ’en-GB’:英国格式(DD/MM/YYYY,24 小时制)
  • ‘sv-SE’:瑞典/ISO 格式(YYYY-MM-DD)
Type: CultureInfo
DefaultValue: '[System.Globalization.CultureInfo]::CurrentCulture'
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 6
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-InputFile

指定要解析的 DNS 调试日志文件路径。
支持数组以处理多个文件。

支持从 Get-ChildItem 或其他生成文件的 cmdlet 管道输入。

Type: String[]
DefaultValue: ''
SupportsWildcards: false
Aliases:
- FullName
- FilePath
- InputPath
- File
- Path
ParameterSets:
- Name: (All)
  Position: 0
  IsRequired: true
  ValueFromPipeline: true
  ValueFromPipelineByPropertyName: true
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-NoDetailsParsing

跳过将 PACKET 详细块解析为结构化 JSON 格式。

指定后,包含详细块的 PACKET 记录将在 Information 列显示 TCP/UDP 信息行,但 Details 列保持为空。
这显著提升处理大型日志文件时的性能,适用于不需要详细数据包结构分析的场景。

使用场景:

  • 处理非常大(100MB+)日志文件,只需基本查询信息
  • 不需要详细结构(消息标志、DNS 区段)分析
  • 优先提升解析速度而非数据完整性

性能影响:对于包含大量 PACKET 详细块的日志,处理速度可提升 30-50%。

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputCulture

指定用于格式化输出 CSV 文件中日期/时间值的文化/区域设置。

控制 DateTime 值写入 CSV 的格式。
当 CSV 文件将被特定区域设置的应用程序或系统使用时,使用此参数。

默认:当前文化

常见示例:

  • ’en-US’:美国格式(MM/DD/YYYY)
  • ‘de-DE’:德国格式(DD.MM.YYYY)
  • ‘sv-SE’ 或 InvariantCulture:ISO 格式(YYYY-MM-DD),兼容性最佳
Type: CultureInfo
DefaultValue: '[System.Globalization.CultureInfo]::CurrentCulture'
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 7
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputFile

指定输出 CSV 文件的路径。
如果未指定,使用输入文件名并替换为 .csv 扩展名,输出到输入文件所在目录。

重要:必须是文件路径,不能是目录。
如果想使用输入文件目录但自定义文件名,请指定包含文件名的完整路径。

Type: String
DefaultValue: ''
SupportsWildcards: false
Aliases:
- Output
- Destination
- OutFile
- OutputPath
ParameterSets:
- Name: (All)
  Position: 1
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputType

指定生成的输出类型。

有效值:

  • ‘CSV’:仅生成包含所有解析日志条目的数据文件
  • ‘Statistic’:仅生成包含聚合指标的统计文件
  • ‘Both’:同时生成数据文件和统计文件(默认)

默认:Both

生成统计时,会创建两个独立文件:

  • ‘_Statistic.csv’:按日期和上下文类型的汇总计数(日期、上下文、计数、计算机名)
  • ‘_PacketStatistic.csv’:按日期、客户端 IP、协议、方向和查询类型的详细 PACKET 计数(日期、客户端 IP、协议、方向、查询类型、计数、计算机名)
Type: String
DefaultValue: Both
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 4
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-RemoveSourceFile

成功处理后删除源 DNS 调试日志文件。

适用于自动化日志处理流水线或磁盘空间管理。
仅当处理成功且所有输出文件生成后才删除源文件。

安全性:不能与 -SkipHeaderValidation 一起使用,以防意外删除无效文件。

警告:源文件将被永久删除。
使用此选项前请确保输出文件有效。

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-SkipHeaderValidation

跳过 DNS 调试日志头部验证检查。

默认情况下,cmdlet 会验证输入文件是否具有有效的 DNS 服务器调试日志头部。
使用此开关可处理无验证的文件,适用于:

  • 修改或自定义日志格式
  • 解决验证问题
  • 非标准或预处理日志

警告:如果文件不是有效的 DNS 日志,可能导致处理错误。

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-WhatIf

显示如果运行 cmdlet 会发生什么。
cmdlet 不会实际运行。

指定后,显示将执行的操作详细信息,但不执行。
适用于:

  • 预览将处理哪些文件
  • 验证输出文件路径
  • 在生产环境运行前测试脚本
Type: SwitchParameter
DefaultValue: ''
SupportsWildcards: false
Aliases:
- wi
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

CommonParameters

此 cmdlet 支持常用参数:-Debug、-ErrorAction、-ErrorVariable、
-InformationAction、-InformationVariable、-OutBuffer、-OutVariable、-PipelineVariable、
-ProgressAction、-Verbose、-WarningAction 和 -WarningVariable。
更多信息请参见 about_CommonParameters

INPUTS

System.String[]

NOTES

版本 : 1.7.1.1
作者 : Andi Bellstedt, Copilot
日期 : 2026-01-26
关键词: Microsoft Windows Server, DNSServer, DNS, DebugLog, LogParser

6 - 使用示例

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

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

6.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 配置,仓库中的权威资源包括:

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

6.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"