
Скрипт PowerShell, который отслеживает DNS-трафик Windows через pktmon для обнаружения отравления, спуфинга, ответов вредоносных резолверов и изменений MAC-адреса шлюза, регистрируя оповещения.
Однофайловый скрипт PowerShell, который отслеживает собственный сетевой трафик машины Windows на предмет признаков DNS-отравления / спуфинга, используя pktmon — встроенный в Windows инструмент захвата пакетов, доступный в 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-спуфинг — обычный первый шаг атакующих, чтобы занять позицию для подмены DNS в локальной сети. |
Каждое оповещение выводит две части:
[TECHNICAL] — детали необработанного пакета, для тех, кто хочет копнуть глубже[WHAT THIS MEANS] — объяснение простым языком, почему это важноВесь вывод также записывается в лог-файл с отметкой времени.
pktmon.exe (входит в состав всех перечисленных)pktmon pcapng (используется для конвертации захватов для анализа) был добавлен после первоначального релиза 1809; если его нет, обновите Windowsgit clone https://github.com/microlaser/dns-watchdog.git
cd dns-watchdog\windows
Никаких модулей или внешних зависимостей устанавливать не нужно — только сам скрипт.
Из повышенной (Administrator) консоли 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 короткими сменяющимися окнами (по умолчанию 5 секунд), захватывая в .etl.pcapng (pktmon pcapng)Одна особенность, которую стоит знать: Windows часто захватывает локально сгенерированные (исходящие) пакеты до добавления заголовка Ethernet на некоторых контрольных точках стека, поэтому исходящие DNS-запросы могут приходить как голые IP-пакеты вообще без кадрирования канального уровня, тогда как входящие ответы приходят с полным Ethernet-кадрированием из сети. Парсер обнаруживает и обрабатывает оба случая. pktmon также склонен сообщать об одном и том же физическом пакете более одного раза (захваченном в нескольких точках сетевого стека); скрипт дедуплицирует побайтово идентичные повторы в пределах каждого окна захвата, чтобы об одном реальном пакете не оповещалось несколько раз — по-настоящему конфликтующий/отравленный ответ имеет другое содержимое, поэтому эта дедупликация его никогда не затрагивает.
pktmon pcapng требует достаточно свежей сборки Windows; очень старые системы эпохи 1809 могут нуждаться в откате к pktmon etl2txt (здесь не реализовано).MIT (или обновите в соответствии с вашими предпочтениями).