DCSO/fever
GitHub: DCSO/fever
FEVER 是一个高性能的 Suricata EVE-JSON 事件路由处理器,用于在高流量环境下替代或前置 Logstash 实现快速事件导入、元数据聚合与威胁情报匹配。
Stars: 57 | Forks: 8
# 🔥 FEVER

[](https://packages.debian.org/stable/fever) [](https://packages.debian.org/testing/fever) 
Fast, Extensible, Versatile Event Router (FEVER) 是一个用于快速处理 Suricata JSON EVE 输出事件的工具。所谓的“处理”由许多模块化组件定义,例如促进快速导入数据库。其他处理器实现了各种元数据的收集、聚合和转发(例如聚合和原始流、被动 DNS 数据等)以及性能指标。
它的预期用途是作为通用日志处理器(如 Logstash)的前端(或替代品),以提高在承载高流量传感器上观察到的事件吞吐量。
## 构建
像任何优秀的 Go 程序一样:
```
$ go get -t ./...
$ go build ./...
$ go install -v ./...
...
$ fever run -h
```
## 使用
```
$ ./fever run -h
The 'run' command starts the FEVER service, consuming events from
the input and executing all processing components.
Usage:
fever run [flags]
Flags:
--active-rdns enable active rDNS enrichment for src/dst IPs
--active-rdns-cache-expiry duration cache expiry interval for rDNS lookups (default 2m0s)
--active-rdns-private-only only do active rDNS enrichment for RFC1918 IPs
--bloom-alert-prefix string String prefix for Bloom filter alerts (default "BLF")
--bloom-blacklist-iocs strings Blacklisted strings in Bloom filter (will cause filter to be rejected) (default [/,/index.htm,/index.html])
-b, --bloom-file string Bloom filter for external indicator screening
-z, --bloom-zipped use gzipped Bloom filter file
-c, --chunksize uint chunk size for batched event handling (e.g. inserts) (default 50000)
--context-cache-timeout duration time for flow metadata to be kept for uncompleted flows (default 1h0m0s)
--context-enable collect and forward flow context for alerted flows
--context-submission-exchange string Exchange to which flow context events will be submitted (default "context")
--context-submission-url string URL to which flow context will be submitted (default "amqp://guest:guest@localhost:5672/")
-d, --db-database string database DB (default "events")
--db-enable write events to database
-s, --db-host string database host (default "localhost:5432")
--db-maxtablesize uint Maximum allowed cumulative table size in GB (default 500)
-m, --db-mongo use MongoDB
-p, --db-password string database password (default "sensor")
--db-rotate duration time interval for database table rotations (default 1h0m0s)
-u, --db-user string database user (default "sensor")
--dummy log locally instead of sending home
--flowextract-bloom-selector string IP address Bloom filter to select flows to extract
--flowextract-enable extract and forward flow metadata
--flowextract-submission-exchange string Exchange to which raw flow events will be submitted (default "flows")
--flowextract-submission-url string URL to which raw flow events will be submitted (default "amqp://guest:guest@localhost:5672/")
-n, --flowreport-interval duration time interval for report submissions
--flowreport-nocompress send uncompressed flow reports (default is gzip)
--flowreport-submission-exchange string Exchange to which flow reports will be submitted (default "aggregations")
--flowreport-submission-url string URL to which flow reports will be submitted (default "amqp://guest:guest@localhost:5672/")
--flushcount uint maximum number of events in one batch (e.g. for flow extraction) (default 100000)
-f, --flushtime duration time interval for event aggregation (default 1m0s)
-T, --fwd-all-types forward all event types
-t, --fwd-event-types strings event types to forward to socket (default [alert,stats])
--heartbeat-enable Forward HTTP heartbeat event
--heartbeat-times strings Times of day to send heartbeat (list of 24h HH:MM strings)
-h, --help help for run
--in-buffer-drop drop incoming events on FEVER side instead of blocking the input socket (default true)
--in-buffer-length uint input buffer length (counted in EVE objects) (default 500000)
-r, --in-redis string Redis input server (assumes "suricata" list key, no pwd)
--in-redis-nopipe do not use Redis pipelining
-i, --in-socket string filename of input socket (accepts EVE JSON) (default "/tmp/suri.sock")
--ip-alert-prefix string String prefix for IP blacklist alerts (default "IP-BLACKLIST")
--ip-blacklist string List with IP ranges to alert on
--logfile string Path to log file
--logjson Output logs in JSON format
--metrics-enable submit performance metrics to central sink
--metrics-submission-exchange string Exchange to which metrics will be submitted (default "metrics")
--metrics-submission-url string URL to which metrics will be submitted (default "amqp://guest:guest@localhost:5672/")
-o, --out-socket string path to output socket (to forwarder), empty string disables forwarding (default "/tmp/suri-forward.sock")
--pdns-enable collect and forward aggregated passive DNS data
--pdns-submission-exchange string Exchange to which passive DNS events will be submitted (default "pdns")
--pdns-submission-url string URL to which passive DNS events will be submitted (default "amqp://guest:guest@localhost:5672/")
--profile string enable runtime profiling to given file
--reconnect-retries uint number of retries connecting to socket or sink, 0 = no retry limit
--toolname string set toolname (default "fever")
-v, --verbose enable verbose logging (debug log level)
Global Flags:
--config string config file (default is $HOME/.fever.yaml)
--mgmt-host string hostname:port definition for management server
--mgmt-network string network (tcp/udp) definition for management server (default "tcp")
--mgmt-socket string Socket path for management server (default "/tmp/fever-mgmt.sock")
```
也可以使用 YAML 格式的配置文件([示例](fever.yaml))。配置是层叠式的:首先从配置文件加载设置,然后可以被命令行参数覆盖。
## 运行测试
测试套件需要在当前路径下有一个 Redis 可执行文件。最简单的方法是直接安装 Redis。例如,通过 `apt`:
```
$ apt install redis-server
```
然后可以通过 Go 的通用测试框架运行测试套件:
```
$ go test -v -race -cover ./...
...
```
## Suricata 设置
该工具旨在从 socket 消费 JSON 事件,默认为 `/tmp/suri.sock`。可以在 `suricata.yaml` 中使用以下设置启用此功能:
```
...
# 可扩展事件格式(昵称 EVE)JSON 格式事件日志
- eve-log:
enabled: yes
filetype: unix_stream
filename: /tmp/suri.sock
...
```
所有 JSON 也会传递到另一个 socket,这允许将其插入到 Suricata 和另一个日志消费者(例如 Logstash 等)之间。
另一种消费事件的方式是通过 Redis。使用 `-r` 参数指定 Redis 主机,将查询键 `suricata` 作为列表以从中 BRPOP 事件。
## 重要设置
- 数据库连接:使用 `-db-*` 参数指定数据库连接。需要 PostgreSQL 9.5 或更高版本。使用 `-m` 将参数改为 MongoDB 连接参数。
- 块大小:决定同时作为一个整体导入的事件数量。较大的值可能更快并带来更好的吞吐量,但会使用更多 RAM,并且在批量导入(=事务)失败时会丢失更多事件。较小的值会增加数据库的开销。
- 性能分析:可选输出一个 pprof 文件,用于配合 `go tool pprof` 使用。
- 表轮换:为了最大写入性能,表被创建为没有索引的 unlogged 表。为了控制表大小,表会加上时间戳并按用户选择的时间间隔(例如 1h)进行轮换。索引创建会推迟到表被轮换且不再写入时进行,并且也是在后台发生的。索引作业会排队,因此如果索引花费的时间超过一个轮换周期,数据应该不会丢失。
- 事件转发:FEVER 处理过的事件可以转发到另一个 socket,由下游工具(例如 Logstash)处理。默认情况下,只转发 `alert` 和 `stats` 事件类型,但可以使用 `-t ` 添加额外的类型来扩展转发的类型集。作为一个兜底选项(对于仍然运行完整 ELK 栈的传感器来说可能是最佳选择),选项 `-T` 将转发所有内容。
- 布隆过滤器可以通过向主进程发送 `SIGUSR1` 来重新加载。
## 使用本地数据进行开发测试运行
创建本地 socket 以消费转发的事件。你也可以使用 [pv](http://www.ivarch.com/programs/pv.shtml) 来监控是否有数据流动以及流量大小(你可能需要先使用 `apt install pv netcat-openbsd` 安装必要的工具):
```
$ nc -klU /tmp/suri-forward.sock | pv > /dev/null
```
与其简单地将其发送到 `/dev/null`,当然也可以使用 `jq` 等工具过滤输出,以直观地确认某些输出已被转发。
启动服务:
```
$ ./fever run -v -n 0 -o '' --logfile '' &
```
`-n 0` 选项禁用流元数据的提交。`-o ''` 禁用转发到本地 socket 接收端。或者,可以使用 `--dummy`/`--nodb` 来禁用数据库插入,仅测试输入解析和元数据聚合。
最后,将测试数据推入输入 socket:
```
$ head -n 100000 huge.eve.json | socat /tmp/suri.sock STDIO
```
这将把 `huge.eve.json` 中的前 10 万个事件送入 socket。`socat` 工具可以照常通过 `apt install socat` 安装。
要使用 Redis 将 EVE 数据送入 FEVER(使用 `-r` 启动),你可以简单地使用 LPUSH 将 JSON 事件推入由键 `suricata` 引用的列表中。使用 Lua 脚本 `scripts/makelpush` 将原始 EVE 行转换为 Redis 语句:
```
$ head -n 100000 huge.eve.json | scripts/makelpush | redis-cli > /dev/null
```
## 端到端测试支持
FEVER 可以选择将带内测试数据注入到下游提交中,例如被动 DNS 观察,以便自动检查接收组件是否正确更新。
* 要将测试告警注入转发流,请使用 `heartbeat.alert-times` 列表指定何时注入告警心跳。该方法与通用心跳的方法相同:在每次指定的时间,将创建并转发一个如下所示的告警:
{
"timestamp": "2021-12-09T09:49:35.641252+0000",
"event_type": "alert",
"src_ip": "192.0.2.1",
"src_port": 39106,
"dest_ip": "192.0.2.2",
"dest_port": 80,
"proto": "TCP",
"alert": {
"action": "allowed",
"gid": 0,
"signature_id": 0,
"rev": 0,
"signature": "DCSO FEVER TEST alert",
"category": "Not Suspicious Traffic",
"severity": 0
},
"http": {
"hostname": "test-2021-12-09.vast",
"url": "/just-visiting",
"http_user_agent": "FEVER",
"http_content_type": "text/html",
"http_method": "GET",
"protocol": "HTTP/1.1",
"status": 200,
"length": 42
}
}
* 对于被动 DNS 观察提交,请使用 `pdns.test-domain` 配置项为该域插入一个虚拟条目,例如,如果 `pdns.test-domain` 设置为 `heartbeat.fever-heartbeat`:
{
"timestamp_start": "2021-12-07T18:18:00.029197078Z",
"timestamp_end": "2021-12-07T18:19:00.063460044Z",
"dns": {
"heartbeat.fever-heartbeat": {
"rdata": [
{
"answering_host": "0.0.0.0",
"rrtype": "A",
"rdata": "0.0.0.0",
"rcode": "NOERROR",
"count": 1
}
]
},
...
}
}
* 对于流报告提交,请使用 `flowreport.testdata*` 配置项为特定 IP 和端口插入虚拟流,例如对于:
flowreport:
# ...
testdata-srcip: 0.0.0.1
testdata-destip: 0.0.0.2
testdata-destport: 99999
我们将得到
{
"sensor-id": "XXX",
"time-start": "2021-12-08T13:53:36.442182896+01:00",
"time-end": "2021-12-08T13:53:46.490743527+01:00",
"tuples": {
"0.0.0.1_0.0.0.2_99999": {
"count": 1,
"total_bytes_toclient": 23,
"total_bytes_toserver": 42
}
},
...
}
## 作者/联系方式
Sascha Steinbiss
## 许可证
BSD-3-clause
标签:Bloom Filter, Debian, EDR, EVE-JSON, EVTX分析, Go, IP 地址批量处理, Metaprompt, Ruby工具, Suricata, 事件处理, 二进制发布, 传感器, 威胁情报, 开发者工具, 开源工具, 搜索引擎查询, 数据摄取, 日志审计, 日志聚合, 日志路由, 日志转发, 测试用例, 现代安全运营, 网络安全, 脆弱性评估, 被动DNS, 遥测数据, 隐私保护