diagonalciso/soc-ops
GitHub: diagonalciso/soc-ops
基于 Wazuh 的轻量级自托管 SOC 工作台,集成 AI 告警分析、案例管理和威胁情报富化功能。
Stars: 0 | Forks: 0
# SOCops
Wazuh 的 AI 辅助 SOC 工作台。轻量级、自托管、单进程 Python 应用 —— 除了 Anthropic SDK 和 pyTelegramBotAPI 外无其他外部依赖。
运行在单个 Linux 主机上。连接到 Wazuh/OpenSearch,将告警存储在 SQLite 中,并在 8081 端口上提供深色主题的 Web UI。
## 功能
### 告警队列 (`/`)
- 每 60 秒从 Wazuh 拉取实时告警队列
- 状态生命周期:`new` → `ack` | `escalated` | `fp` | `suppressed`(重新打开为 `new`)
- **类别筛选器**:全部 / Systemd / 完整性 (FIM) / CIS / Web / Windows
- **状态筛选器**:全部 / 新 / 已升级 / Ack / FP
- **分组视图**:在独立告警和分组视图之间切换(折叠相同规则 + 相同 agent,显示 ×N 计数)
- 通过 Claude Haiku 对每个告警进行 AI 分析(如果没有 API key/credits 则回退到基于规则的 stub)
- 源 IP 上的威胁情报风险徽章(AbuseIPDB + OTX)
- 将告警分配给分析师
- 添加带有完整时间戳记录的备注;状态更改会自动记录
- 从操作栏将告警添加到案例
- 可点击的 agent 名称 / 源 IP 可打开 24 小时实体时间线
### 仪表板 (`/dashboard`)
每 5 分钟更新一次的 Chart.js 面板:
- 随时间变化的告警严重程度(柱状图)
- 按告警数量排名的 Top agent(柱状图)
- MITRE ATT&CK 战术分布(环形图)
- CIS 合规性仪表盘(通过 / 失败 / 错误率)
### 案例 (`/cases`)
- 创建命名的安全事件容器(标题、严重程度、描述)
- 将多个告警链接到一个案例
- 案例状态生命周期:`open` → `in_progress` → `resolved` → `closed`
- 案例详情显示所有链接的告警
### 抑制规则 (`/suppressions`)
- 定义在接入时自动抑制嘈杂告警的规则
- 匹配项:`rule_id`、`agent_name`、`srcip`、`rule_description`
- 运算符:`equals`、`contains`、`starts_with`
- 可选的过期日期;命中计数器显示每条规则已抑制了多少告警
- 告警详情中的“⊘ 抑制”按钮会从当前告警自动预填表单
### 指标 (`/metrics`)
- **KPI 卡片**:MTTR、FP 率、24 小时数量、积压时长、升级率
- **每小时数量迷你图**:过去 24 小时按小时统计的告警数
- **Top agent 表**:按告警数量排名的前 5 个 agent(过去 7 天)
- **嘈杂规则表**:按 FP 率排名的检测规则(红色 > 50%,橙色 > 30%)
- **MITRE ATT&CK 覆盖率**:14 战术网格,显示过去 7 天内触发了哪些战术
- **检测规则库**:包含总计/ack/fp/escalated 计数的完整规则表,可排序
## 要求
- Python 3.10+
- 可通过 HTTPS 访问的 Wazuh 和 OpenSearch Dashboards
- `anthropic` Python 包(可选 —— 用于 Claude API 分析)
- `pyTelegramBotAPI`(可选 —— 用于 Telegram bot)
```
pip3 install anthropic pyTelegramBotAPI --break-system-packages
```
### 通过 Ollama 使用本地 AI(出于隐私推荐)
SOCops 支持通过 Ollama 进行本地 LLM 分析 —— 无需 API key 或互联网,并且**告警数据永远不会离开您的网络**。对于担心将安全事件数据发送到第三方云 API 的环境,这是首选方案。
最简单的入门方法是 [AnythingLLM Desktop](https://anythingllm.com),它自带了 Ollama 实例 —— 安装后即可直接使用 Ollama,无需额外设置。
**设置:**
1. 安装 AnythingLLM Desktop 并启动它(Ollama 运行在 `http://127.0.0.1:11434`)
2. 拉取模型 —— 针对此用例推荐:
curl -s http://127.0.0.1:11434/api/pull -d '{"name":"qwen2.5:3b"}' # 快速,~20s/告警
curl -s http://127.0.0.1:11434/api/pull -d '{"name":"qwen3:8b"}' # 质量更高,~75s/告警
3. 在 `.env` 中设置:
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen2.5:3b
**分析调度顺序:** Ollama → OpenRouter → 基于规则的 stub
**GPU 注意事项:** 如果您的 GPU VRAM 小于 6 GB,Ollama 将报 CUDA OOM 错误。SOCops 会自动强制使用 CPU 推理(`num_gpu: 0`)来避免这种情况。
**思考模型:** `qwen3:8b` 支持 `think: true` 以进行更深入的推理,但需要快速的 CPU —— 预计每个告警至少需要 75 秒。
## 配置
将 `.env.example` 复制到 `.env` 并填入相应值:
```
# 必填项
WAZUH_HOST=your.wazuh.host # Wazuh/OpenSearch host
WAZUH_USER=changeme # OpenSearch user
WAZUH_PASS=yourpassword # OpenSearch password
# App 设置
SOCOPS_PORT=8081
POLL_INTERVAL=60 # Wazuh poll interval (seconds)
INITIAL_WINDOW=now-24h # How far back to fetch on first run
# AI 分析 — 设置一个或多个(如果已配置,则优先尝试 Ollama)
ANTHROPIC_API_KEY=sk-ant-... # Claude Haiku (cloud)
OLLAMA_BASE_URL=http://127.0.0.1:11434 # Local Ollama (AnythingLLM or standalone)
OLLAMA_MODEL=qwen2.5:3b # Model to use (must be pulled first)
# Threat intel 富化(可选)
OTX_KEY= # AlienVault OTX API key
ABUSEIPDB_KEY= # AbuseIPDB API key (1000 lookups/day free)
# 出站通知(可选)
NOTIFY_WEBHOOK= # Slack / ntfy / generic webhook URL
NOTIFY_EMAIL= # Recipient email for high-severity alerts
SMTP_HOST= # SMTP server hostname
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
NOTIFY_LEVEL=12 # Minimum rule level to trigger notification
```
## 运行
### 直接运行
```
cd /path/to/soc-ops
env WAZUH_HOST=your.wazuh.host WAZUH_USER=changeme WAZUH_PASS='yourpassword' \
SOCOPS_PORT=8081 ANTHROPIC_API_KEY='sk-ant-...' \
python3 app.py
```
或者使用 `.env` 文件:
```
env $(cat .env | grep -v '^#' | xargs) python3 app.py
```
### 作为 systemd 服务运行
```
# 首先使用真实凭据编辑 .env
sudo cp soc-ops.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now soc-ops
sudo journalctl -u soc-ops -f
```
该服务单元通过 `EnvironmentFile=` 从 `.env` 读取凭据。
## 架构
```
Browser → http://:8081
↓
Python ThreadingHTTPServer (app.py)
├─ GET / → Alert queue (HTML)
├─ GET /dashboard → Wazuh dashboard (HTML)
├─ GET /cases → Case management (HTML)
├─ GET /suppressions → Suppression rules (HTML)
├─ GET /metrics → KPIs + MITRE heatmap (HTML)
├─ GET /api/alerts → Alert list JSON (?status=&category=&group_key=&rule_id=&since=)
├─ GET /api/alerts/ → Single alert + analysis + enrichment
├─ POST /api/alerts//action → {action, notes, assigned_to}
├─ GET /api/alerts//notes → Notes thread
├─ POST /api/alerts//notes → Add note
├─ GET /api/stats → Queue statistics
├─ GET /api/groups → Grouped alert view (?status=&category=)
├─ GET /api/kpis → SOC KPI metrics
├─ GET /api/mitre → MITRE tactic coverage
├─ GET /api/rules → Detection rule stats
├─ GET /api/timeline → Entity timeline (?agent=|?ip=&hours=)
├─ GET /api/enrich/ → On-demand IP enrichment
├─ GET /api/suppressions → List suppression rules
├─ POST /api/suppressions → Create suppression rule
├─ DELETE /api/suppressions/ → Delete rule
├─ GET /api/cases → List cases
├─ POST /api/cases → Create case
├─ GET /api/cases/ → Case detail + alerts
├─ POST /api/cases//alerts → Link alert to case
├─ POST /api/cases//action → Update case status
├─ GET /api/export/alerts.csv → CSV export (?status=&category=&since=7d)
├─ GET /api/export/alerts.json → JSON export
└─ GET /api/data → Dashboard chart data (5-min cache)
↓ background threads
_poller() — every 60s: fetch new Wazuh alerts → SQLite, check suppression, notify
_analyst_worker() — continuous: AI analysis for unanalyzed alerts (highest level first)
_enrichment_worker()— every 30s: enrich srcIPs via AbuseIPDB + OTX (1 IP/sec rate limit)
↓
wazuh.py WazuhClient → OpenSearch at WAZUH_HOST:443
db.py SQLite → soc-ops.db
analyst.py → Ollama (local) → OpenRouter → rule-based stub
enrichment.py → AbuseIPDB + OTX APIs
notifier.py → Webhook + SMTP email
```
## 文件布局
| 文件 | 作用 |
|---|---|
| `app.py` | 主服务器 —— 所有路由、后台线程、所有页面的内联 HTML/CSS/JS |
| `db.py` | SQLite schema、CRUD 助手、抑制引擎 |
| `wazuh.py` | WazuhClient —— OpenSearch 查询、噪声过滤 |
| `analyst.py` | 分析引擎:Ollama → OpenRouter → 基于规则的 stub |
| `enrichment.py` | IP 威胁情报:AbuseIPDB + OTX |
| `notifier.py` | 出站告警:webhook + SMTP 邮件 |
| `soc-ops.service` | systemd unit 文件 |
| `.env.example` | 配置模板 |
| `soc-ops.db` | SQLite 数据库(自动创建,不在 git 中) |
## 数据库 Schema
```
alerts — main alert store (Wazuh hits + SOC workflow state)
alert_notes — timestamped notes thread per alert (analyst + auto-generated)
cases — incident containers
case_alerts — many-to-many: alerts ↔ cases
suppression_rules — ingest-time suppression conditions
settings — key/value store (last_poll_time, etc.)
```
关键告警字段:`wazuh_id`、`timestamp`、`agent_name`、`agent_ip`、`rule_id`、`rule_level`、`rule_description`、`rule_groups`、`mitre_technique`、`mitre_tactic`、`srcip`、`status`、`group_key`、`analysis`、`enrichment`、`assigned_to`、`operator_notes`、`full_json`。
## 噪声过滤
匹配以下内容的告警将在接入时被丢弃(绝不存储):
- VirusTotal 频率限制 / 无记录错误
- PAM 登录会话开启/关闭
- SSH 身份验证成功
- Wazuh agent/manager/server 启动消息
在 `wazuh.py` → `NOISE_MUST_NOT` 中配置其他过滤器。
## 告警类别
| 类别 | 规则组匹配 |
|---|---|
| Systemd | `rule_groups LIKE '%systemd%'` |
| 完整性 | `rule_groups LIKE '%syscheck%'` (FIM + 注册表) |
| CIS | `rule_groups LIKE '%sca%'` |
| Web | `rule_groups LIKE '%web%'` |
| Windows | `rule_groups LIKE '%windows%'` |
## Telegram Bot
位于 `telebot/` 的独立 bot,可让您通过手机与 Claude 聊天。
```
cd /path/to/telebot
# 编辑 .env:添加 TELEGRAM_BOT_TOKEN 和 ANTHROPIC_API_KEY
python3 bot.py
```
命令:`/clear` 重置历史记录 · `/model` 显示当前使用的模型 · `/myid` 显示您的 Telegram 用户 ID。
仅限您的账户使用:在 `.env` 中设置 `ALLOWED_USER_ID=`。
## Wazuh 连接
- 主机:`WAZUH_HOST` 端口 443 (OpenSearch Dashboards)
- 认证:通过 `POST /auth/login` 获取 session cookie
- 查询:过去 N 小时的告警,根据最低规则级别和噪声排除进行过滤
- FIM 路径排除:`*/.cache/*`、`*/tmp/*`
标签:AI风险缓解, Python, Wazuh, 告警管理, 安全运营, 扫描框架, 无后门, 逆向工具