ParshwaBhavsar/dnswatch

GitHub: ParshwaBhavsar/dnswatch

dnswatch 是一款被动 DNS 日志分析器,通过五种统计与行为检测器从已有 DNS 日志中发现 C2 beaconing、DNS 数据外泄、DGA 域名及 NXDOMAIN 风暴等威胁。

Stars: 0 | Forks: 0

# dnswatch ![Python](https://img.shields.io/badge/python-3.10%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Tests](https://img.shields.io/badge/tests-42%20passing-brightgreen) ![Type](https://img.shields.io/badge/type-defensive%20%2F%20blue--team-informational) **专为检测工程师设计的被动 DNS 日志分析器。** 只需将来自路由器、Pi-hole、Zeek 或 pfSense 的导出 DNS 日志输入其中,它便会对每一次查询运行五种行为检测器——从而发现 C2 beaconing、DNS 数据外泄隧道、DGA 域名、NXDOMAIN 风暴以及已知恶意域名,并在每次告警中提供 MITRE ATT&CK 映射。 没有流量拦截,也没有主动的 DNS 组件——`dnswatch` 仅读取您已有的日志文件。 ## 目录 - [为什么开发此项目](#why-this-exists) - [检测器](#detectors) - [安装说明](#install) - [快速开始](#quick-start) - [用法](#usage) - [输出示例](#example-output) - [工作原理](#how-it-works) - [支持的日志格式](#supported-log-formats) - [测试](#testing) - [项目结构](#project-structure) - [展示的概念](#concepts-demonstrated) - [客观存在的局限性](#honest-limitations) - [路线图](#roadmap) - [道德与范围](#ethics--scope) ## 为什么开发此项目 DNS 是互联网的电话簿——而攻击者无时无刻不在滥用它。C2 框架通过 DNS 查询与控制端进行通信。恶意软件使用算法生成的域名,以至于没有任何静态拦截列表能够将它们全部捕获。数据外泄工具将窃取的字节编码到子域名标签中,并将其发送到攻击者控制的域名服务器。这些攻击中的每一次都会在您的 DNS 查询日志中留下蛛丝马迹。 `dnswatch` 读取这些日志,并应用 SOC 分析师通常手动应用的相同统计和行为分析技术——beaconing 规律性、子域名熵值、域名中的辅音分布——并将它们转化为结构化、可解释的告警。 该项目涵盖了检测工程领域的**网络层**:继 `bintriage`(文件层)和 `authdetect`(应用/日志层)之后,DNS 层的分析补全了全栈防御的蓝图。 ## 检测器 | 检测器 | 特征 | MITRE | 严重程度 | |----------|--------|-------|----------| | **黑名单 (Blocklist)** | 域名匹配已知的恶意威胁情报列表 | T1071.004 | CRITICAL–LOW | | **DNS 数据外泄** | 子域名标签长度 > 45 个字符且熵 > 3.5 bits/char;或者同一基础域名拥有 > 15 个唯一子域名 | T1048.003 | HIGH / MEDIUM | | **Beaconing** | 以固定间隔查询同一域名 (CV < 0.4) —— 自动化的 C2 签到 | T1071.004 | HIGH / MEDIUM | | **DGA 检测** | 高辅音比例 (> 62%),高熵,标签长度 14-22 —— 算法生成的域名 | T1568.002 | HIGH / MEDIUM | | **NXDOMAIN 风暴** | 60 秒内一个客户端收到 > 10 个 NXDOMAIN 响应 —— DGA 恶意软件正在循环尝试候选域名 | T1568, T1568.002 | HIGH | 每次告警包含: - 源 IP、域名、时间戳 - 关于*为什么*会触发告警的人类可读描述 - 量化证据(熵值分数、CV、查询次数等) - MITRE ATT&CK 战术和技术 ID - 误报指导 ## 安装说明 ``` git clone https://github.com//dnswatch.git cd dnswatch pip install -r requirements.txt pip install -e . ``` 要求 Python 3.10+。运行时依赖项:`rich`。 ## 快速开始 ``` # 1. 生成模拟日志(所有数据均为虚构——不包含真实域名或 IP) python -m dnswatch generate-logs --output sample.ndjson # 2. 运行全部五个检测器 python -m dnswatch analyze --logfile sample.ndjson ``` ## 用法 ``` # 分析日志文件 — 丰富的终端表格 python -m dnswatch analyze --logfile /var/log/pihole.log # 用于管道传输到 SIEM 或 jq 的 JSON 输出 python -m dnswatch analyze --logfile dns.ndjson --output-format json # 添加自定义 blocklist(每行一个域名) python -m dnswatch analyze --logfile dns.ndjson --blocklist my_iocs.txt # 过滤为 HIGH 及以上级别 python -m dnswatch analyze --logfile dns.ndjson --min-severity high # 显式指定日志格式 python -m dnswatch analyze --logfile dns.log --format pihole # 生成模拟测试日志 python -m dnswatch generate-logs --output test.ndjson ``` ## 输出示例 ``` Blocklist: 3 domains Parsed 247 events from sample.ndjson dnswatch — 4 alert(s) ┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Sev ┃ Detector ┃ Src IP ┃ Finding ┃ ┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ 🟠 HIGH │ dns_exfiltration │ 192.168.1.55 │ Possible DNS Data Exfil │ │ │ │ │ Label 48 chars, entropy │ │ │ │ │ 4.71 bits/char │ │ │ │ │ [MITRE] T1048.003 │ │ 🟠 HIGH │ dga_detection │ 192.168.1.99 │ Possible DGA Domain │ │ │ │ │ cgkhyqwdmvlqzh.net │ │ │ │ │ entropy 3.82, 91% conson. │ │ │ │ │ [MITRE] T1568.002 │ │ 🟠 HIGH │ nxdomain_storm │ 192.168.1.99 │ NXDOMAIN Storm │ │ │ │ │ 10 NXDOMAIN in 60s │ │ │ │ │ [MITRE] T1568, T1568.002 │ └──────────┴──────────────────┴───────────────┴───────────────────────────┘ ╭────────── Summary ───────────╮ │ Events analysed: 247 │ │ Total alerts: 4 │ │ 🟠 HIGH: 4 │ │ dga_detection 2 │ │ dns_exfiltration 1 │ │ nxdomain_storm 1 │ ╰──────────────────────────────╯ ``` ## 工作原理 ``` log file (Pi-hole / Zeek / CSV / NDJSON) │ ▼ parsers.py auto-detect format → normalise to DNSQueryEvent │ timestamp · src_ip · domain · qtype · response ▼ detectors/ ├── blocklist.py exact + parent-domain match against threat intel ├── exfil.py label length + entropy + subdomain diversity ├── beaconing.py inter-query interval CV (σ/μ) ├── dga.py consonant ratio + entropy + label length scoring └── dga.py NXDOMAIN sliding-window count │ ▼ model.py Alert with evidence dict + MITRE ATT&CK │ ▼ report.py rich terminal table / NDJSON stream ``` ### 检测逻辑详解 **DNS 数据外泄** —— DNS 隧道工具 (iodine, dnscat2) 将数据进行 base64/hex 编码并放入子域名标签中。包含两个信号:(1) 长度 > 45 个字符且 Shannon 熵 > 3.5 bits/char 的标签指示了编码后的 payload;(2) 在一个会话中对同一基础域名有 > 15 个唯一子域名指示了分块数据传输。 **Beaconing** —— C2 框架会按计划回连。取证信号在于其*规律性*。`dnswatch` 会计算每个 (src_ip, domain) 对的查询间隔变异系数 (σ/μ)。CV < 0.40 被标记为 MEDIUM;CV < 0.20 被标记为 HIGH。合法的浏览器流量通常是突发性的(高 CV);而恶意软件的计时器则像节拍器一样极其规律(低 CV)。 **DGA** —— 域名生成算法通过将种子(通常是当天的日期)输入 PRNG 来生成域名。生成的名称在统计学上与人类选择的域名有所区别:高辅音密度、无可识别词汇、Shannon 熵升高。`dnswatch` 会在三个维度上对每个标签进行评分,当综合得分超过 0.70 时触发告警。 **NXDOMAIN 风暴** —— 当 DGA 恶意软件启动时,它会快速遍历候选域名,直到有一个解析成功。每次失败的尝试都会产生一个 NXDOMAIN 响应。在 60 秒内来自同一客户端的 > 10 次 NXDOMAIN 响应是一个强烈的 DGA 指标,特别是当这些解析失败的域名共享结构属性时。 **黑名单** —— 与调用方提供的威胁情报集进行精确匹配和父域名匹配,并支持父域名传播(拦截 `evil.com` 也会拦截 `sub.evil.com`)。严重程度派生自类别标签(c2 → CRITICAL,malware → HIGH,tracker → LOW)。 ## 支持的日志格式 | 格式 | 解析器 | 自动检测条件 | |--------|--------|-----------------| | JSON / NDJSON | `JSONParser` | 以 `{` 开头的行 | | Pi-hole / dnsmasq | `PiholeParser` | 包含 `query[` 或 `dnsmasq` | | Zeek dns.log | `ZeekParser` | 以 `#fields` 或 `#separator` 开头 | | CSV | `CSVParser` | 包含逗号,表头可选 | **JSON 字段别名** —— JSON 解析器会自动解析常见的字段名变体(`query` → `domain`,`client` → `src_ip`,`rcode_name` → `response` 等),因此来自不同来源的日志无需预处理即可直接使用。 ## 测试 ``` pip install pytest pytest -q ``` ``` 42 passed in 0.12s ``` 测试范围涵盖了每个解析器、全部五个检测器、合成日志生成器,以及对样本日志能够触发多个检测器的端到端验证。 ## 项目结构 ``` dnswatch/ ├── dnswatch/ │ ├── model.py # DNSQueryEvent, Alert dataclasses │ ├── parsers.py # Pi-hole / Zeek / CSV / JSON parsers │ ├── report.py # rich terminal + NDJSON + log generator │ ├── cli.py # analyze / generate-logs subcommands │ └── detectors/ │ ├── base.py # BaseDetector ABC │ ├── blocklist.py # threat intel lookup │ ├── exfil.py # DNS exfiltration patterns │ ├── beaconing.py # C2 beacon regularity │ └── dga.py # DGA scoring + NXDOMAIN storm ├── tests/ │ └── test_dnswatch.py # 42 tests ├── requirements.txt ├── pyproject.toml └── README.md ``` ## 展示的概念 - **DNS 协议** —— 查询和响应是如何工作的,NXDOMAIN / NOERROR / SERVFAIL 代表什么,子域名标签是如何结构的 - **Shannon 熵**作为一种分析基础 —— 与 `bintriage` 的加壳检测器中的概念相同,此处应用于检测 DNS 标签中的编码 payload - **统计行为分析** —— 用于 beaconing 的变异系数;用于 DGA 的辅音比例 + 熵值评分;用于 NXDOMAIN 风暴的滑动窗口计数 - **MITRE ATT&CK** —— T1048(通过替代协议外泄)、T1071.004(DNS)、T1568.002(DGA);与 `authdetect` 使用相同的框架 - **日志标准化** —— 将四种不同的 DNS 日志格式映射到单一的 `DNSQueryEvent` 模型中,从而使所有检测器都与格式无关 - **模块化检测器架构** —— 每个检测器都是一个独立的类;添加新检测器只需编写一个文件,并将其追加到 `cli.py` 的列表中即可 ## 客观存在的局限性 - **无实时捕获** —— `dnswatch` 读取的是导出的日志,而不是实时流量。如需实时分析,请使用日志转发器(Filebeat, Vector)或 tail 模式为其提供数据。 - **DGA 误报** —— 某些合法服务会使用看起来像随机生成的子域名(CDN 资产哈希、ACME 验证 token)。阈值经过了保守调整;请根据您的环境调整 `detectors/dga.py` 中的 `_MIN_LABEL_LEN`、`_MIN_ENTROPY` 和 `_MIN_CONSONANT`。 - **Beaconing 需要历史记录** —— 您需要每个 (IP, 域名) 对有足够的事件才能计算出有意义的统计数据。较短的日志时间窗口会遗漏掉频率较慢的 beaconing。 - **不支持加密 DNS** —— DoH / DoT 流量在 DNS 层是不透明的;此工具只能看到以未加密形式通过网络传输的查询。 ## 路线图 - [ ] Zeek + Suricata 告警关联(DNS 异常 + IDS 特征 = 更高的置信度) - [ ] Pi-hole 实时日志 tail 模式(流式分析) - [ ] 被动 DNS 信誉查询(VirusTotal / PassiveDNS API) - [ ] 基于 YAML 的自定义检测器规则(与 `authdetect` 格式相同) - [ ] 包含各检测器操作演练和可视化的 Jupyter notebook ## 道德与范围 专为防御用途构建:威胁狩猎、检测工程、事件响应和安全教育。`dnswatch` 仅读取日志文件;它不会建立任何网络连接,不执行任何 DNS 查找,也不与任何实时流量进行交互。请仅分析您被授权访问的日志。 ## 许可证 MIT
标签:C2检测, DNS日志分析, IP 地址批量处理, PB级数据处理, Python, 威胁情报, 安全规则引擎, 安全运维, 开发者工具, 无后门, 逆向工具