jtshor14899/threat-dash

GitHub: jtshor14899/threat-dash

一款面向家庭实验室的开源威胁情报仪表板,将入站流量、出站归属、威胁情报与终端安全整合在单一可视化界面中。

Stars: 0 | Forks: 0

# threat-dash [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![Docker](https://img.shields.io/badge/docker-ready-2496ed?logo=docker)](./Dockerfile) [![Python](https://img.shields.io/badge/python-3.12-3776ab?logo=python&logoColor=white)](./Dockerfile) [![stdlib only](https://img.shields.io/badge/python%20deps-stdlib%20%2B%202-success)](./Dockerfile) [![Issues](https://img.shields.io/github/issues/jtshor14899/threat-dash)](https://github.com/jtshor14899/threat-dash/issues) [![Stars](https://img.shields.io/github/stars/jtshor14899/threat-dash?style=social)](https://github.com/jtshor14899/threat-dash/stargazers)

threat-dash hero
(Run scripts/seed-demo-data.py to populate a copy with realistic synthetic data — see SCREENSHOTS.md.)

## 目录 - [功能简介](#what-it-does) - [截图展示](#screenshots) - [同类对比](#how-it-compares) - [快速开始](#quick-start) - [拦截后端](#block-backends) - [终端节点可见性 (Wazuh)](#endpoint-visibility-wazuh) - [部署模式](#deployment-patterns) - [架构](#architecture) - [配置说明](#configuration) - [API 提供商 — 免费与收费](#api-providers--whats-free-whats-not) - [REST + SSE 接口](#rest--sse-endpoints) - [性能表现](#performance) - [安全性](#security) - [路线图](#roadmap) - [贡献指南](#contributing) - [许可证](#license) ## 功能简介 Threat-dash 监控四个方面,并将它们整合到一个实时视图中: 1. **入站流量** — 访问您 Cloudflare zone 的请求。每一个 WAF 事件,每一次 被拦截 / 验证 / 允许的请求,每一次 Cloudflare Access 登录 尝试,经过 GeoIP 丰富处理后,通过动态弧线投影到 3D 地球仪上, 指向您的 homelab。 2. **出站流量** — 您的容器正在向外请求的内容。sidecar 从 每个容器的 netns 读取 `/proc/net/tcp`,进行去重,并将 目标地址输入到同一个地图中(颜色不同,方向不同)。 3. **威胁情报** — 每个出站目的地都会自动与 GreyNoise、Censys、Shodan 以及(按需)VirusTotal 进行比对丰富。🛰 情报页面 展示完整的主机配置文件:开放服务、软件栈、TLS 证书、 SSH banner、WHOIS、DNS、CVE、威胁评分汇总。 4. **终端节点** — 来自 **Wazuh** SIEM/XDR 管理器的 agent 清单、漏洞发现和 FIM 事件。 基于严重程度分类的单个 agent CVE 钻取分析;整个集群的状态 KPI。参见 [docs/WAZUH.md](docs/WAZUH.md)。 您还将获得: - 在 Cloudflare 边缘 *或* **pfSense** 防火墙上**点击拦截** (基于别名,无需为每个 IP 单独创建规则 — 参见 [docs/PFSENSE.md](docs/PFSENSE.md))。 - **区域攻击面** — 选择一个区域(`country:US state:CA`, `country:DE`,`asn:13335`,任何可用于 Shodan 过滤的参数)并查看有多少 主机暴露了 SSH / RDP / SMB / Redis / Mongo / Kibana / Docker API / Modbus / MQTT / Elasticsearch / VNC 等。点击任意行即可深入查看 分面细分 — 主要组织、ASN、产品、版本、操作系统、 城市、CVE — 所有这些都在 Shodan 的 **免费 `oss` 层级**上。 - **按容器划分的流量归属** — 哪个容器在何时、通过哪个 端口与哪个 IP 进行了通信。 - **抽屉式导航** — 页眉下方的水平标签栏;点击 标签会在右侧弹出一个滑出式抽屉,显示该部分的内容。 地球仪在主视图中始终保持全屏显示,直到您需要查看详细信息。 - **浅色和深色主题**,**可调整大小的抽屉**,**键盘快捷键** (`1`-`6` 切换标签,`T` 切换主题,`R` 刷新,`Esc` 关闭抽屉,`F` 实时流)。 - **仅使用 stdlib 的 Python 服务器** — `http.server` + `sqlite3` + `urllib` + `maxminddb` + `cryptography`。没有 Flask,没有 SQLAlchemy,没有 Celery。 - **原生 JS 前端** — 使用 globe.gl + three.js 实现 3D 视图。客户端总计约 150 KB。 无构建步骤,无 node_modules。 ## 截图展示 以下所有截图均来自通过 `scripts/seed-demo-data.py` 填充演示数据的副本 — 无需真实的 Cloudflare / Censys / GreyNoise / Shodan / VT 凭据即可 复现它们。截图获取方法请参见 [SCREENSHOTS.md](docs/SCREENSHOTS.md)。
Overview tab — globe centered on the contiguous US with top-attacker country breakdown
Overview — animated globe + top-attacker country list, opened in the right-side drawer
Traffic tab — per-container outbound destinations
Traffic — per-container outbound destinations, ranked
Blocks tab — active rules from both Cloudflare and pfSense backends
Blocks — Cloudflare and pfSense rules in one list, backend-badged
Endpoints tab — Wazuh agent inventory with KPI strip and per-agent drilldown
Endpoints — Wazuh agent fleet, status KPIs, CVE drilldown NEW
Outbound Intel page — enriched destination IPs
Outbound Intel — GreyNoise / Censys / Shodan / VT enrichment
Settings UI showing Cloudflare, pfSense, and Wazuh configuration sections
Settings — every credential & toggle (Cloudflare, Shodan, Censys, GreyNoise, pfSense, Wazuh) editable at runtime, no restart. Env vars win and are marked locked.
## 同类对比 | 工具 | 功能 | threat-dash 的增值之处 | | --- | --- | --- | | [CrowdSec](https://crowdsec.net/) | 基于行为的 IPS,社区订阅源 | 3D 地球仪 + 出站可见性 + 在 CF 边缘点击拦截,替代 iptables | | Cloudflare dashboard | 数据本身 | 单一面板涵盖入站 + 出站 + 情报,带有实时流和按容器划分的流量归属 | | [Shodan](https://shodan.io/) | 互联网规模的扫描数据 | 我们*消费* Shodan;我们并不取代它。结合您自己的出站列表,提供基于目的地的情报 | | [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) | LAN 设备发现 | 范围不同 — WYL 是 L2 清单,threat-dash 是 L7 / 外部 | | [Grafana + Cloudflare Loki](https://grafana.com/) | DIY 仪表板 | Threat-dash 就是仪表板本身。无需编写 PromQL/LogQL | ## 快速开始 ``` # 1. clone git clone https://github.com/jtshor14899/threat-dash.git cd threat-dash # 2. fill in API tokens (Cloudflare required for inbound data; # Censys / GreyNoise / VT / Shodan optional but make the Intel page sing) cp .env.example .env $EDITOR .env # 3. fetch the free GeoIP databases (~50 MB total, monthly refresh) ./scripts/setup-geoip.sh # 4. up docker compose up -d --build # 5. (optional) seed with realistic synthetic data so the UI is interesting # before any real Cloudflare events trickle in: docker compose exec threat-dash python /scripts/seed-demo-data.py ``` 仪表板现在位于 `http://127.0.0.1:5959/`。**不要将 5959 公开暴露** — 请使用以下部署模式之一作为前端。 ## 拦截后端 | 后端 | 规则所在位置 | 模式 | 设置 | | ------------- | ------------------------ | ---------------------------------- | ----- | | **Cloudflare**| Zone IP Access Rules | 拦截、验证(3 种方式)、允许| 默认 — 使用您现有的 `CF_DASH_TOKEN`。 | | **pfSense** | 您 pfSense 上的主机别名| 拦截、允许 | [docs/PFSENSE.md](docs/PFSENSE.md) — 需要安装 `pfSense-pkg-RESTAPI` 软件包。 | 各个后端相互独立 — 您可以运行其中一个,或另一个,或者同时连接 两者。拦截标签页的下拉菜单允许您为每个规则进行选择。 ## 终端节点可见性 Threat-dash 接入 **Wazuh** SIEM/XDR 管理器,在专用的 **终端节点** 标签页中展示 agent 清单、漏洞发现和文件完整性事件。严格只读 — 拦截决策仍然通过 Cloudflare 或 pfSense 执行;Wazuh 仅用于提供可见性,而非执行。 | 后端 | 展示内容 | 您将获得什么 | 设置 | | -------- | --------------- | ------------------------------------------------------------ | ----- | | **Wazuh**| Manager REST API| agent 清单、状态 KPI、按 agent 划分的 CVE 钻取分析、FIM | [docs/WAZUH.md](docs/WAZUH.md) — 适用于任何 Wazuh 4.x 管理器(单节点 `wazuh-docker` 是最快捷的途径)。 | 内置的内存模拟器意味着您无需搭建 真实的 Wazuh 即可试用终端节点标签页:`docker compose -f docker-compose.yml -f docker-compose.mock.yml up -d`。 ## 部署模式 为 homelab 爱好者实际运行的架构量身定制的方案。选择一个; 所有方案均位于 [`examples/`](./examples) 目录下。 | 模式 | 适用场景 | TLS | 身份验证 | 是否公开? | | --- | --- | --- | --- | --- | | **[仅限局域网](./examples/lan-only-no-proxy/)** | 首次试用 / 受信任的 LAN+VPN | ❌ | 无 | 否 | | **[Tailscale sidecar](./examples/tailscale-sidecar/)** | 您已经在使用 Tailscale | ✓ | tailnet ACLs | 否(通过 Funnel 则为是) | | **[Traefik](./examples/traefik/)** | 已经在使用 Traefik(*arr/Jellyfin 架构) | ✓ Let's Encrypt | forward-auth | 可选 | | **[Caddy](./examples/caddy/)** | 已经在使用 Caddy | ✓ Let's Encrypt | forward-auth | 可选 | | **[Nginx Proxy Manager](./examples/nginx-proxy-manager/)** | 您喜欢 NPM 图形界面 | ✓ Let's Encrypt | NPM 访问列表 | 可选 | | **[Cloudflare Tunnel](./examples/cloudflare-tunnel/)** | 无需端口转发的公开访问 | ✓ CF 边缘 | Cloudflare Access SSO | **是** ✓ | | **[Authelia / Authentik](./examples/authelia-forward-auth/)** | 您运行自己的 SSO | 取决于代理 | TOTP/WebAuthn | 可选 | **推荐大多数 homelab 使用**:`tailscale-sidecar`(最快捷)或 `cloudflare-tunnel + cloudflare-access`(最完善,对公开暴露安全)。 ## 架构 ``` ┌──── Cloudflare edge ────┐ ┌──── Wazuh manager ────┐ │ GraphQL Analytics │ │ REST API :55000 │ │ Firewall events │ │ agents / vulns / FIM │ │ Access audit log │ │ JWT auth, cached │ └────────────┬────────────┘ └──────────┬─────────────┘ │ │ ▼ 60s poll ▼ on-demand ┌──────────────────────────────────────┐ ┌──────────────────┐ │ collector.py (background thread) │ │ wazuh_client.py │ │ + outbound_collector.py (sidecar) │ │ (per-request) │ └────────────────────┬─────────────────┘ └────────┬─────────┘ ▼ │ ┌──────────────────────────────────────┐ │ │ GeoIP / ASN (DB-IP Lite mmdb, free) │ │ │ Auto-enrich (GreyNoise + Censys) │ ← 5/tick │ └────────────────────┬─────────────────┘ │ ▼ │ ┌─── SQLite (WAL, /data) ────┐ │ │ events, blocks, recon │ │ │ vt_cache, scans, settings │ │ └──────────────┬─────────────┘ │ ▼ │ ┌──────────────────────────────────────────────────┴─────┐ │ server.py — stdlib http.server │ │ REST + Server-Sent Events on :5959 │ └─────┬───────────────────────┬───────────────────────────┘ ▼ ▼ ┌────────────────────┐ ┌──────────────────────┐ │ Cloudflare API │ │ pfSense REST API v2 │ │ IP Access Rules │ │ host-alias mutate │ │ (per-IP rules) │ │ + apply │ └────────────────────┘ └──────────────────────┘ ▲ ▲ │ click-to-block │ └───── from any IP row ─┘ your reverse proxy ▼ browser (globe.gl + drawer UI) ``` ## 配置说明 配置 threat-dash 有两种方式 — 请选择适合您工作流程的一种: 1. **通过设置界面**(页眉中的 ⚙ 图标,或按 `,` 键)。在 仪表板中编辑 API token、homelab 品牌信息、自身流量检测和出站规则。 更改在下次 API 调用时生效 — 无需重启容器。 密钥在**传输过程中会被掩码处理**(只有最后 4 个字符会离开 服务器)。每个提供商的“测试”按钮会在数据源验证每个 token。 2. **通过 `.env`**(经典方式)。环境变量始终优先于界面设置的值 — 设置页面会将它们显示为“被环境变量锁定”。现有部署 不受影响。 完整列表请参见 [`.env.example`](./.env.example)。重点如下: | 变量 | 是否必需? | 备注 | | --- | --- | --- | | `CF_DASH_TOKEN`, `CF_ZONE_ID`, `CF_ACCOUNT_ID` | 用于入站 | Cloudflare API。作用域记录在 `.env.example` 中。 | | `HOMELAB_LAT`, `HOMELAB_LON`, `HOMELAB_LABEL` | 推荐 | 地球仪上的图钉位置 + 页眉中的品牌文本 | | `VT_API_KEY` | 可选 | VirusTotal v3 免费层(每天 500 次查询) | | `SHODAN_API_KEY` | 可选 | 免费 `oss` 层 — 区域攻击面 + 分面钻取 | | `CENSYS_TOKEN` | 可选 | Censys Platform PAT(按主机丰富数据,免费) | | `CENSYS_API_ID` + `CENSYS_API_SECRET` | 可选 | Censys Search v2(每月 250 次查询,免费) | | `GREYNOISE_API_KEY` | 可选 | 社区版无需 key 即可工作;认证可提升速率限制 | | `SELF_EMAILS`, `SELF_IPS`, `SELF_ASN_PREFIXES` | 可选 | 隐藏您自己的流量 | | `OUTBOUND_EXTRA_RANGES` | 可选 | 逗号分隔的 CIDR,将其视为内部网络 | | `DEMO_MODE` | 可选 | `1` 禁用所有实时轮询 — 用于截屏 | ## API 提供商 — 免费与收费 | 提供商 | 免费 | 付费要求 | | --- | --- | --- | | **VirusTotal** | 每天 500 次 v3 查询 | 更高配额,深度搜索 | | **Censys Platform** | 按主机丰富数据 (PAT) | 搜索、聚合 | | **Censys Search v2** | 每月 250 次搜索查询 | 批量结果,更高配额 | | **GreyNoise** | 社区分类(每天 50 次,无需 key) | RIOT 背景,深度搜索 | | **Shodan** | `/host/count` + 分面(`oss` 计划) | `/host/`, `/host/search` | 任何您没有提供 key 的功能都会在界面中隐藏,并带有 解释原因的提示。Threat-dash 始终会平滑降级 — 您甚至仅使用 Cloudflare + DB-IP 运行,依然能获得一个有用的仪表板。 ## REST + SSE 接口 UI 是基于轻量级 REST API 构建的瘦客户端: ``` GET /api/stats?range=24h&self=hide&direction=in|out GET /api/arcs?range=24h&limit=400 GET /api/events?range=24h&limit=200 GET /api/intel/outbound?range=24h&limit=250 GET /api/signins?range=24h GET /api/containers?container=&range=24h GET /api/blocks POST /api/block {ip, mode?, reason?, expires_at?} DEL /api/blocks/ PATCH /api/blocks/ {mode?, reason?, expires_at?} GET /api/recon/status GET /api/shodan/surface?base= GET /api/shodan/drill?base=&category= GET /api/shodan/host/ GET /api/censys/host/ GET /api/recon/search?q=&per_page=25 GET /api/greynoise/ GET /api/vt/{ip,domain,hash,url}/ POST /api/scan {ip, profile=common|extended, force?} GET /stream Server-Sent Events GET /healthz 200 ok (used by HEALTHCHECK) ``` 这对于将 threat-dash 脚本化集成到更大的 SOAR 类工作流中非常有用 — 例如,通过 Slack 的斜杠命令 拦截一系列 IP。 ## 性能表现 前端经过精心优化,以确保不会使您的浏览器卡顿: - SSE 事件在每个 200 ms 的 rAF 周期中进行批量处理(不会针对每个事件重新渲染)。 - 无论数据流速度如何,地球仪的重绘频率都限制在约 3 fps。 - 当数据特征未改变时,`renderStats` 会短路跳出。 - 当 `document.hidden` 时,定期刷新频率会降至 2 分钟一次。 - 所有列表更新均使用 `DocumentFragment` + `replaceChildren`。 Python 服务器: - 单进程,多线程 `HTTPServer`。每个 SSE 客户端都会获得一个有界的 `queue.Queue`,因此缓慢的消费者不会导致广播阻塞。 - 采用 SQLite WAL 模式,写操作使用单个 `threading.Lock`;读操作 非同步。 - 出站数据丰富处理的速率限制为每周期(每 60 秒)5 个 IP,因此 免费层级的 API 配额不会因突然出现的大量新 目的地而被耗尽。 在一台普通的 VM(2 vCPU / 2 GB)上,每天处理约 6 万个事件,RSS 占用约为 80 MB。 ## 安全性 Threat-dash 是一款安全工具。它理应遵循高标准。 - **切勿在没有前置身份验证的情况下公开暴露 5959 端口。** 系统中没有 用户模型。任何获取了 URL 的人都可以在您的 Cloudflare 边缘拦截 IP。 - 以 **非 root** 用户(UID 1000)运行,采用多阶段构建镜像,丢弃了所有 Linux 权限,并设置了 `no-new-privileges:true`。 - 对 `/healthz` 执行 `HEALTHCHECK`,以便编排器在其卡死时能及时发现。 - 出站 TCP 扫描仪由 **操作员手动触发**,仅执行连接 + banner 抓取 — 没有 漏洞利用路径。请确认在您所在的司法管辖区内进行扫描是否合法。 - `.env` 已被 git-ignore;每季度轮换一次 Cloudflare token。 完整的威胁模型 + 加固检查清单位于 [`docs/SECURITY-HARDENING.md`](./docs/SECURITY-HARDENING.md)。 报告漏洞:[`SECURITY.md`](./SECURITY.md)。 ## 路线图 - [ ] 为没有使用自己的代理作为前端的用户提供内置的 basic-auth / 代理标头认证 - [ ] 保存查询捆绑包(“每周区域攻击面差异比对”) - [ ] 在达到威胁评分阈值时触发 ntfy / Slack / Discord webhook - [ ] 将出站 CVE 与您镜像的 Trivy SBOM 扫描结果进行交叉比对 - [ ] 将镜像发布到 GHCR,实现拉取而非构建的部署 - [ ] 接入更多提供商:AbuseIPDB、AlienVault OTX、IPinfo Lite 如果您想支持某项功能或提出不同的建议,请提交一个 issue。 ## 许可证 [MIT](./LICENSE)。运行时的 DB-IP Lite 数据库由 [db-ip.com](https://db-ip.com) 提供,基于 CC-BY 4.0 协议。 由 homelab 运维者为 homelab 运维者打造。如果它帮助您 免受僵尸网络的凭证撞库攻击,请[⭐ 给仓库点星][stars] — 这是我们仅有的营销预算。
标签:AppImage, Docker, PB级数据处理, Python, Web应用防火墙, 可视化仪表板, 威胁情报, 安全运维, 安全防御评估, 家庭实验室, 开发者工具, 数据可视化, 无后门, 请求拦截, 逆向工具