一个单文件 PowerShell 脚本,使用 pktmon 监视 Windows 机器自身的网络流量,以发现 DNS 投毒 / 欺骗 的迹象。pktmon 是 Windows 10(1809+)、Windows 11 和 Windows Server 2019+ 内置的数据包捕获工具。无需第三方捕获工具(Wireshark、Npcap、tcpdump)。
它在操作系统网络栈处捕获 DNS 流量(UDP/TCP 端口 53),这覆盖了典型机器上的 LAN 和 WAN 流量,然后自行解析原始数据包——pcapng 二进制格式、Ethernet/IP/UDP/TCP 报头以及 DNS 消息格式,包括名称压缩指针——完全使用原生 PowerShell。
配套的 bash/tcpdump 版本 覆盖 macOS 和 Linux。
| 信号 | 为什么重要 |
|---|---|
| 对同一 DNS 查询的冲突应答 | 投毒尝试的教科书式特征:攻击者用伪造应答与真实应答竞争,希望伪造应答先到达并被缓存。 |
| 来自你从未配置过的 DNS 服务器的响应 | 与 Get-DnsClientServerAddress 进行比对。来自无法识别服务器的应答可能表明存在路径外攻击者注入应答。 |
| 没有匹配的未完成查询的响应 | 针对监视器从未见过被询问的问题的应答——可能是注入/欺骗流量的迹象(带有启动宽限期以避免误报)。 |
| 会话中途默认网关 MAC 地址发生变化 | 每个捕获周期通过 Get-NetNeighbor 轮询。ARP 欺骗通常是攻击者为在 LAN 内进行 DNS 篡改而采取的第一步。 |
每个警报打印两部分:
[TECHNICAL] — 原始数据包细节,供进一步调查的人使用[WHAT THIS MEANS] — 用通俗语言解释为什么重要所有输出也会写入带时间戳的日志文件。
pktmon.exe 可用(这些系统均内置)pktmon pcapng(用于转换捕获以供分析)是在最初的 1809 版本之后添加的;如果缺失,请更新 Windowsgit clone https://github.com/microlaser/dns-watchdog.git
cd dns-watchdog\windows
无需安装模块或外部依赖——只需脚本本身。
从 提升权限(管理员) 的 PowerShell 中:
.\dns_watchdog.ps1
默认情况下,脚本会自动检测你的默认网关和已配置的 DNS 服务器,并跨所有网络适配器进行捕获(pktmon 在操作系统网络栈处运行,因此这自然覆盖 LAN 和 WAN 流量,无需选择特定适配器)。使用 Ctrl+C 停止监视;退出时会打印会话摘要。
.\dns_watchdog.ps1 [-LogFile <path>] [-CaptureIntervalSeconds <n>] [-GraceResponses <n>] [-KeepCaptures]
| 参数 | 描述 |
|---|---|
-LogFile | 会话日志的路径(默认:.\dns_watchdog_<timestamp>.log) |
-CaptureIntervalSeconds | 每个捕获窗口在被转换和分析之前的长度。越低 = 检测延迟越小,开销越大。默认:5 |
-GraceResponses | 在“无匹配查询”警报激活之前观察的响应数量,以避免启动噪音。默认:10 |
-KeepCaptures | 将每个窗口的 .etl/.pcapng 文件保留在磁盘上,而不是在分析后删除 |
=========================================================================
DNS Watchdog (Windows) - DNS poisoning / spoofing monitor
=========================================================================
Capturing on: all network adapters (pktmon captures at the OS networking stack,
which covers this host's LAN and WAN traffic together)
Default gateway: 192.168.1.1 (MAC baseline: 60-95-F8-2B-5E-78)
Configured DNS: 192.168.0.1, 192.168.1.1
Log file: .\dns_watchdog_20260918_204725.log
...
[20:47:44.872] [ALERT] Conflicting DNS responses for the same query
[TECHNICAL] txn=64878 query=example.com (type 28) first_response=[AAAA:2607:f8b0:...] conflicting_response(src=10.0.0.9)=[AAAA:dead:beef::1]
[WHAT THIS MEANS] This machine's DNS question got two DIFFERENT answers back. Legitimate DNS servers don't normally do this. This is the textbook signature of a DNS poisoning attempt, where an attacker races a forged answer against the real one, hoping the forged one arrives first and gets cached.
Windows 没有直接将 tcpdump 管道传输到文本解析器的直接对应物——pktmon 的实时控制台输出是原始字节,而不是解码后的行。因此,此脚本改为:
pktmon,捕获到 .etl.pcapng(pktmon pcapng)一个值得了解的怪癖: Windows 经常在某些栈检查点处,在添加 Ethernet 报头 之前 捕获本地生成(出站)的数据包,因此出站 DNS 查询可能以完全没有链路层帧的裸 IP 数据包形式到达,而入站响应则从线路上以完整的 Ethernet 帧到达。解析器检测并处理这两种情况。pktmon 也倾向于多次报告同一个物理数据包(在网络栈的多个点捕获);脚本在每个捕获窗口内对字节完全相同的重复项进行去重,因此一个真实数据包不会被多次警报——真正冲突/被投毒的响应具有不同的内容,因此永远不会受此去重影响。
pktmon pcapng 转换需要相当新的 Windows 版本;非常古老的 1809 时代系统可能需要回退到 pktmon etl2txt(此处未实现)。MIT(或根据你的偏好更新)。