helixmap/sigwood
GitHub: helixmap/sigwood
sigwood 是一款无需 SIEM 或 agent 的本地优先命令行威胁狩猎工具,直接对已有的 Zeek、Pi-hole、syslog 和 CloudTrail 日志运行透明检测器并给出带方法说明的发现报告。
Stars: 64 | Forks: 5
# `sigwood`
[](https://github.com/helixmap/sigwood/actions/workflows/ci.yml)
sigwood 是一款为自托管用户设计的本地优先命令行威胁狩猎工作台。你
可以让它指向你已有的日志 - Zeek, Pi-hole/dnsmasq, syslog, CloudTrail - 然后
它会告诉你其中包含什么,并对其运行透明的检测器:beaconing、可疑的
DNS、端口扫描、罕见的 syslog 事件、异常的长连接,以及不寻常的 CloudTrail
活动。每次运行都会指出每个检测器背后的技术,因此你始终可以清楚地知道某个
发现是来自已发表的算法还是直观的启发式方法。
**不是 SIEM。不是 agent。不是魔法。** 无需部署,没有数据库,没有 daemon,也无需
账号。安装它,将其指向一个日志目录,然后读取输出即可。它运行在
管理员自己的机器上,处理处于静止状态的日志。
[](#license)

**文档:** [常见问题及检测器工作原理](https://github.com/helixmap/sigwood/blob/main/docs/FAQ.md) · [路线图](https://github.com/helixmap/sigwood/blob/main/docs/ROADMAP.md) · [已知问题](https://github.com/helixmap/sigwood/blob/main/docs/KNOWN-ISSUES.md) · [数据结构](https://github.com/helixmap/sigwood/blob/main/docs/SCHEMA.md)
每次运行都会以一个汇总横幅开始 - 加载了什么内容,以及每个
检测器使用了哪种技术 - 然后按检测器对发现进行分组,以纯文本形式在你的
终端中呈现(默认),或以更丰富的格式(例如 html)呈现。下方的输出仅为
示例展示;地址属于 [RFC 5737](https://datatracker.ietf.org/doc/html/rfc5737)
文档空间:
` 即可针对一个目录或
单个文件进行工作。`sigwood init` 只是为了让操作可重复执行。
## 为什么使用 sigwood?
- **在日志所在的地方运行。** 无需服务,无需数据库,无需 daemon,无需推送 agent。
`pipx install sigwood`,将其指向一个目录,即可获取输出。唯一存在的设置步骤
是可选的:`sigwood init`,并且它只是为了方便而在 `~/.sigwood/` 下写入纯文本文件。
- **真实的方法,完全透明。** Beaconing 是通过对连接时序进行 FFT 发现的;
DNS 是通过对每次查询的行为进行 HDBSCAN 聚类发现的;罕见的 syslog 事件是通过 drain3
日志模板化加上稀有度评分发现的;CloudTrail 是通过透明的按主体(per-principal) z-score
复合评分发现的。每次运行都会告诉你运行了哪种技术。你可以确切地读懂*为什么*某些内容
会被揪出来 - 没有黑盒。
- **广泛的接入能力。** 一个工具即可读取 Zeek(NDJSON *和* TSV,扁平目录 *或* 按日期分区的
目录)、Pi-hole/dnsmasq、扁平的 RFC 3164 syslog(Debian *和* RHEL/Fedora 布局)
以及 CloudTrail。日志轮转和 `.gz`/`.bz2`/`.xz` 压缩都会被透明地处理。
- **在狩猎前先熟悉环境。** `sigwood digest FILE` 会读取日志并报告关于
它的事实信息 - 时间跨度、主要通信者、混合流量的形态 - 且不给出任何结论。它告诉你里面有
什么,从而让你知道该将检测器指向哪里。
- **分析前先过滤。** 默认开启了一份精选的已知无害基础设施白名单,它会在
任何检测器看到数据*之前*抑制掉这些噪音 - 你可以按名称关闭任意列表,使用
`--no-allowlist` 丢弃整个列表,或者添加你自己的列表。你的噪音底线由
你自己设定;检测器永远不知道它的存在,而且每次运行都会披露它隐藏了多少内容。
- **诚实的输出。** 发现结果带有严重程度、评分背后的证据,并且(使用
`-v`/`-vv` 时)带有供分析师下一步追踪的切入点。根据任务选择合适的格式:用于阅读的
**报告**(`text`, `html`, `pdf`),用于编写脚本处理的**无损数据流**
(`json`),或者用于分诊处理的**工作清单**(`csv`)。
## 它狩猎什么
| 检测器 | 发现目标 | 方法 | 来源 |
|-----------|-----------------------------------------------------|------------------------------|--------------------------------|
| `beacon` | 周期性的 C2 风格回调 | 对连接时序进行 FFT | Zeek `conn.log` |
| `dns` | DGA / 隧道 / 异常查询 | HDBSCAN 聚类 | Zeek `dns.log` **或** Pi-hole |
| `syslog` | 罕见的事件和重启 | drain3 模板化 + 稀有度 | syslog (扁平) **或** Zeek `syslog.log` |
| `scan` | 垂直 / 水平 / 块 / 慢速端口扫描 | 模式(启发式) | Zeek `conn.log` |
| `duration`| 异常的长连接 | 启发式 | Zeek `conn.log` |
| `aws` | 按主体的异常 CloudTrail 行为 | 统计方法(z-score 复合) | CloudTrail `*.json*`(包含 `.gz`) |
`dns` 和 `syslog` 各自跨越**两**个来源家族回答**一个**问题 - DNS 对应 Zeek 和
Pi-hole,syslog 对应扁平的 rsyslog 和 Zeek 自带的 `syslog.log` - 并且会适应
它们所接收到的任何保真度。
运行所有检测器(`sigwood hunt`),选择部分检测器(`sigwood hunt --detect=beacon,dns`),或者排除
(`sigwood hunt --detect='all,!syslog'`)。每个检测器也可以作为它自己的子命令运行:
`sigwood beacon ~/zeek`。
## sigwood 与 RITA / AC-Hunter
如果你了解 [RITA](https://github.com/activecm/rita)(或者其商业版本
AC-Hunter),就会对这种 beacon 狩猎的目标感到熟悉 - 两者都在 Zeek 日志中狩猎 C2,
并且 RITA 在这方面非常出色。sigwood 在理念而非野心方面有所不同:它没有
数据库,也没有导入步骤(它直接在原地读取 Zeek - 以及 Pi-hole、syslog 和 CloudTrail),它跨越多个
日志家族,而不仅仅是 conn/dns,它为还没见过的日志提供了一个用于熟悉环境
的命令(`digest`),并且它在报告本身上指出了每个发现背后的技术。如果你已经在专用的
Zeek 传感器上运行了 RITA,请保留它 - sigwood 适用于那些日志已经存在的主机,以及
希望用一个轻量级工具处理所有日志的分析师。
## 运行机制
```
discover & parse → allowlist (suppress) → detect → render
```
职责不会跨越这条界限。**加载器**(loader)负责查找文件、解压、
将每个连接源标准化为统一的 schema,并吸收存储方式上的差异
(TSV 与 NDJSON,扁平目录与按日期分区的目录,轮转)。**白名单**(allowlist)在
分析*之前*抑制已知的正常流量。**检测器**(Detectors)只负责分析 - 它们从不打开文件、
读取配置或进行抑制。**输出处理程序**(Output handlers)只负责渲染。CLI 是唯一一个
将错误转化为可操作信息并管理退出码的地方。
因为检测器是纯分析工具,所以每一个都可以像普通的
Python 函数一样被导入和调用 - 当你想在 notebook 中进行实验时非常有用。
### 分析时间窗口
当指向一个**目录**时,未加限定符的运行会回顾过去 `default_window`
(默认为 `7d`)的*该源自身的*数据 - 这对于你不希望每次都完整读取的实时日志目录来说是
正确的默认设置。当指向一个**单个文件**时,它会读取整个
文件。可以通过以下方式覆盖任何一种设置:
```
sigwood --since=7d ~/zeek # last 7 days
sigwood --since=2026-05-01 --until=2026-05-08 ~/zeek
sigwood --days=2-4 ~/zeek # 2 to 4 days ago
sigwood --all ~/zeek # the entire archive
```
CloudTrail 是唯一选择退出默认时间窗口的来源 - 新颖性检测需要
完整的历史记录,因此除非你明确缩小范围,否则它总是全量加载。
时间以你的本地时区进行渲染并会照此标明。传入 `--utc`(或在
配置中设置 `use_utc = true`)以改为使用 UTC 渲染 - 该设置还会将无时区偏移的
`--since`/`--until` 日期和 `--days` 日界线视为 UTC,导出功能的无时间范围
默认窗口也会受其影响。带有明确偏移量的日期(`--since=2026-05-01T09:00+02:00`)
始终按输入原样执行。无论哪种情况,`json` 输出始终是 ISO-8601 UTC 格式。
## 在狩猎前先熟悉环境:`digest`
```
sigwood digest /var/log/messages
sigwood digest /var/log/pihole/pihole.log # a great first move on a Pi-hole box
sigwood digest conn.log dns.log # several files → several cards
```
`digest` 会对每个文件进行内容嗅探,将其路由到合适的汇总器(conn、dns、syslog、
cloudtrail),对于任何无法识别的内容,则回退到快速的字节分析器 - **blob**。卡片采用左对齐且基于事实:文件的
时间窗口、行数和大小,带有刻度锚定的直方图,以及一些通俗易懂的
见解(“一个客户端占据了 71% 的查询”)。它陈述事实和极端情况,从不给出结论 - 没有“可疑”,没有
“异常”。它在白名单*之前*读取你的数据,因为文件中的所有内容,
无论是否在白名单中,都是“这里有什么”的一部分。Blob 分析器是有边界的:它对大型
文件进行采样而不是完整读取,因此一个 1GB 的未知文件消耗的时间与 1KB 的文件
相同。
## 安装
在所有地方都是同一个名字:PyPI 发行版、命令、导入包和
配置部分都叫 `sigwood`。需要 **Python 3.11+**。
推荐的安装方式是 [pipx](https://pipx.pypa.io),它为 sigwood 提供了自己的
隔离环境,并将命令放在你的 PATH 中 - 并且避开了直接使用 `pip install` 在
Debian 12+、Raspberry Pi OS、Ubuntu 23.04+ 和 Fedora 上遇到的
`externally-managed-environment` 拒绝(PEP 668):
**Debian / Raspberry Pi OS / Ubuntu**
```
sudo apt install pipx
pipx ensurepath # once - then reopen your shell
pipx install sigwood
sigwood --help
```
**Fedora**
```
sudo dnf install pipx
pipx ensurepath
pipx install sigwood
sigwood --help
```
**macOS (Homebrew)**
```
brew install pipx
pipx ensurepath
pipx install sigwood
sigwood --help
```
更喜欢 [uv](https://docs.astral.sh/uv/)?`uv tool install sigwood` 在
uv 支持的任何平台上都能完成相同的工作。普通的 virtualenv 也可以工作
(`python3 -m venv venv && venv/bin/pip install sigwood`;最小化的 Debian 可能需要
先运行 `sudo apt install python3-venv`)。应该避免的做法是:`sudo pip install` - 它不能
绕过 PEP 668,并且无论如何都会污染系统 Python。使用
`pipx upgrade sigwood`(或在你的 venv 中运行 `pip install -U sigwood`)进行升级。
可选的附加组件(在 pipx 或 pip 下拼写相同):
```
pipx install 'sigwood[all]' # fast + splunk + cloudtrail (recommended)
pipx install 'sigwood[splunk]' # Splunk exporter
pipx install 'sigwood[cloudtrail]' # CloudTrail (S3) exporter
pipx install 'sigwood[fast]' # force fast-hdbscan for DNS clustering
pipx install 'sigwood[hdbscan]' # stock hdbscan for DNS clustering
pipx install 'sigwood[pdf]' # PDF reports - opt-in, see note below
```
在人们通常运行此工具的平台上,无需 C 编译器即可进行裸安装。在 64 位机器上(x86-64 和
aarch64/arm64,包括 64 位 Raspberry Pi OS),sigwood 会从纯 wheel 包安装 `fast-hdbscan`;
在 32 位 ARM(armv7l/armv6l)上,它会从 piwheels 保留标准的 `hdbscan`。该
工具在每次包含 dns 检测器的运行中都会指明当前启用的聚类后端。预计在小型机器上的*第一*次
运行会很慢:科学计算栈的冷导入加上一次性的 numba JIT
预热在 Raspberry Pi 上可能需要几分钟的时间,这两者都会缓存在磁盘上 - 之后的每次
运行都会很快。`[fast]` 依然是强制使用 `fast-hdbscan` 的稳定方式,而 `[hdbscan]`
会安装标准的 `hdbscan`(用于 32 位 ARM,并可在 64 位上进行校准/测试)。
如果同时存在这两个后端,sigwood 会优先选择 `fast-hdbscan`。
`[pdf]` 特意与 `[all]` 分开,因为它需要两样东西:python 包
(`pip install 'sigwood[pdf]'`)以及 WeasyPrint 渲染所需的本地文本库
(Pango, HarfBuzz, fontconfig),这些是 `pip` 无法安装的。使用你平台的包
管理器添加它们 - 在 macOS 上使用 `brew install pango`,在 Linux 上使用 `apt install libpango-1.0-0`(或 `dnf install pango`)。其他所有格式无需额外设置即可使用。
从源码构建:
```
git clone https://github.com/helixmap/sigwood
cd sigwood
python3 -m venv .venv # Python 3.11+
.venv/bin/pip install -e '.[all]'
```
## 配置配置是可选的 - sigwood 无需任何配置即可针对路径运行。当你想让操作
可重复时,`sigwood init` 会查看你机器上的常规位置,分析它
找到的内容(哪些日志家族、大致大小、新鲜度 - 仅读取文件的足够部分以识别其格式,绝不读取其内容),
并在 `~/.sigwood/`(如果是系统级安装,则为 `/etc/sigwood`)下写入一个带有注释的
配置。你可以随时重新运行它:它会提议合并到现有配置中(每个提示都会显示
你已经设置了什么 - 按 Enter 键保留;合并操作永远不会破坏你已经
拥有的设置)或重置它,并且无论哪种方式,它都会在写入之前
显示将要更改的内容摘要。
配置会从以下位置中的第一个加载:
1. `--config=FILE`
2. `~/.sigwood/config.toml`
3. `/etc/sigwood/config.toml`
sigwood 拥有的一切都位于隐藏的 `~/.sigwood/` 目录下 - 配置、白名单、
导出、报告 - 因此它不会与项目目录发生冲突。一个精简的示例:
```
[sigwood]
detect = "all" # "all" | "dns,beacon" | "all,!syslog"
zeek_dir = "/var/log/zeek"
syslog_dir = "/var/log"
# pihole_dir = "/var/log/pihole"
# cloudtrail_dir = "/var/log/cloudtrail"
home_net = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
default_window = "7d" # lookback for a directory; "" or "all" = full
output_format = "text" # text | json | csv | html | pdf
```
默认情况下,发现结果会打印到你的终端 - 保持其可通过管道传输。设置 `report_dir`(或传入
`--out=PATH`)以写入报告文件。检测器暴露的每个可调参数都作为注释掉的“机房”记录在
生成配置的底部(你极少需要用到它),并且
`sigwood --help` 会列出该命令的标志。
## 支持的日志来源
- **Zeek** - `conn.log`、`dns.log`、`syslog.log`,NDJSON 或 TSV 格式,来自扁平目录或
按日期分区的子目录。轮转和 gzip/bzip2/xz 压缩会被透明地处理。
- **Pi-hole / dnsmasq** - DNS 事件日志,按域名聚合以进行聚类。
- **syslog** - 扁平的 RFC 3164。发现机制是通过内容嗅探,而不是文件名匹配,因此它
可以同时处理 Debian 约定(`syslog`、`auth.log`、`kern.log`)和 RHEL/Fedora
约定(无扩展名的 `messages`、`secure`、`maillog`) - 并且不会把 `dnf.log` 或像
`wtmp` 这样的二进制文件误认为是日志流。
- **CloudTrail** - gzip 压缩的 JSON 事件记录,在本地读取或从 S3 拉取(见下文)。
## 白名单
sigwood 在分析**之前**进行过滤:已知的无害流量会在任何
检测器看到它之前被丢弃,因此信号不会被日常基础流量淹没。白名单文件有两种类型:
- **扁平文件 = 抑制。** 每行一个规则 - IP、CIDR、`:port/proto` 或
域名 glob/正则表达式。匹配的流量会在任何检测器运行之前被丢弃。
- **TOML 配置段 = 分类。** 当检测器需要知道某个东西*是什么*
(DNS 服务器、备份客户端)而不是是否要丢弃它时使用。
sigwood 附带三个精选的**域名**列表,可通过名称切换:
| 列表 | 默认 | 覆盖范围 |
|------|---------|--------|
| `common` | 开启 | 广泛的互联网基础设施 - CDN、云、NTP、证书验证、公共 DNS、操作系统更新通道 |
| `devices` | 开启 | 消费级 IoT / 智能家居主机的对外通信 |
| `homelab` | 关闭 | 自托管工具(Splunk、Proxmox、UniFi 等) - 需主动开启,因为屏蔽你正在运行的产品会造成真正的盲点 |
不包含任何广告、跟踪或特定于目的地的内容 - 因为各人看法不同,你可能希望看到
这些内容。sigwood 绝不附带数字连接抑制规则(这些取决于你的主机,
附带它们可能会隐藏真实的发现)。
使用 `allowlist` 命令检查和管理它:
```
sigwood allowlist # what's loaded, each list's on/off state and size
sigwood allowlist show common # the patterns in a list
sigwood allowlist enable homelab # turn a shipped list on (writes [allowlist.lists])
sigwood allowlist disable common # …or off
sigwood allowlist copy common # fork a shipped list into your allowlist.d to edit
```
开关也可以直接在配置的 `[allowlist.lists]` 下设置;对于单次运行,可以使用
`--no-allowlist` 关闭整个白名单,或者通过 `enabled = false` 永久关闭。每次检测
运行都会在运行摘要横幅中披露其覆盖情况(`allowlist: suppressed 1,284 connections
(12%) and 312 domains (59%)` - 被抑制的已加载行(按类型)占比,因此
惊人的抑制率可以一目了然),所以抑制操作永远不是静默的。
在 `~/.sigwood/allowlist.d/` 下的任何 `domains_*` 文件中添加你自己的列表(附带的
`domains_user` 是一个入门文件)。插入文件始终是**附加的**,并在升级后保留;要
替换附带的列表,请将其 `disable` 并添加你自己的。插入文件不带有扩展名,因此像
`domains_user.bak` 这样带有点的副本将不会被加载(读取输出会提示你重命名它);要安静地
搁置废弃的列表,请添加尾部 `~` 或去掉 `domains_`/`connections_` 前缀。格式错误的正则表达式行会被跳过,并
提示指明其文件和行号,而不会导致崩溃,因此一个拼写错误不能
使一次运行崩溃或静默地禁用列表的其余部分。没有端点的纯主机 IP 会抑制
涉及该主机的*所有*流量 - 功能强大但很危险,无论在
哪里出现都会被明确指出。
## 导入日志:导出器
sigwood 可以从外部系统获取日志到本地文件,然后它会像
分析任何其他源一样对其进行分析 - syslog 检测器无法分辨数据是来自 rsyslog 还是
Splunk 导出。
```
sigwood export splunk # run the configured "default" query
sigwood export splunk auth # run the configured named query: "auth"
sigwood export cloudtrail # pull logs from S3
```
- **Splunk** - `[export.splunk.query.]` 下命名的 SPL 查询。首选
使用 `SIGWOOD_SPLUNK_USER` / `SIGWOOD_SPLUNK_PASS` 环境变量,而不是
在配置中使用明文凭据,但 sigwood 不会评判你。
- **CloudTrail** - 从 S3 前缀拉取 gzip 压缩的 JSON。AWS 身份验证在此处*不*进行
处理:你需要验证你的 shell 身份,然后由 boto3 解析环境凭据链。
sigwood 绝不会读取、存储或提示输入 AWS 凭据,并会在大量
数据传出前发出警告。
## 输出格式
根据你对发现结果的处理方式来选择 - `--format=NAME`(或在配置中设置
`output_format`):
- **`text`**(默认) - 针对终端的分组、汇总报告,带有每个检测器
的表格,显示每个发现背后的信号。
- **`html`** - 相同的报告,带有相同的每个检测器的信号表格,作为一个自包含的
带样式文件,你可以将其在浏览器中打开、打印或分享。无需额外依赖;包含深色模式和
打印样式。
- **`pdf`** - 将 html 报告渲染成 PDF(一个渲染器,两种输出)。可选开启:
`pip install 'sigwood[pdf]'`,加上本地文本库(Pango/HarfBuzz/fontconfig
- 参见上方的安装说明)。宽报告会横向打印,宽单元格会换行而不是被裁剪。
- **`json`** - 无损的机器数据流:带有 `run_summary` 和 `findings` 的单个对象,
类型正确,适合 `jq` 或 SIEM,始终包含完整集合。包含 `schema_version`。
- **`csv`** - 补救工作清单:每个发现占一行,包含后续步骤、“原因”,
以及空的 `status`/`notes` 列,方便你在处理项目时进行追踪。
`text`、`html` 和 `pdf` 是阅读视图 - 它们显示相同的内容,并遵循 `-v`(精选的
“为什么这样评分”)和 `-vv`(原始调试:模板字符串、聚类成员资格、完整
证据)。`json` 和 `csv` 始终携带完整集合。
**输出去向。** 每种文本格式 - 包括 `html` - 默认情况下都会打印到标准输出;重定向
或使用管道进行保存(`sigwood dns -f=html > report.html`)。`pdf` 是二进制格式,因此它需要
一个目的地:管道(`-f=pdf > report.pdf`)或文件。设置 `--out=PATH` 或 `report_dir` 来写入
文件;目录目标会自动命名为 `sigwood-report__`(单个检测器,否则
为 `-plusN`)并报告其写入的路径。即使设置了 `report_dir`,`-o=-` 也会
强制输出到标准输出。
## 从源码构建并运行测试
```
git clone https://github.com/helixmap/sigwood
cd sigwood
python3 -m venv .venv # Python 3.11+
.venv/bin/pip install -e '.[dev]'
.venv/bin/python -m pytest
```
`main` 分支保持可运行状态。架构测试涵盖了重要的边界 - 检测器
发现、运行计划、加载器元数据、白名单抑制、输出注册和
CLI 错误格式化。
## 致谢
sigwood 基于数学的检测 - 用于 beacon 周期性的 FFT,用于 DNS 行为的无监督聚类
- 灵感来自 David Hoelzer 的 SANS SEC595。这些技术本身(FFT、
HDBSCAN、drain3)属于公共领域的数学和开源库;此实现
是独立且原创的,任何错误均由本人承担。sigwood 不隶属于 SANS 或
GIAC,也未得到它们的认可。
## 许可证
sigwood 采用 [MIT 许可证](https://github.com/helixmap/sigwood/blob/main/LICENSE) 授权。
标签:Blue Team, IP 地址批量处理, Python, 安全, 插件系统, 无后门, 聊天机器人, 超时处理, 逆向工具