DreadpiratePickles/floodlight
GitHub: DreadpiratePickles/floodlight
一款轻量级防御性异常流量检测工具,基于真实时间戳从访问日志或实时抓包中识别 DDoS 洪水与流量尖峰。
Stars: 0 | Forks: 0
# 🌊 Floodlight
### 用于防御性 DDoS 监控的异常流量速率检测。
     
*洪水不会事先宣告。它只会突然降临。*
Floodlight 为你紧盯水位线,这样你就不必死盯着数据包计数,
直到你的灵魂悄悄出窍。它会根据可调的速率阈值*以及*时间尖峰检测器对
数据包/请求流量进行评分,将证据存储在 SQLite 中,
将其呈现为带有颜色编码的终端报告,并且可以提供一个只读的 Web 仪表板。
它是一个**防御性**工具,适用于你**拥有或获得明确授权进行**
监控**的系统**。它从不生成流量、探测或攻击任何东西——它只
观察并评估你所指向的目标。
## 为什么开发它
小团队需要一种轻量级的方式,在*日志变成一团乱麻*且寻呼机响起*之前*
注意到洪水。现成的 DDoS 缓解措施往往比较繁重,且通常
位于 CDN 边缘;Floodlight 则恰恰相反——它是一个单文件支持的 CLI,你可以
在跳板机上运行它来分析访问日志,或者在你控制的接口上嗅探一段时间的实时流量,
并立即获得一个可解释的判定结果:
- **谁**在过度通信(主要通信者,每个源的速率)。
- **总计多少**(相对于你的基准)。
- 流量的**形状是什么**(半开 SYN 洪水,突然的时间尖峰)。
它的构建目的是验证基准、记录事件,并向利益相关者解释异常,
而无需让他们就着冷咖啡阅读原始的数据包转储。
## 工作原理
```
access log / live interface
│
▼
┌───────────────┐ TrafficEvent(timestamp, src_ip, dst_ip,
│ capture / │──▶ protocol, dst_port, length, flags)
│ parse layer │
└───────────────┘
│ list[TrafficEvent]
▼
┌───────────────┐ detect(events, Thresholds):
│ detector │ • aggregate-rate (total per window)
│ (scoring) │ • source-rate (per source per window)
│ │ • syn-flood (SYN without ACK per source)
│ │ • rate-spike (z-score over the rate series)
└───────────────┘
│ list[DetectionAlert] + report dict
├────────────▶ SQLite store (events + alerts) [store.py]
├────────────▶ rich terminal render / pure JSON [ui.py / cli.py]
└────────────▶ Flask dashboard + /api/summary [app.py]
```
### 检测窗口
所有内容都在锚定于最近事件的 `--window` 秒滑动**窗口**内进行评分。
在该窗口内,Floodlight 会检查:
| 告警类型 | 严重程度 | 触发条件… |
| ---------------- | --------- | ----------- |
| `aggregate-rate` | high | 窗口内的事件总数超过 `--max-total`。 |
| `source-rate` | high | 任何单个源超过 `--max-per-source`。 |
| `syn-flood` | critical | 某个源发送了超过 `--max-syn-per-source` 个无 ACK 的 SYN 事件(典型的半开握手特征)。 |
| `rate-spike` | medium | 最繁忙的窗口比每个窗口速率序列的平均值高出 `--spike-sigma` 个标准差,**并且**至少是其两倍(统计突发检测——捕获从未超过绝对上限的急剧尖峰)。 |
### 访问日志时间戳(正确性说明)
Floodlight 会解析**真实的 Common/Combined Log Format 时间戳**
(`[20/Jun/2026:13:55:36 +0000]`),因此检测窗口测量的是真实的秒数,
而不是“最后 N 行”。没有可解析时间的行会沿用
前一个时间戳;完全没有时间戳的文件将回退到
以行号作为秒数,这样该工具依然能执行合理的操作。
### 内置加固
- **授权门控。** `monitor`(用于嗅探接口)和非环回网络上的
`serve` 在没有明确的 `--i-am-authorized` 确认
或 `FLOODLIGHT_AUTHORIZED=1` 的情况下拒绝运行。
- **恶意输入处理。** 访问日志被视为受攻击者影响的:
大小限制(`--max-bytes`,默认 200 MiB)和行数限制(`--max-lines`)
阻止巨大的/恶意的文件耗尽服务器内存 (OOM);截断会在
标准错误输出 (stderr) 上公布,绝不静默处理。
- **安全的默认设置。** 仪表板绑定到 `127.0.0.1`;进一步暴露它是
受到门控和警告的。响应包含 `Content-Security-Policy`、
`X-Content-Type-Options`、`X-Frame-Options`、`Referrer-Policy`。
- **无秘密,无堆栈跟踪。** 错误以单行可操作信息的形式呈现。
- **输入验证。** 窗口/阈值必须为正数;错误的值会被
解析器拒绝并附带清晰的消息,而不是产生异常行为。
## 安装
```
cd floodlight
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e . # provides the `floodlight` entry point
cp .env.example .env # optional: pre-set thresholds / auth
```
实时捕获 (`monitor`) 还需要 **Scapy** 和操作系统捕获
权限(Linux 上的 root / `CAP_NET_RAW`,或者 Windows 上带有 Npcap 的提权 shell)。
离线的 `analyze-log`、`summary` 和 `serve` 无需 Scapy 即可工作。
## 用法
全局标志(在子命令**之前**或**之后**使用均可):`--db PATH`、
`--plain`、`--no-color`、`--no-banner`。系统会自动遵循
`NO_COLOR` 和非 TTY 输出。每个输出数据的命令都支持 `--json`,
以提供适合 `jq`/脚本的纯粹、无样式的 JSON 路径。
**退出代码:** `0` = 正常,`2` = 发现告警,`1` = 错误,`3` = 被拒绝
(授权),`130` = 被中断。
### `analyze-log` — 离线评估访问日志
```
floodlight analyze-log --log /var/log/nginx/access.log
floodlight analyze-log --log access.log --window 60 --max-per-source 500
floodlight analyze-log --log access.log --json | jq '.alerts'
```
示例输出:
```
╭─────────────────────────────────────────────────────────────────╮
│ 🌊 floodlight abnormal traffic-rate detection for authorized … │
╰─────────────────────────────────────────────────────────────────╯
╭─ scan summary ──────────────────────────────────────────────────╮
│ source log:access.log │
│ events 354 (288 in last 10s window) │
│ distinct sources 14 │
│ peak rate 270 events / 10s window │
│ alerts 1 │
╰─────────────────────────────────────────────────────────────────╯
top talkers
source ip events share
198.51.100.9 270 93.8%
203.0.113.3 3 1.0%
…
alerts
severity type source observed threshold detail
HIGH source-rate 198.51.100.9 270 100 / 10s 198.51.100.9 produced 270 events…
```
选项:`--window`, `--max-total`, `--max-per-source`, `--max-syn-per-source`,
`--spike-sigma`, `--max-bytes`, `--max-lines`, `--json`。
### `monitor` — 捕获实时数据包并进行评分
```
sudo FLOODLIGHT_AUTHORIZED=1 floodlight monitor --interface eth0 --duration 30
sudo floodlight monitor --interface eth0 --duration 20 --i-am-authorized --json
```
未经授权将拒绝执行(退出代码 `3`):
```
Refusing to capture on interface 'eth0' without an explicit authorization acknowledgement.
Floodlight is a DEFENSIVE tool for systems you own or are explicitly authorised to monitor.
Re-run with --i-am-authorized or set FLOODLIGHT_AUTHORIZED=1 to confirm.
```
选项:`--interface`, `--duration`, `--filter` (BPF),阈值标志,
`--i-am-authorized`, `--json`。
### `summary` — 呈现已存储的证据
```
floodlight summary # pretty table of stored events + alerts
floodlight summary --json | jq '.critical_count'
floodlight summary --watch --interval 5 # live-refreshing terminal dashboard
```
`--watch` 使用实时更新视图(按 Ctrl-C 停止)。`--json` 始终输出纯粹的
JSON:`{ "alerts": [...], "event_count", "source_count", "critical_count" }`。
### `serve` — 只读 Web 仪表板
```
floodlight serve # binds 127.0.0.1:5067
floodlight serve --host 0.0.0.0 --port 5067 --i-am-authorized
```
| 方法 | 路径 | 用途 |
| ------ | -------------- | -------------------------------- |
| `GET` | `/` | 告警仪表板(自动刷新)。 |
| `GET` | `/api/summary` | 事件/告警摘要 JSON。 |
将绑定扩展到环回地址以外会暴露源 IP 和告警详情,因此它被置于
`--i-am-authorized` 的门控之后并会发出警告。`--debug` 会启用 Flask 的交互式
调试器(可执行代码)——仅供本地开发使用,Floodlight 会对此予以显著提示。
## 调优
阈值的好坏仅取决于你的基准。首先在一个已知安静的日志上运行 `analyze-log`
以查看正常的每源和总体速率,然后将阈值设定在高于该水平的一个舒适范围内。
注意 **NAT、代理和负载均衡器**——它们将许多真实的客户端合并为一个源 IP,这既可能
隐藏分布式洪水,也可能在繁忙的出口接口上导致错误的 `source-rate` 告警。
所有阈值也可以通过 `FLOODLIGHT_*` 环境变量进行设置
(参见 `.env.example`)。
## 开发与测试
```
cd floodlight
PYTHONPATH=src python -m pytest -q
# 直接从源码运行 CLI:
PYTHONPATH=src python -m floodlight.cli --help
PYTHONPATH=src python -m floodlight.cli analyze-log --log access.log
```
测试套件速度快且依赖少(无网络、无 sleeps、无 Scapy):
它涵盖了每个检测器、真实的 CLF 时间戳解析、大小上限、速率尖峰
数学计算、参数验证、JSON 纯度、退出代码以及授权门控。
### 目录结构
```
floodlight/
src/floodlight/
detector.py # event model, thresholds, detection + log parsing
capture.py # Scapy packet-capture adapter (lazy import)
store.py # SQLite events and alerts
ui.py # shared rich theme, banner, table/panel renderers
cli.py # analyze-log · monitor · summary · serve
app.py # Flask dashboard + JSON summary + security headers
templates/dashboard.html
tests/
```
## 安全 / 授权
Floodlight **仅用于授权的防御性监控**。在接口上捕获流量
会从网络上读取其他方的数据包;请仅在你拥有
或获得明确书面授权进行监控的系统上执行此操作。设置 `monitor` 和
非环回 `serve` 门控是为了让这种确认变得刻意——不要在你无法担保的自动化流程中
回避它们。
```
---
## 🏷️ 为什么叫 "Floodlight"?
Point a floodlight at the water and you can watch the level rise. Static thresholds only ever catch the flood you thought to predict; the one that takes you down is the one shaped differently than your rule. So this reads real access-log timestamps and adds statistical burst detection on top of the fixed limits — the boring threshold catches the obvious, and the statistics catch the rest.
---
## 🔬 这个工具是如何构建的
> One of ten defensive tools rebuilt to a single standard — *understand, reimagine,
> build the CLI, harden, document, verify*. The goal was never to change what these
> tools **are**, but to take each one as far as it could honestly go on correctness,
> safety and the experience of the person actually running it at 2am.
**Purpose.** A trustworthy, explainable traffic-rate flood detector. It reads real
access-log timestamps (so its window means seconds), adds statistical burst
detection on top of static thresholds, and gates the interface-sniffing and
dashboard behind explicit authorization.
**How it works.** `analyze-log` parses Common/Combined-Log timestamps, buckets
requests into time windows, and flags any window whose per-source rate crosses the
static ceiling *or* spikes statistically. `monitor` does the same over live
capture. Both emit a structured report (events, windowed counts, peak rate, top
talkers, alerts).
**Standout CLI.** A color-coded alerts table, a scan-summary panel, a top-talkers
table with per-source share, `console.status` spinners around parsing/capture, and
a `summary --watch` live-refreshing dashboard via `rich.Live`; global
`--plain`/`--no-color`/`--no-banner` accepted before or after the subcommand.
**Key improvements.** *Functional:* the correctness fix — `parse_access_log` reads
the real CLF timestamp so the window measures **seconds, not line count** (carries
forward on gaps, falls back to index-as-seconds only when a file has no timestamps
at all); a new z-score rate-spike detector (mean + `spike_sigma`×stddev, guarded
by a ≥2× floor) catches sharp bursts that never cross the ceiling; `monitor` gained
`--json` for parity. *Security:* the authorization gate on `monitor` and
non-loopback `serve` (`--i-am-authorized` / `FLOODLIGHT_AUTHORIZED=1`, exit 3);
hostile-input caps on logs (`--max-bytes` default 200 MiB, `--max-lines`, streamed
not slurped, truncation announced on stderr); the standard loopback + header
hardening on the dashboard.
**Example.**
```bash
PYTHONPATH=src python -m floodlight.cli analyze-log \
--log access.log --window 10 --max-per-source 100
```
## ⚖️ 授权使用与安全规章
**这些是用于你拥有或获得明确授权进行评估的系统、文件、网络和人员的防御性工具。**
在运行任何内容之前,请阅读以下内容:
- **授权不是可选的。** 钓鱼模拟、网络扫描、IP
信誉查询和 Web 应用探测都会触及他人的系统或
数据。请首先获得书面授权。在你声明授权之前,部分工具*拒绝执行操作*
(`--yes`, `--authorized-training`, `--i-have-authorization`,
`--i-am-authorized` 等)。
- **默认安全。** 每个 Web UI 都绑定到 `127.0.0.1`(环回地址)。出口流量、
实时发送和主动扫描都由明确的标志进行门控——试运行、
被动模式或拒绝并警告始终是默认设置。
- **杜绝意外的自损行为。** Flask 的 `--debug`(Werkzeug 交互式
调试器在任何回溯时都是远程代码执行)会受到显著警告,并且在
环回地址之外完全被拒绝。不受信任的输入受到大小限制、验证并被
无效化处理,使得恶意的文件或日志行不会导致你的终端崩溃——或被接管。
- **输出中不含机密信息。** API 密钥保留在请求标头中,密码来自
环境变量,且不会记录或打印任何敏感信息。
这些不是攻击性工具。它们不包含任何漏洞利用、凭证收集
器和 payload。如果某个工具*可能*被滥用,它的构造就会使其能够抵御
这种滥用。
## 🧪 开发
```
python -m venv .venv && source .venv/bin/activate
pip install -e .
pytest -q # 20 tests, no network, no sleeps
floodlight --help
```
## 📄 许可证
在 **MIT License** 下发布。参见 [LICENSE](LICENSE)。
防御性工具。无漏洞利用,无 payload,无凭证收集器。
标签:DDoS监控, Python, 安全运营, 异常检测, 扫描框架, 无后门, 逆向工具, 配置错误