fretscha/modsec-exporter
GitHub: fretscha/modsec-exporter
面向 Apache + ModSecurity/OWASP CRS 4.x 的 Prometheus exporter,通过关联访问日志与 WAF 错误日志导出 RED 服务指标、WAF 规则统计及攻击者追踪指标,帮助团队在 Grafana 中实时监控 Web 应用防火墙的防护效果。
Stars: 0 | Forks: 0
# modsec-exporter
[](https://github.com/fretscha/modsec-exporter/actions/workflows/ci.yml)
[](https://pkg.go.dev/github.com/fretscha/modsec-exporter)
[](https://goreportcard.com/report/github.com/fretscha/modsec-exporter)
[](LICENSE)
一个 Prometheus exporter,通过 tail 读取 Apache 访问日志以及 ModSecurity / OWASP CRS 4.x 错误日志,并提供以下指标:
- **Service RED 指标** — 请求率、错误率、延迟、响应大小、国家/地区分布。
- **WAF 指标** — 规则触发次数、严重程度 / 偏执级别 / 攻击类别分布、异常分数直方图。
- **定向的“拦截 vs 放行”关联** — 以 Apache `unique_id` 为键:对于每条触发的规则,请求返回了什么 HTTP 状态类别?
- **Top-N 攻击者** — 有上限的活动最频繁的攻击者 IP 数值,包含国家/地区 / ASN。
为了进行更深入的调查(按 IP / URI / 规则消息下钻),请将此 exporter 与您选择的独立批量日志分析工具配合使用 —— modsec-exporter 故意将高基数维度排除在 Prometheus 之外,以控制时间序列的数量。
## 快速开始
**选项 1 — 预编译二进制文件** (Linux amd64/arm64,静态链接):
```
# 如果需要,将 linux-amd64 替换为 linux-arm64
curl -Lo modsec-exporter \
https://github.com/fretscha/modsec-exporter/releases/latest/download/modsec-exporter-linux-amd64
chmod +x modsec-exporter
./modsec-exporter \
--access-log /var/log/apache2/access.log \
--error-log /var/log/apache2/error.log \
--listen :9555
```
请使用[发布页面](https://github.com/fretscha/modsec-exporter/releases/latest)附带的 `checksums.txt` 进行验证。
**选项 2 — go install**:
```
go install github.com/fretscha/modsec-exporter/cmd/modsec-exporter@latest
modsec-exporter \
--access-log /var/log/apache2/access.log \
--error-log /var/log/apache2/error.log \
--listen :9555
```
**选项 3 — 从源码构建**:
```
git clone https://github.com/fretscha/modsec-exporter.git
cd modsec-exporter
make build
./bin/modsec-exporter \
--access-log /var/log/apache2/access.log \
--error-log /var/log/apache2/error.log \
--listen :9555
```
## 配置
| 标志 | 环境变量 | 默认值 | 备注 |
|---|---|---|---|
| `--config` | — | — | TOML 配置文件的路径;与 `--access-log`/`--error-log` 互斥 |
| `--access-log` | `MODSEC_EXPORTER_ACCESS_LOG` | — | 单站点模式;如果未提供 `--config` 则必填 |
| `--error-log` | `MODSEC_EXPORTER_ERROR_LOG` | — | 单站点模式;如果未提供 `--config` 则必填 |
| `--listen` | `MODSEC_EXPORTER_LISTEN` | `:9555` | |
| `--mmdb` | `MODSEC_EXPORTER_MMDB` | `""` | 留空则禁用 GeoIP 回退 |
| `--top-n` | — | `50` | 每个站点;`0` 为禁用 |
| `--buffer-size` | — | `50000` | 每个站点的关联缓冲区容量 |
| `--buffer-ttl` | — | `60s` | 孤立阈值 |
| `--sweep-interval` | — | `10s` | TTL 清扫周期 |
| `--replay` | — | `false` | 一次性文件读取;metrics 端点保持运行直到收到 SIGINT/SIGTERM |
## 多站点配置
要使用一个进程监控多个 Apache 站点,请创建一个 TOML 配置文件:
```
[[site]]
name = "shop"
access_log = "/var/log/apache2/shop-access.log"
error_log = "/var/log/apache2/shop-error.log"
[[site]]
name = "blog"
access_log = "/var/log/apache2/blog-access.log"
error_log = "/var/log/apache2/blog-error.log"
```
然后使用 `--config` 启动 exporter:
```
modsec-exporter --config /etc/modsec-exporter/sites.toml --listen :9555
```
所有 Prometheus 指标都带有一个 `site` 标签(例如 `site="shop"`)。每个站点都有自己的关联缓冲区和 Top-N 跟踪器;GeoIP 和 HTTP 端点是共享的。
## 核心 PromQL
CRS 规则实际拦截请求的比例(相对于仅在 DetectionOnly 模式下发出警告):
```
sum by(rule_id)(rate(modsec_request_outcome_total{status_class="4xx"}[5m]))
/ sum by(rule_id)(rate(modsec_request_outcome_total[5m]))
```
按 4xx 状态码速率排名的最活跃攻击国家/地区:
```
topk(10, sum by(country)(rate(http_requests_by_country_total{status_class="4xx"}[15m])))
```
疑似误报规则 —— 高触发率,低拦截率:
```
(
sum by(rule_id)(rate(modsec_rule_triggered_total[15m]))
) > 1
and on(rule_id)
(
sum by(rule_id)(rate(modsec_request_outcome_total{status_class="4xx"}[15m]))
/ sum by(rule_id)(rate(modsec_request_outcome_total[15m]))
) < 0.1
```
## 基数
最坏情况:对于运行完整 CRS 4.x 并具有 5 个 vhost 的单个 Apache,约有 18k 个序列。有关细分,请参见[设计文档](docs/design/2026-04-29-modsec-prom-exporter-design.md#cardinality-budget)。
`client_ip`、`uri`、`user_agent` 和 `msg` 被故意不作为标签公开(在有上限的 Top-N 指标内的 `client_ip` 除外)。要进行按 IP / URI 的调查,请将此 exporter 与能够处理无限基数的批量日志分析工具配合使用。
## 开发
```
make test # unit + integration
make smoke # e2e replay smoke against test/fixtures
make lint
```
Smoke 测试的 fixtures 已被 gitignore。使用附带的 `loggen` 工具生成它们:
```
go run ./cmd/loggen \
--count 5000 \
--access-out test/fixtures/access.log \
--error-out test/fixtures/error.log
```
## 容器
```
docker build -t modsec-exporter:dev -f docker/Dockerfile .
docker run --rm -v /var/log/apache2:/logs:ro -p 9555:9555 modsec-exporter:dev \
--access-log /logs/access.log --error-log /logs/error.log
```
## Systemd
在 `deploy/modsec-exporter.service` 中提供了一个经过安全强化的 unit 文件。安装步骤:
```
sudo cp bin/modsec-exporter /usr/local/bin/
sudo useradd -r -s /usr/sbin/nologin modsec-exporter
sudo usermod -aG adm modsec-exporter # for log read access
sudo cp deploy/modsec-exporter.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now modsec-exporter
```
## Prometheus 抓取
```
- job_name: modsec
scrape_interval: 30s
static_configs:
- targets: ['apache-host-1:9555']
```
## 许可证
根据 Apache License, Version 2.0 授权。详情请参见 [LICENSE](LICENSE) 和 [NOTICE](NOTICE)。
标签:AMSI绕过, Apache, AppImage, CRS, DevSecOps, EVTX分析, Golang, ModSecurity, Python安全, RED指标, WAF, Web应用防火墙, 上游代理, 威胁检测, 安全编程, 异常分数, 指标监控, 攻击者追踪, 日志审计, 网络流量分析, 自定义请求头, 请求拦截