ashishsaud2025/mini-ids

GitHub: ashishsaud2025/mini-ids

一个用 Python 实现的轻量级入侵检测引擎,通过 YAML 规则对离线或实时网络流量进行匹配并生成告警。

Stars: 0 | Forks: 0

# Mini-IDS [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/ashishsaud2025/mini-ids/actions/workflows/ci.yml) **一个轻量级的、受 Snort 启发的入侵检测规则引擎,使用 Python 编写。** ## 功能简介 `mini-ids` 从 **pcap 文件**或**实时网络接口**读取数据包,并将它们与受 Snort 启发的小型、声明式 **YAML 规则语言**进行匹配。 当一个数据包(或一组突发数据包)匹配某条规则时,引擎会打印警报,并可选择将其追加到 JSON Lines 文件中以便日后分析。 ``` # 回放 capture 文件 python -m src.cli --rules rules.yaml --pcap capture.pcap # 同时将 alerts 写入 JSONL 文件 python -m src.cli --rules rules.yaml --pcap capture.pcap --log alerts.jsonl # 实时 capture(需要 root/admin 权限 — 见下文) sudo python -m src.cli --rules rules.yaml --live eth0 ``` | 参数 | 含义 | |-----------|----------------------------------------------------------------| | `--rules` | YAML 规则文件的路径(必填) | | `--pcap` | 待重放的 PCAP 文件(离线分析) | | `--live` | 用于实时嗅探的接口名称,例如 `eth0`, `en0`, `Wi-Fi` | | `--log` | 将警报以 JSON Lines 格式追加到此文件中(每行一个 JSON 对象)| ## 规则语法 规则存放在单个 `rules.yaml` 文件中。该文件是一个 YAML 规则文档**列表**;加载器也接受以 `---` 分隔的多个文档。 ``` - name: "ICMP Ping Sweep" protocol: icmp condition: "count > 10 in 5s from same src" severity: medium - name: "Plaintext FTP Login" protocol: tcp port: 21 payload_contains: ["USER", "PASS"] severity: high - name: "Suspicious User-Agent" protocol: tcp port: 80 payload_regex: "curl|python-requests|Wget" severity: low ``` ### 字段说明 | 字段 | 必填 | 含义 | 示例 | |--------------------|----------|---------------------------------------------------------------------------------------------|------------------------------------------| | `name` | ✅ | 显示在警报中的规则名称 | `"ICMP Ping Sweep"` | | `protocol` | ✅ | 要匹配的数据包协议:`tcp`、`udp` 或 `icmp` | `tcp` | | `severity` | ✅ | 警报严重程度:`low`、`medium`、`high` | `high` | | `port` | ❌ | 目标端口过滤器(验证范围 1–65535)。在任何条件计数*之前*应用。 | `21` | | `payload_contains` | ❌ | 子字符串列表(不区分大小写);它们**全部**必须出现在 payload 中。 | `["USER", "PASS"]` | | `payload_regex` | ❌ | 在 payload 中搜索的 Python 正则表达式。 | `"curl\|python-requests\|Wget"` | | `condition` | ❌ | `"count > N in Ts from same src"` → **有状态**窗口;`"payload_len > N"` → **无状态**大小检查 | `"count > 10 in 5s from same src"` | 一条规则必须至少定义一个匹配条件(`condition`、`payload_contains` 或 `payload_regex`)。一条规则上的多个条件将通过 **AND**(与)逻辑组合,因此必须每个指定的字段都匹配成功,规则才会触发。 **有状态窗口**会为每个 `(规则, 源 IP)` 维护一个滑动的时间窗口,因此 `count > 10 in 5s from same src` 表示如果在任何 5 秒的时间跨度内,有超过 10 个匹配的数据包来自同一个源,就会触发。该窗口使用 `collections.deque` 实现。 ## 规则示例 (`rules.yaml`) 代码库附带了 10 条规则,涵盖了规范中的每一种场景: | 规则 | 类型 | 场景 | |----------------------------------------|-------------|--------------------------------------------| | ICMP Ping Sweep | 有状态 | 5秒内来自同一源 IP 的 >10 个 ICMP 事件 | | TCP Port Scan | 有状态 | 5秒内来自同一源 IP 的 >100 个 TCP 事件 | | UDP Port Scan | 有状态 | 5秒内来自同一源 IP 的 >50 个 UDP 事件 | | 明文 FTP 登录 | 无状态 | 端口 21 上的 `USER`/`PASS` | | Telnet 明文登录 | 无状态 | 端口 23 上的 `login:`/`Password:` | | HTTP Basic Auth 凭据 | 无状态 | 端口 80 上的 `Authorization: Basic ` | | 可疑的 User-Agent | 无状态 | `curl`、`python-requests` 或 `Wget` | | 异常大的 DNS 响应 | 无状态 | UDP/53 payload > 512 字节(放大攻击) | | SSH 暴力破解 | 有状态 | 60秒内来自同一源 IP 的 >10 个 TCP/22 事件 | | 超大 HTTP 响应 | 无状态 | 端口 80 上 payload > 65536 字节 | ## 这与 Snort/Suricata 的映射关系(及区别) 这种语言*受* Snort 的 `alert` DSL *启发*,但经过了刻意的简化: | Snort / Suricata 概念 | Mini-IDS 等价物 | |---------------------------------------------------|---------------------------------------------------------| | `alert tcp $HOME_NET any -> $EXTERNAL_NET 80` | `protocol: tcp`, `port: 80` (始终为 `any -> any`) | | `content:"USER"; content:"PASS";` | `payload_contains: ["USER", "PASS"]` | | `pcre:"/curl\|python-requests\|Wget/i";` | `payload_regex: "curl|python-requests|Wget"` | | `threshold: type both, track by_src, count 10, seconds 5` | `condition: "count > 10 in 5s from same src"` | | `dsize:>512;` / `byte_test:...` | `condition: "payload_len > 512"` | | `msg:"..."; classtype:...; priority:...` | `name: ...`, `severity: ...` | | `sid:... rev:...` (规则标识/版本控制) | — (改用规则名称) | **我们进行简化的原因:** - **使用 YAML 而非 Snort DSL。** Snort 那种面向行的 DSL 非常紧凑,但包含大量隐藏的语法(动作、方向操作符、规则选项、修饰符)。YAML 使结构变得清晰明了,并允许我们在处理任何数据包之前,对各个字段进行独立验证并提供清晰的错误信息。 - **没有 home-net/external-net 变量。** `$HOME_NET`/`$EXTERNAL_NET` 需要了解网络拓扑结构;mini-ids 只是简单地匹配 `src`/`dst` 并按源 IP 进行计数。 - **没有规则动作。** Snort 规则可以执行 `alert`、`drop`、`reject`、`log` 等操作,而 mini-ids *仅*生成警报。 - **使用子字符串列表代替 `content` + offset/distance 修饰符。** Snort 的 `offset:`/`depth:`/`distance:`/`within:` 用于微调内容必须匹配的*位置*。支持它们会使语言变得过于臃肿,但教育意义却微乎其微。 - **单一的窗口语法。** Snort 的阈值支持多种组合(`type both/limit/threshold`、`track by_src/by_dst`、`count`、`seconds`)。我们恰好只支持一种形式:`count > N in Ts from same src`。 - **仅限正则表达式,不支持类似 `U` (UTF-8) 或 `R` (相对) 的 `pcre` 修饰符。** 正则表达式直接使用 Python 的 `re` 进行编译。 结论是:Snort/Suricata 规则是一种极其丰富的语言,专为以线速部署包含 40,000 条规则的社区规则集而调优。而这个项目则是希望你能完全理解匹配流水线中的每一个微小细节。 ## 引擎内部原理 ``` pcap/live packets │ ▼ capture.py ─ normalizes Scapy packets → dicts │ (timestamp, protocol, src/dst, ports, payload) ▼ engine.py ─ for each rule: │ 1. protocol/port gate │ 2. payload_contains / payload_regex (stateless AND) │ 3. condition: │ • "payload_len > N" → stateless size match │ • "count > N in Ts..." → sliding-window counter (deque) │ ▼ cli.py ─ prints alert to stdout, optionally appends JSONL ``` - **无状态规则**使用协议、端口、子字符串、正则表达式或大小检查来匹配单个数据包。`payload_contains` 的匹配不区分大小写(原始字节 → 转换为小写后比较),而 `payload_regex` 则区分大小写(如果需要不区分大小写的正则表达式,请自行编写 `(?i)`)。 - **有状态规则**为每个 `(规则名称, 源 IP)` 维护一个包含事件时间戳的 `collections.deque`。每个匹配的数据包都会追加其(数据包的)时间戳;一旦过期条目落在窗口之外(`cutoff = now - T`),就会立即从左侧弹出。这使得平摊维护成本为 O(1),且内存限制在最后 `T` 秒内的事件数量,即无需进行全历史扫描。仅当计数值*跨越*阈值时才会触发警报,从而避免在进行中的扫描期间每个数据包都产生警报。 ## 已知局限性 - **不支持 TCP 重组。** 仅按单个数据包检查 payload;跨越多个 TCP 分段的内容对此引擎是不可见的。 - **不支持加密 payload 检查。** TLS/QUIC payload 显示为密文,无法匹配子字符串/正则表达式规则(尽管有状态的连接速率规则仍适用于 TCP/UDP 层面)。 - **单进程,单线程。** 纯 Python 引擎无法跟上线速流量;`sniff()` + Python 匹配的速度远不及 Snort 优化过的 C/模式匹配流水线。 - **无抗规避能力。** 没有重叠分片处理,没有 IP/TCP 标志位标准化,没有 TTL 检查,也没有去碎片化。攻击者可以轻易地规避这些规则。 - **端口扫描检测属于启发式方法。** `count > N in Ts` 会产生误报(正常的突发流量)和漏报(超出窗口时间范围的慢速扫描)。 - **pcap 文件会在分析前完全加载到内存中**(`rdpcap`)。处理非常大的抓包文件是不切实际的;如果需要,请在自己的代码中流式传输该文件。 - **重启后状态不会持久化。** 长时间的实时捕获会在内存中累积窗口;每个窗口的内存是有界的,但是 `(规则, 源 IP)` 键的字典会随着看到的唯一源 IP 数量增加而不断增大。 ## 为你自己的抓包编写规则 推荐的工作流程是*先观察,后编写规则*: ``` # 1. 查看 capture 实际包含的内容(protocols、ports、payloads) python scripts/analyze_pcap.py pcap-files/my-capture.pcapng # 2. 找出哪些 flows 包含感兴趣的 strings(credentials、HTTP、UAs) python scripts/find_interesting.py pcap-files/my-capture.pcapng # 3. 为你发现的内容编写 rules(参见 my_rules.yaml,这是一个针对真实 capture 编写的带注释 # 教程文件),然后回放: python -m src.cli --rules my_rules.yaml --pcap pcap-files/my-capture.pcapng ``` 请查看 `my_rules.yaml` 中带有完整注释的示例,该示例详细介绍了*为什么*要这样编写每条规则(包括经典的 `USER` 与 `User-Agent` 子字符串陷阱,以及通过调整阈值来消除 TLS 突发误报)。 ## 演示抓包 一个小巧的辅助脚本会生成一个独立的 `test_traffic.pcap`(由 Scapy 构建的数据包:FTP 登录、可疑的 User-Agent、超大的 DNS 响应,以及包含 110 个数据包的端口扫描突发流量),用于端到端测试 CLI: ``` python scripts/make_test_pcap.py python -m src.cli --rules rules.yaml --pcap test_traffic.pcap --log alerts.jsonl ``` 预期会出现四个警报:**Plaintext FTP Login**、**Suspicious User-Agent**、**Unusually Large DNS Response**,以及当突发流量超过阈值时触发的一个 **TCP Port Scan** 有状态警报。 ## 运行测试 ``` pip install -r requirements.txt pytest -q ``` 测试**仅使用带有模拟时间戳的事件**(没有真实抓包,也没有 Scapy),因此测试套件可以在任何机器上快速且确定性地运行。 ## 项目结构 ``` src/ rule_loader.py # YAML parsing + strict schema validation (clear errors) engine.py # stateless matching + deque-based sliding windows capture.py # pcap replay / live sniff() abstraction, Scapy normalization cli.py # argparse entry point, stdout + JSONL output rules.yaml # 10 example rules (classic Snort-style) my_rules.yaml # annotated tutorial — how to write rules for YOUR traffic scripts/ make_test_pcap.py # generates demo test_traffic.pcap analyze_pcap.py # protocol/port/payload summary of a capture find_interesting.py # locates flows carrying interesting strings smoke_test.py # end-to-end smoke test (loader → engine → JSONL) tests/ test_rule_loader.py # validation errors, multi-doc YAML, malformed files test_engine.py # stateless + stateful matching with fake timestamps README.md requirements.txt ``` ## 免责声明 本项目是一个**用于教育演示的项目**。它**不是**生产级别的 IDS 软件,绝不能用于保护真实的网络。真正的 IDS 引擎(Snort、Suricata)是在防规避、协议解码器、性能工程和坚如磐石的工具支持方面经过数十年发展的成果。请利用本项目来理解其中的*理念*,然后在真正进行防御工作之前,去阅读 Snort 的官方文档。
标签:Python, 云计算, 无后门, 网络安全, 规则引擎, 逆向工具, 防御绕过, 隐私保护