FabulaNox/agentic-soc-triage
GitHub: FabulaNox/agentic-soc-triage
基于本地小模型的 SOC 告警分诊代理,通过 L1-L2-人类三层架构自动过滤 SIEM 噪音,只将真正需要关注的告警交给人工处理。
Stars: 0 | Forks: 0
# 智能 SOC 分诊
**一个本地 LLM SOC 分析师,负责对家庭实验室 SIEM 的夜间告警进行分诊,因此人类只需关注真正需要人类处理的内容。**
[为什么使用 Agent](#why-an-agent-not-just-a-filter) · [分诊层级](#the-l1---l2---human-tiers) · [运行说明](#run-it) · [NoxLab 的一部分 ↗](https://github.com/FabulaNox/NoxLab)
[](LICENSE)
一个**本地 LLM SOC 分析师**,负责对家庭实验室 SIEM 的夜间告警进行分诊,因此人类只需关注真正需要人类处理的内容。一个 **L1 agent**(一个本地小模型)对每个高危/严重告警进行分类,关闭显而易见的误报,随时间学习良性模式,并**仅将其无法解决的问题升级**给 **L2** 审核者(Claude),然后再交给我。它完全在本地机器上的入门级 GPU 上运行,完全免费。
它的存在是因为家庭实验室的 SIEM 会产生*大量*噪音——即使在空闲时,它也会接收约 160,000 个事件——而且手动进行早间分诊(或者通过按 token 付费给云端模型,将安全遥测数据发送到外部)无法规模化扩展。

## 目录
- [为什么使用 Agent,而不仅仅是过滤器](#why-an-agent-not-just-a-filter)
- [L1 -> L2 -> 人类 分诊层级](#the-l1---l2---human-tiers)
- [包含内容](#whats-here)
- [运行说明](#run-it)
- [Agent 生成的产物](#what-the-agent-produces)
- [截图](#screenshots)
- [设计说明](#design-notes)
## 为什么使用 Agent,而不仅仅是过滤器
SOC 分诊的难点不在于数量,而在于**关联判断**:“这条规则触发了 200 次”毫无意义,除非你知道这是游戏会话、扫描器还是补丁爆发。因此,L1 阶段是一个真正的 agent,而不是正则表达式:
- **它按顺序根据上下文进行推理。** prompt 告诉模型首先检查*关联规则*,然后是*已知模式*,接着是*当天的首要规则 + 最近的报告*以查找关联活动——这模仿了分析师实际进行分诊的方式。
- **在不需要判断时保持低成本。** 在任何模型调用之前,两个短路机制会确定性地关闭告警:一个无条件良性规则 ID 列表,以及一个 CVE 预检,当受影响的包刚刚安装且*已经是最新可用版本*时,该预检会关闭漏洞告警(存在 CVE,无上游补丁 = 无需操作)。
- **随着时间推移变得更敏锐。** 模型识别出的良性模式会被标准化(IP 转换为 `/24`)并追加到下一次运行加载的**关联记忆**中——并提交到笔记库中,从而将学习过程版本化。
- **基于我自己的笔记进行基础设定。** **RAG 查找**会针对每个规则在知识库中运行,因此模型在决定之前会看到类似“*规则 5710 预计来自 VPN 网段 - 良性*”的信息。
- **它知道自己的局限性。** 任何被它分类为 `SUSPICIOUS`/`UNKNOWN` 且超过阈值的告警都会触发 **L2 升级**——它从不自行裁定安全事件。
## L1 -> L2 -> 人类 分诊层级
| 层级 | 负责者 | 运行方式 | 任务 |
|---|---|---|---|
| **L1** | `gemma4:e4b` (本地,每夜,免费) | 每天晚上 | 过滤 + 总结,关闭显而易见的告警,**绝不进行裁定** |
| **L2** | Claude (按需) | 仅针对 L1 无法解决的少数告警 | 审核升级的告警,记录结论 |
| **人类** | 我 | 随时 | 最终决定 |
每次 L1 运行都会向**基准 CSV** 中记录一行数据(包含其决定、耗时,以及用于后续 L2 结论的一列),以便随着时间的推移将 L1 的决策与 L2 进行对比衡量——该模型是被问责的,而不是被盲目信任的。
在实践中,大多数早晨都是 **L1-only**:agent 关闭所有告警,我只需阅读摘要。L2 是例外——仅在其标记出无法解决的问题时才启用——因此最近的报告通常完全显示如下所示的 L1 输出。
## 包含内容
```
scripts/soc-agent.sh the L1 agent (3 stages: classify, assemble, escalate)
soc-agent.conf.example config: model, paths, known-rule short-circuits, thresholds
examples/
sample-daily-report.md a report before/after the agent runs (the injected L1 block)
gemma-soc-memory.example.md the self-updating correlation memory format
assets/ where the dashboard / alert screenshots go (see assets/README.md)
```
## 运行说明
```
$ soc-agent.sh --report ~/notes/.../security-report-2026-04-09.md
[2026-04-09 06:00:01] Starting SOC agent on: security-report-2026-04-09.md
[2026-04-09 06:00:01] Stage 1: classifying findings...
[2026-04-09 06:02:01] Stage 1 done (120034ms): 6 findings
[2026-04-09 06:02:01] Stage 2: assembling draft...
[2026-04-09 06:03:48] Stage 2 done (107442ms)
[2026-04-09 06:03:48] Stage 3: L2 flag triggered (1 unresolved findings)
[2026-04-09 06:03:48] Injected L1 Analysis block into report
[2026-04-09 06:03:49] Memory updated and committed
[2026-04-09 06:03:49] Done
```
`--dry-run` 会将分析块打印到标准输出,而不是将其注入报告。该 agent 是幂等的:它会跳过已经包含 `## L1 Analysis` 部分的报告。
## Agent 生成的产物
该 agent 会在每日报告中追加一个 **L1 Analysis** 块——包括安全态势、总结、操作项表格、每个告警的结论,以及(如果触发)L2 审核标志。请参阅 [`examples/sample-daily-report.md`](examples/sample-daily-report.md) 获取完整的前后对比;该块如下所示:
```
## L1 分析 (gemma4:e4b - 2026-04-09 06:03)
**Overall Posture:** ELEVATED
Volume normal (~140k events). Dominant pattern is perimeter scan noise on the
edge router (rule 100120), all blocked. One UNKNOWN: an outbound connection from
the Windows lab VM worth a human glance.
### Action Items
| # | Priority | Status | Item | Target |
|---|----------|--------|------|--------|
| 1 | Med | Open | Unexpected outbound from lab VM - confirm benign | win11-lab |
| 2 | Info | L1 Closed | Edge scan noise, blocked at perimeter | router |
### Finding Verdicts
| Finding | Verdict | Inference |
|---------|---------|-----------|
| Rule 100120 on router | KNOWN | Perimeter scan, dropped at firewall - recurring |
| Rule 5710 on win11-lab | UNKNOWN | Outbound to unrecognised host, no vault note |
### 需要 L2 Review
Gemma flagged 1 finding it could not resolve (threshold: 1).
```
## 截图
请参阅 [`assets/README.md`](assets/README.md)。Telegram 实时告警、Wazuh dashboard 和渲染后的每日报告都在那里——已**脱敏**(这些显示了实时的主机/IP,并且图像的像素不受文本脱敏机制的保护,因此在发布前必须手动裁剪/模糊处理)。
## 设计说明
- **本地化、小型、夜间运行是刻意为之。** 本地化将遥测数据保留在设备上(第三方无法看到安全事件,也没有按 token 收费)。`e4b` 足以在入门级 GPU 上进行初步分诊——它负责过滤和总结,不进行裁定。夜间运行利用了 GPU,此时没有其他任务需要它;摘要会在新的一天开始前准备好。
- **它是噪音过滤器和初步总结者,而不是决策者。** 根据设计,升级和裁定由人类完成——本地小模型擅长“显然是良性的/显然值得关注”,并且被限制在这条线的这一侧。
*自托管安全家庭实验室的一部分。规则 ID 是标准的 Wazuh ID;主机、地址和路径已进行抽象处理。*
## 许可证
[MIT](LICENSE) - 配置、脚本和文档可免费改编。标签:AI风险缓解, Cutter, LLM, LLM评估, Metaprompt, Ollama, Unmanaged PE, 告警分诊, 安全运营, 扫描框架, 本地大模型