DCSO/fever

GitHub: DCSO/fever

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

Stars: 57 | Forks: 8

# 🔥 FEVER ![Build Status](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/eb50a60d6b122257.svg) [![DebianSBadge](https://badges.debian.net/badges/debian/stable/fever/version.svg)](https://packages.debian.org/stable/fever) [![DebianTBadge](https://badges.debian.net/badges/debian/testing/fever/version.svg)](https://packages.debian.org/testing/fever) ![Ubuntu package](https://img.shields.io/ubuntu/v/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, 遥测数据, 隐私保护