TsekrekosEA/NetWatch

GitHub: TsekrekosEA/NetWatch

NetWatch是一个结合统计基线与机器学习的双阶段网络入侵检测系统,支持实时流量分析、威胁情报富化及可视化监控。

Stars: 2 | Forks: 0

# NetWatch — 网络异常检测与入侵检测系统 一个两阶段的网络入侵检测系统,结合了统计基线与 ML 异常评分、实时 WebSocket 流、IP 威胁情报充实,以及 Prometheus/Grafana 可观测性堆栈——基于真实的数据包捕获和 CIC-IDS-2018 基准数据集构建。 ![演示](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/4972be7c84074150.png) ## 架构 ![图表](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/3a9147c657074152.png) ## 工作原理 ### 阶段 1 — 统计基线检测 每个传入的网络流都表示为一个 20 维特征向量(字节数、数据包速率、到达时间间隔、TCP 标志分布)。包含最近 1,000 个流的滚动窗口会维护每个特征的均值和标准差。任何特征偏离基线超过 3.5 个标准差的流都会被标记。这可以立即捕获基于流量的攻击(端口扫描、SYN 洪水、DoS),且无需任何训练数据。 ### 阶段 2 — ML 分类器 在 CIC-IDS-2018 数据集上训练了两个模型: - **Isolation Forest** (无监督):仅使用良性流量进行训练。模拟一个点能多容易地与正常行为的集群隔离——异常点通常很容易被隔离。低于 `IF_THRESHOLD` 的分数会触发警报。 - **Random Forest** (有监督):在所有 14 个标记的攻击类别上进行训练。为已知签名提供特定的攻击分类。低置信度预测(低于 `RF_CONFIDENCE_THRESHOLD`)会被抑制以减少误报。 这两个阶段是互补的:阶段 1 会立即捕获流量异常;阶段 2 会捕获从流量上看正常但基于模式的攻击(慢速扫描、暴力破解、C2 信标)。 ### 警报速率限制 在可配置的时间窗口(`ALERT_RATE_LIMIT_SECONDS`)内,对同一 `(src_ip, category)` 对的重复警报会被抑制。抑制表限制为 5,000 个条目,并采用 LRU 淘汰机制。 ### IP 威胁情报 当打开警报详情模态框时,NetWatch 会实时充实源 IP 信息: - 通过 ip-api.com 获取 **GeoIP**(无需 API 密钥):国家、地区、城市、ISP、组织、ASN - **AbuseIPDB**(可选,设置 `ABUSEIPDB_API_KEY`):滥用置信度分数(0–100%)、报告数量、Tor 出口节点标记 - 结果在内存中缓存 1 小时;跳过私有/RFC-1918 地址 ### 可观测性 - **Prometheus** 每 10 秒抓取一次 `/metrics` - **Grafana** 附带一个预配置的 NetWatch 仪表板,每 10 秒自动刷新一次: - 流量/秒、警报/分钟、速率受限计数、ML 加载状态、活跃的 WS 连接数 - 时间序列:按协议分类的流量、按严重程度分类的警报 - 百分位延迟(p50 / p95 / p99) - 饼图:按检测阶段、按严重程度、按攻击类别 ## 技术栈 | 层级 | 技术 | 原因 | |---|---|---| | 数据包捕获 | Scapy + libpcap | 可脚本化,跨平台 | | 流量引擎 | Python + NumPy | 完全控制特征提取 | | 阶段 1 | 统计 (z-score) | 快速、可解释、无需训练 | | 阶段 2 | scikit-learn (IF + RF) | 标准、易于理解、可导出 | | 数据集 | CIC-IDS-2018 | IDS 研究的学术标准 | | 警报存储 | SQLite (WAL 模式) | 零依赖、便携、写入速度快 | | 后端 | FastAPI | 异步、原生支持 WebSocket | | 实时推送 | WebSocket | 低延迟警报流 | | 威胁情报 | ip-api.com + AbuseIPDB | GeoIP 充实、无需强制密钥 | | 可观测性 | Prometheus + Grafana | 行业标准、预配置 | | 前端 | React + TypeScript + Vite | 包含 Recharts 的实时仪表板 | | 容器 | Docker + docker-compose | 一条命令运行所有内容 | | 测试 | pytest + pytest-asyncio | 50 个测试涵盖流水线、模型、API | ## 快速开始 — 演示模式 ``` # 1. 克隆并配置 cp .env.example .env # 2. 启动所有服务(backend、capture、frontend、prometheus、grafana) docker compose up --build # 3. 打开 Dashboard open http://localhost:5174 # 4. 打开 Grafana(admin / netwatch) open http://localhost:3000 ``` 演示模式生成合成的良性流量(约 50 个流/分钟),并定期注入攻击(端口扫描、SYN 洪水、SSH 暴力破解、DNS 洪水)——无需 root 权限或实时网络。 ## 快速开始 — 实时捕获模式 ``` # 1. 配置以进行实时捕获 cp .env.example .env # 编辑 .env:设置 DEMO_MODE=false, INTERFACE= # 2. 启动(capture 服务需要 NET_ADMIN 以使用 raw sockets) docker compose up --build # 3. 打开 Dashboard open http://localhost:5174 ``` ## 快速开始 — PCAP 重放模式 通过完整的检测管道重放录制的 `.pcap` / `.pcapng` 文件: ``` # 1. 配置 cp .env.example .env # 编辑 .env: # DEMO_MODE=false # REPLAY_PCAP=/data/your-capture.pcap # REPLAY_SPEED=10.0 (10倍实时速度;0 = 尽可能快) # REPLAY_LOOP=true (循环以进行持续演示) # 2. 将你的 PCAP 挂载到 docker-compose.yml 中的 capture 容器里: # volumes: # - ./your-capture.pcap:/data/your-capture.pcap # 3. 启动 docker compose up --build ``` PCAP 重放遵循真实的包间时间(由 `REPLAY_SPEED` 缩放),因此检测管道可以看到真实的流持续时间和到达间隔统计信息。 ## 训练 ML 模型 ML 阶段是可选的——当模型不存在时,系统仅使用统计检测运行。要启用 ML 分类: ``` # 1. 下载 CIC-IDS-2018(说明请参阅 data/README.md) # 将 CSV 文件放置在 data/ 目录中 # 2. 训练模型 cd backend pip install -r requirements.txt python3 -m ml.train # 3. 评估 python3 -m ml.evaluate # 4. 模型将保存到 backend/ml/models/ 并在启动时自动加载 ``` ## 运行测试 ``` cd backend pip install pytest pytest-asyncio httpx python3 -m pytest tests/ -v ``` 跨 6 个文件的 50 个测试: | 文件 | 涵盖范围 | |---|---| | `test_stage1.py` | 滚动基线 z-score 检测、预热、严重性阈值、异常分类 | | `test_stage2.py` | ML 分类器加载、预测、置信度门控、类别→严重性映射 | | `test_severity.py` | 严重性组合逻辑、阶段合并、未知异常回退处理 | | `test_pipeline.py` | 警报速率限制和去重 | | `test_models.py` | 数据库插入/查询、分页、按严重性/类别/IP 筛选 | | `test_api.py` | REST 端点响应、认证令牌强制执行、CSV 导出、统计端点 | ## 性能指标 在来自 CIC-IDS-2018 数据集的 **4,089,895 个流**上进行训练(80/20 的训练/测试拆分): ### Random Forest (有监督多分类) | 指标 | 值 | |---|---| | 总体准确率 | **90.91%** | | 加权 F1 分数 | **0.91** | | 良性误报率 | **3.21%** | 按类别细分: | 类别 | 精确率 | 召回率 | F1 | |---|---|---|---| | Benign | 1.00 | 0.97 | 0.98 | | DDoS | 0.72 | 0.94 | 0.82 | | DoS | 0.78 | 0.63 | 0.69 | ### Isolation Forest (无监督异常检测) | 指标 | 值 | |---|---| | 误报率 | **0.96%** | | 检出率 | 0.19%(预期值——仅在良性基线上训练) | ## 环境变量 ### 后端 | 变量 | 默认值 | 描述 | |---|---|---| | `CAPTURE_TOKEN` | `change-me-in-production` | 捕获和后端之间的共享认证令牌 | | `ML_MODELS_PATH` | `./ml/models` | 训练好的模型文件的路径 | | `LOG_LEVEL` | `INFO` | 日志详细程度 | | `STAT_THRESHOLD` | `3.5` | 统计异常的 Z-score 阈值 | | `ROLLING_WINDOW_SIZE` | `1000` | 滚动基线窗口中的流数量 | | `STAT_WARMUP` | `30` | 统计检测激活前的最少样本数 | | `SEVERITY_MEDIUM_THRESHOLD` | `3` | 中等 (MEDIUM) 严重性的异常特征数量 | | `SEVERITY_HIGH_THRESHOLD` | `6` | 高 (HIGH) 严重性的异常特征数量 | | `IF_THRESHOLD` | `-0.2` | Isolation Forest 异常分数截止点 | | `RF_CONFIDENCE_THRESHOLD` | `0.4` | 信任分类的最低 RF 概率 | | `ALERT_RATE_LIMIT_SECONDS` | `10` | 在此窗口内抑制重复的 (src_ip + category) 警报 | | `ABUSEIPDB_API_KEY` | _(空)_ | 可选 — 在威胁情报中启用 AbuseIPDB 置信度评分 | ### 捕获服务 | 变量 | 默认值 | 描述 | |---|---|---| | `DEMO_MODE` | `true` | 启用合成流量生成 | | `REPLAY_PCAP` | _(空)_ | 用于重放模式的 PCAP 文件路径(优先于演示模式) | | `REPLAY_SPEED` | `10.0` | 重放速度乘数(1 = 实时,0 = 最快速度) | | `REPLAY_LOOP` | `false` | 连续循环 PCAP 文件 | | `INTERFACE` | `eth0` | 用于实时捕获的网络接口 | | `BPF_FILTER` | `ip` | 传递给 Scapy 的 BPF 过滤器表达式 | | `FLOW_TIMEOUT` | `120` | 空闲流过期并发出前的秒数 | | `MAX_FLOW_PACKETS` | `10000` | 强制发出前每个流的最大数据包数 | ### 前端 | 变量 | 默认值 | 描述 | |---|---|---| | `VITE_API_URL` | `http://localhost:8001` | 后端 REST API 基础 URL | | `VITE_WS_URL` | `ws://localhost:8001` | 后端 WebSocket 基础 URL | ## 服务端口 | 服务 | 主机端口 | 备注 | |---|---|---| | 后端 | **8001** | 内部端口 8000 | | 前端 | **5174** | 内部端口 5173 | | Prometheus (Prometheus) | **9090** | | | Grafana | **3000** | 登录凭据:`admin` / `netwatch` | ## API 参考 | 方法 | 端点 | 描述 | |---|---|---| | `POST` | `/ingest` | 从捕获服务接收流(需要 `X-Capture-Token`) | | `GET` | `/alerts` | 分页的警报历史——筛选条件:`severity`、`category`、`src_ip`、`since`、`until`、`limit`、`offset` | | `GET` | `/alerts/recent` | 最近 N 条警报 | | `GET` | `/alerts/export` | 带可选筛选条件(`severity`、`category`、`src_ip`、`until`)的 CSV 导出 | | `GET` | `/stats/summary` | 仪表板摘要统计 | | `GET` | `/stats/timeline` | 按分钟分桶的流量/警报时间线 | | `WS` | `/ws/alerts` | 实时警报 + 统计流(JSON、`alert` 和 `stats_update` 消息类型) | | `GET` | `/threats/intel/{ip}` | 针对某个 IP 地址的 GeoIP + AbuseIPDB 威胁情报 | | `GET` | `/health` | 服务健康检查——ML 加载状态、运行时间、已处理流 | | `GET` | `/metrics` | Prometheus 抓取端点 | ## 项目结构 ``` netwatch/ ├── docker-compose.yml # Orchestrates all 5 services ├── .env.example # Environment configuration template │ ├── capture/ # Packet capture + flow engine │ ├── main.py # Entrypoint: demo / live capture / PCAP replay │ ├── capture.py # Scapy live sniffer (BPF filter + SIGTERM) │ ├── flow_engine.py # 5-tuple flow assembly (bounded to 50K flows) │ ├── features.py # 20-dimension feature extraction │ ├── publisher.py # Async HTTP publisher (background queue, non-blocking) │ ├── demo_traffic.py # Synthetic traffic + attack pattern injection │ └── pcap_replay.py # PCAP replay with speed multiplier + optional loop │ ├── backend/ # FastAPI backend │ ├── main.py # App entrypoint + lifespan + /health + /metrics │ ├── config.py # All settings via pydantic-settings + env vars │ ├── database.py # SQLite async with WAL mode │ ├── metrics.py # Prometheus counters / gauges / histogram │ ├── enrichment.py # IP threat intelligence (GeoIP + AbuseIPDB, LRU cache) │ ├── models/alert.py # DB operations: insert, query, paginate, filter │ ├── schemas/ # Pydantic schemas (FlowData, AlertOut) │ ├── routers/ │ │ ├── ingest.py # POST /ingest — flow ingestion │ │ ├── alerts.py # GET /alerts, /alerts/recent, /alerts/export │ │ ├── ws.py # WS /ws/alerts — live streaming │ │ └── threats.py # GET /threats/intel/{ip} │ ├── detection/ │ │ ├── pipeline.py # Two-stage orchestrator + alert rate limiter │ │ ├── stage1_statistical.py # Z-score rolling baseline │ │ ├── stage2_ml.py # IF + RF with confidence gating │ │ └── severity.py # Severity scoring + stage combination logic │ ├── ml/ │ │ ├── train.py # Train on CIC-IDS-2018 │ │ ├── evaluate.py # Compute and print metrics │ │ └── preprocess.py # Column alignment + label simplification │ └── tests/ # pytest test suite (50 tests) │ ├── conftest.py │ ├── test_stage1.py │ ├── test_stage2.py │ ├── test_severity.py │ ├── test_pipeline.py │ ├── test_models.py │ └── test_api.py │ ├── frontend/ # React + TypeScript dashboard │ ├── src/ │ │ ├── api/client.ts # Axios instance (reads VITE_API_URL) │ │ ├── hooks/ │ │ │ ├── useAlertStream.ts # WebSocket hook with reconnect backoff │ │ │ └── useStats.ts # Polling hook (summary + timeline, loading state) │ │ ├── pages/Dashboard.tsx # Main layout — modal state, filters, tab state │ │ └── components/ │ │ ├── AlertFeed.tsx # Live scrollable alert list + expand/collapse │ │ ├── AlertToolbar.tsx # Severity filter buttons, IP search, CSV export │ │ ├── AlertDetailModal.tsx # Forensic modal: flow metadata, z-score chips, │ │ │ # ML details, IP threat intel, related alerts │ │ ├── StatsBar.tsx # Summary cards (flows, alerts, rate-limited, ML) │ │ │ # + inline sparkline charts │ │ ├── TrafficChart.tsx # Area chart with gradient fills + legend │ │ ├── ProtocolBreakdown.tsx # Protocol/category pie chart │ │ ├── ThreatHeatmap.tsx # Attack category bar chart with gradient fill │ │ ├── SeverityBadge.tsx # Severity chip — CRITICAL pulses with red glow │ │ ├── CriticalAlertToast.tsx # Fixed top-right toasts for CRITICAL alerts │ │ ├── ErrorBoundary.tsx # React error boundary with dark fallback UI │ │ └── Skeleton.tsx # Shimmer loading placeholders │ └── index.html │ ├── infra/ │ ├── prometheus/ │ │ └── prometheus.yml # Scrape config: backend:8000/metrics every 10s │ └── grafana/ │ ├── provisioning/ │ │ ├── datasources/prometheus.yml │ │ └── dashboards/dashboards.yml │ └── dashboards/ │ └── netwatch.json # Pre-built Grafana dashboard │ └── data/ # CIC-IDS-2018 CSV files (gitignored) └── README.md # Dataset download instructions ``` ## 20 维特征向量 每个网络流都表示为一个固定长度的数值向量——这是 ML 阶段和统计基线的相同输入: | # | 特征 | 描述 | |---|---|---| | 1 | `duration` | 流持续时间(秒) | | 2 | `total_fwd_packets` | 转发包数量 | | 3 | `total_bwd_packets` | 后向包数量 | | 4 | `total_fwd_bytes` | 转发字节数量 | | 5 | `total_bwd_bytes` | 后向字节数量 | | 6 | `fwd_packet_rate` | 每秒转发包数 | | 7 | `bwd_packet_rate` | 每秒后向包数 | | 8 | `fwd_byte_rate` | 每秒转发字节数 | | 9 | `bwd_byte_rate` | 每秒后向字节数 | | 10 | `mean_iat_fwd` | 平均到达时间间隔(转发) | | 11 | `std_iat_fwd` | 到达时间间隔标准差(转发) | | 12 | `mean_iat_bwd` | 平均到达时间间隔(后向) | | 13 | `std_iat_bwd` | 到达时间间隔标准差(后向) | | 14 | `syn_flag_count` | TCP SYN 标志 | | 15 | `ack_flag_count | TCP ACK 标志 | | 16 | `fin_flag_count` | TCP FIN 标志 | | 17 | `rst_flag_count` | TCP RST 标志 | | 18 | `psh_flag_count` | TCP PSH 标志 | | 19 | `mean_packet_length` | 平均数据包大小(字节) | | 20 | `std_packet_length` | 数据包大小的标准差 | ## 许可证 MIT
标签:Apex, API集成, C2通信检测, CIC-IDS-2018, CISA项目, DoS攻击检测, Grafana, IP 地址批量处理, NIDS, WebSocket, 依赖分析, 免杀技术, 入侵检测系统, 可观测性, 威胁情报, 孤立森林, 安全数据湖, 容器化, 开发者工具, 插件系统, 数据流处理, 暴力破解检测, 机器学习, 深度学习, 特征工程, 端口扫描检测, 统计基线, 网络安全, 网络异常检测, 自定义请求头, 请求拦截, 逆向工具, 随机森林, 隐私保护, 零日攻击防御