omarbabba779xx/wazuh-n8n-soc-pipeline

GitHub: omarbabba779xx/wazuh-n8n-soc-pipeline

基于 Wazuh、n8n 和 Gmail API 构建的实时 SOC 告警流水线,通过事件驱动的 webhook 集成实现告警的去重、严重性路由和邮件通知,具备磁盘队列容错机制。

Stars: 0 | Forks: 0

# Wazuh → n8n → Gmail:实时 SOC 告警流水线 一个自托管的安全自动化流水线,可将原始的 Wazuh 检测结果转化为经过严重性分类和去重的邮件告警 —— 在本地 SOC 实验室中完成了端到端的构建与验证,其中包含由真实 Windows 端点生成的实时发现。 ![架构图](https://static.pigsec.cn/wp-content/uploads/repos/cas/c2/c21426346b401f1233c0342996fcea7d74a3a997b329eeec8ca431fa80448d03.png) ## 关于本项目 大多数 Wazuh 到通知的教程都停留在“每隔几秒轮询一次 JSON 文件并转发”的阶段。本项目则恰恰相反:它将 Wazuh 自带的 **Integrator** 模块通过经过身份验证的生产环境 webhook 直接接入 n8n 工作流,因此告警可以实时传输,并在任何人看到之前就完成验证和去重。 当 n8n webhook 在投递时无法访问时,告警会被持久化排队到磁盘,而 systemd 定时器会在 n8n 恢复后自动清空该队列 —— 这是通过在传输中途强行停止 n8n 并确认其自动恢复来测试的。 它是在真实的基础设施上构建、破坏并修复的 —— 包括真正的 Windows 端点 agent、受控的暴力破解模拟、一次意外自我触发的告警,以及在实验室验证期间诊断并解决的一个真实运营问题(合规性扫描引发的告警洪流)。以下每一项声明都有一组匹配的截图作为佐证:一张来自 Wazuh 仪表板,另一张来自收到的邮件,两者具有相同的规则 ID 和相同的时间戳。 **技术栈:** Wazuh 4.14.6(manager + Windows agent) · Docker · n8n 2.31.4(自托管,已固定版本) · Gmail API (OAuth2) · systemd ## 架构 | 阶段 | 组件 | 职责 | |---|---|---| | 1 | **受监控主机** | Linux manager + Windows 端点 agent 生成原始事件:认证日志、sudo 活动、文件完整性变更、合规性检查 | | 2 | **Wazuh Manager** | 解码并分类事件,分配规则 ID 和严重性级别 | | 3 | **Wazuh Integrator** | 自定义脚本在级别 ≥ 7 时触发,使用 secret header token 对请求进行身份认证,并将其 POST 到 webhook —— 这是事件驱动的,而非轮询循环 | | 4 | **n8n Webhook** | 通过 Header-token 进行身份认证的入口,在认证后(在 Normalize/Validate/Gmail 运行之前)立即响应 `202 Accepted`,然后将其移交给处理链 | | 5 | **Normalize** | 将原始告警展平为一致的结构,将规则级别映射为严重性标签 | | 6 | **Validate** | 在格式错误或不完整的 payload 蔓延之前将其拒绝 | | 7 | **Deduplicate** | 跟踪已处理的事件 ID;重复项会被静默丢弃 | | 8 | **Severity Router** | 根据严重性标签进行分支处理;低严重性和明确排除的嘈杂源永远不会生成邮件 | | 9 | **Format** | 构建 HTML 报告;仅凭主题行就足以进行分类甄别 | | 10 | **Gmail Delivery** | 通过经过身份认证的 OAuth2 账户,在专用的发件人身份下发送邮件 | 如果在第 4 阶段无法访问 webhook,告警将被写入本地磁盘队列而不是被丢弃。systemd 定时器每 60 秒重试一次,并在 n8n 恢复的瞬间自动清空队列。 ## 测试用例 以下每个用例都将 Wazuh 端的检测与生成的通知配对 —— 相同的规则 ID,相同的时间戳,从而证明这是端到端的流水线,而不是模拟的演示。 ### 用例 1 — 受控暴力破解检测 在授权的本地实验室内,针对一个不存在的用户进行了受控的 SSH 暴力破解模拟,该行为被 Wazuh 原生检测到(规则 5712,级别 10)并自动转发,无需任何手动干预。
Wazuh dashboard — rule 5712Resulting alert email
### 用例 2 — 验证去重功能 相同的事件 ID 被连续提交了两次。第一次执行运行了通往 Gmail 的完整链路;第二次在去重步骤被干净地过滤掉,从未到达收件箱 —— 一次事件,一次通知。
n8n execution — full chain, first runSingle resulting email
### 用例 3 — 一次意外的、完全真实的告警 在调试 SSH 密钥权限问题时,连续三次 `sudo` 密码输入错误触发了一次真正的 Wazuh 检测(规则 5404,“Three failed attempts to run sudo”),完全没有任何预先编排。它实时到达了收件箱。
Alert email — unplanned, organic triggerThe terminal session that caused it
### 用例 4 — 真实的 Windows 端点,以及一次调优经验 一个真正的 Wazuh agent 被部署在 Windows 11 主机上并连接到 manager。其内置的 Security Configuration Assessment 模块运行了完整的 CIS benchmark 扫描 —— 共 482 项检查,其中 350 项失败,许多处于级别 7 及以上。 由于去重是基于事件 ID 进行的,而每一次单独的检查都有唯一的 ID,因此每一次失败的检查都会产生其独立且有效的告警。按事件 ID 去重对于抑制同一事件的重复传输副本是正确的,但它无法合并来自同一个嘈杂源的、一批真正不同的子事件 —— 这种过滤必须在上游完成,即在 Integrator 或规则组级别,而不是在去重步骤中。流水线的表现与配置完全一致;如此巨大的数量暴露了一个缺失的范围过滤器,而这个数据源原本就没人打算让它去打扰任何人。在这里故意保留这个案例的原因是:一个从未被自身数据压测过的流水线,其实并没有经受过真正的测试。
Resulting inbox volume — rule 19007Matching Wazuh dashboard events
**修复:** 在事件发生期间,首要的行动是在源头阻止这场告警洪流。持久的修复方案 —— 将 `sca` 规则组从实时转发路径中排除,同时保留其在 Wazuh Dashboard 中的可见性以供定期审查 —— 已经在 `wazuh/custom-n8n`(`EXCLUDED_RULE_GROUPS`)中实现,并在事后提交。 ## 经验教训 - **事件驱动优于轮询。** 直接连接 Integrator 使得在所有测试用例中观察到的告警延迟保持在较低的个位数秒内,并且没有浪费周期去重新读取日志文件。 - **去重需要作用域,而不仅仅是键值。** 仅将事件 ID 作为键对于真正的事件是正确的,但是一个嘈杂的源会为每个子检查生成一个新的 ID,从而完全绕过它 —— 修复方案应该属于源过滤器,而不是去重逻辑。 - **只有在中途强行停止服务,停机测试才是真实的。** 在代码中模拟队列行为什么都证明不了;停止容器并观察磁盘队列在重启时自动清空才能说明问题。 - **最好的故障模式是声音响亮的故障。** 合规性扫描引发的告警洪流在几分钟内就被诊断出并找到了根本原因,因为流水线将每个告警都单独展示了出来,而不是默默地吞掉错误。 ## 安全控制 - n8n 生产环境 webhook 需要 header-token 身份验证 —— 而不是嵌入在 URL 中的 token。 - Wazuh Integrator 脚本从 `/var/ossec/etc/n8n_token` (`640`, `root:wazuh`) 读取 token;它从不会被硬编码在脚本中,也不会被记录在日志中。 - Gmail 投递使用 OAuth2 —— 没有以明文形式存储应用密码。 - n8n 仅监听 `127.0.0.1`;远程访问通过 SSH 隧道进行,绝不直接暴露于网络。 - 主机防火墙默认为拒绝(default-deny),并具有限定于所需端口的显式允许规则。 - Secret、token 和凭证 ID 均被排除在此仓库之外(`.gitignore`、`.env.example` 占位符);提交的 n8n 工作流和集成文件使用 `REPLACE_WITH_*` 占位符代替真实的凭证引用。 - 截图在发布前经过了审查;唯一可见的 IP 地址是私有的 RFC1918 实验室地址。 ## 快速开始 有关完整的设置过程,请参阅 [`docs/installation.md`](docs/installation.md);如果某些组件无法正常启动,请参阅 [`docs/troubleshooting.md`](docs/troubleshooting.md)。 ## 测试 [`tests/test-matrix.md`](tests/test-matrix.md) 跟踪了实际已验证的内容与仍然推荐验证的内容。使用 `tests/test-webhook.sh` 和 `tests/` 中的示例 payload 来重现已覆盖的用例。 ## 仓库结构 ``` . ├── README.md ├── .env.example ├── .gitignore ├── docker/ │ └── docker-compose.yml ├── wazuh/ │ ├── custom-n8n │ └── ossec-integration.xml.example ├── n8n/ │ └── wazuh-alert-processing.workflow.json ├── replay/ │ ├── replay-wazuh-n8n.py │ ├── wazuh-n8n-replay.service │ └── wazuh-n8n-replay.timer ├── tests/ │ ├── sample-medium-alert.json │ ├── sample-high-alert.json │ ├── sample-critical-alert.json │ ├── test-webhook.sh │ └── test-matrix.md ├── docs/ │ ├── installation.md │ └── troubleshooting.md └── assets/ ├── architecture.png └── screenshots/ ├── 01-wazuh-dashboard-rule5712.png ├── 02-gmail-alert-rule5712.png ├── 03-n8n-execution-dedup-1st.png ├── 04-gmail-dedup-test.png ├── 05-gmail-organic-rule5404.png ├── 06-terminal-sudo-3fail-trigger.png ├── 07-gmail-sca-flood-rule19007.png └── 08-wazuh-dashboard-sca-rule19007.png ```
标签:Cutter, n8n, Wazuh, 告警通知, 安全运营, 扫描框架, 请求拦截, 逆向工具