DCSO/balboa

GitHub: DCSO/balboa

balboa 是一款被动 DNS 观测数据的索引与查询服务器,支持多源数据摄入、灵活过滤标记和 GraphQL/REST 接口查询。

Stars: 50 | Forks: 7

# 📑 balboa ![Build Status](https://static.pigsec.cn/wp-content/uploads/repos/cas/a6/a6d2b66acade0556c67adb568dff7fe775ae65149c37137a060d9cdb774fe8f6.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/DCSO/balboa)](https://goreportcard.com/report/github.com/DCSO/balboa) balboa 是 BAsic Little Book Of Answers(基础小答案书)的缩写。它消费并索引来自[被动 DNS](https://www.farsightsecurity.com/technical/passive-dns/)采集的观测数据,并提供一个 [GraphQL](https://graphql.org/) 接口来访问观测数据库中的聚合内容。我们构建 balboa 来处理从 [Suricata](https://suricata-ids.org)收集的元数据中聚合的被动 DNS 数据。 该 API 应该适合集成到现有的多源可观测数据集成框架中。可以使用 GraphQL API(见下文)或兼容 [CIRCL](https://www.circl.lu/services/passive-dns/)的 REST API,以[通用输出格式](https://datatracker.ietf.org/doc/draft-dulaunoy-dnsop-passive-dns-cof/)兼容的 schema 来生成结果。 balboa 软件... - 查询和输入/更新速度快 - 使用可插拔后端实现存储,后端可能位于单独的机器上 - 支持追踪和专门查询多个传感器 - 在查询和摄取时利用多核 CPU - 同时接受来自多个源的输入 - HTTP (POST) - AMQP - Unix socket - 网络 socket(仅限 NMSG 格式) - 可以根据各种属性对观测数据进行标记和过滤 - 可以根据匹配的选择器将观测数据存储到一个或多个后端 - 接受多种输入格式 - 基于 JSON - [FEVER](https://github.com/DCSO/fever) - [gopassivedns](https://github.com/Phillipmartin/gopassivedns) - [Packetbeat](https://www.elastic.co/guide/en/beats/packetbeat/master/packetbeat-dns-options.html)(通过 Logstash) - [Suricata EVE DNS v1 和 v2](http://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html#event-type-dns) - 平面文本文件 - Edward Fjellskål 的 [PassiveDNS](https://github.com/gamelinux/passivedns) 表格格式(默认顺序 `-f SMcsCQTAtn`) - 二进制 - Farsight Security [NMSG 格式](https://www.farsightsecurity.com/txt-record/2015/01/28/nmsg-intro/)(通过网络 socket) ## 构建与安装 ``` $ go get github.com/DCSO/balboa/cmd/balboa ... ``` 这会将 `balboa` 可执行文件放入您的 Go bin 路径中。 构建后端: ``` $ cd $GOPATH/src/github.com/DCSO/balboa/backend $ make ... ``` 这会在每个后端目录的 `build/` 子目录中创建一个可执行二进制文件。 ### 依赖项 - Go 1.10 或更高版本 - 对于内置的 RocksDB 后端:[RocksDB](https://rocksdb.org/) 5.0 或更高版本(共享库,支持 LZ4) 例如,在 Debian 上,可以通过以下方式满足这些依赖项: ``` % apt install golang-go librocksdb-dev ... ``` ## 用法 ### 配置 feeder Feeder 用于将观测数据导入数据库。它们并发运行并在后台处理输入,一旦数据库中完成了最终的 upsert 事务,即可通过查询接口访问结果。要创建哪些 feeder 在 YAML 配置文件中定义(通过 `-f` 参数传递给 `balboa serve`)。示例: ``` feeder: - name: AMQP Input type: amqp url: amqp://guest:guest@localhost:5672 exchange: [ tdh.pdns ] input_format: fever_aggregate - name: HTTP Input type: http listen_host: 127.0.0.1 listen_port: 8081 input_format: fever_aggregate - name: Socket Input type: socket path: /tmp/balboa.sock input_format: gopassivedns ``` 给定此 feeder 配置的 balboa 实例将支持以下输入选项: - 通过 AMQP 从临时队列传递的 FEVER 聚合格式 JSON,该队列附加在 `localhost` 端口 5762 上的交换机 `tdh.pdns` 中,使用用户 `guest` 和密码 `guest` 进行身份验证 - 从本地系统端口 8081 上的 HTTP POST 请求中解析的 FEVER 聚合格式 JSON - gopassivedns 格式的 JSON,输入到由 balboa 创建的 UNIX socket `/tmp/balboa.sock` 中 所有这些 feeder 同时接受输入,不区分观测数据的来源。只要它们的 `name` 唯一,就可以指定多个相同类型但设置不同的 feeder。 ### 配置选择器 Balboa 提供了一个选择器引擎,可用于选择或过滤观测数据。 选择器引擎在 YAML 文件中进行配置,该文件通过 `-s` 参数提供给 balboa。 可用的选择器实现: * regex:使用一个或多个选择器匹配观测数据的 `RRNAME` 字段 * lua:使用 lua 脚本处理观测数据,有关示例,请参见 *selector.lua* 示例: ``` selectors: - name: Filter Unwanted TLDs type: regex mode: filter regexp: - unwanted_regex.txt tags: - filtered_tlds - name: CobaltStrike Regex type: regex mode: select regexp: - cobaltstrike_regex.txt ingest: - filtered_tlds tags: - possible_cobaltstrike ``` 此配置会将所有**未**被 `unwanted_regex.txt` 中的正则表达式匹配到的观测数据打上 `filtered_tlds` 标签。 所有标记为 `filtered_tlds` 且匹配 `cobaltstrike_regex.txt` 中一个或多个正则表达式的观测数据,都会被标记为 `possible_cobaltstrike`。 ### 配置数据库后端 支持多个数据库后端来持久化存储 pDNS 观测数据。每个数据库后端都作为一个独立的二进制(可执行文件)提供。前端只连接到一个数据库后端。但是,后端支持多个客户端或前端连接。 每个后端可以配置为处理所有观测数据(没有 `tags` 参数)或处理一系列标签列表(条件或)。 后端配置在 YAML 文件中定义(通过 `-b` 参数传递给 `balboa server`)。示例: ``` - name: cobaltstrike host: "localhost:4242" tags: - possible_cobaltstrike - name: all filtered observations host: "localhost:4343" tags: - filtered_tlds ``` 具有此后端配置的 balboa 实例会将所有标记为 `possible_cobaltstrike` 的事件存储到监听端口为 `localhost:4242` 的后端中,并将所有标记为 `filtered_tlds` 的事件存储到 `localhost:4343` 上的后端中。 ### 运行后端和前端服务并消费输入 所有在命令行上与前端的交互都是通过 `balboa` 前端可执行文件进行的。前端依赖于后端服务,这通常是其独立的可执行文件。 例如,可以使用以下命令启动 RocksDB 后端: ``` $ balboa-rocksdb -h `balboa-rocksdb` provides a pdns database backend for `balboa` Usage: balboa-rocksdb [options] -h display help -D daemonize (default: off) -d path to rocksdb database (default: `/tmp/balboa-rocksdb`) -l listen address (default: 127.0.0.1) -p listen port (default: 4242) -v increase verbosity; can be passed multiple times -j thread throttle limit, maximum concurrent connections (default: 64) --membudget rocksdb membudget option (value: 134217728) --parallelism rocksdb parallelism option (value: 8) --max_log_file_size rocksdb log file size option (value: 10485760) --max_open_files rocksdb max number of open files (value: 300) --keep_log_file_num rocksdb max number of log files (value: 2) --database_path same as `-d` --version show version thenp exit $ balboa-rocksdb --database_path /data/pdns -l 127.0.0.1 -p 4242 ``` 启动后端后,可以按如下方式启动 `balboa` 前端: ``` $ balboa serve -l '' INFO[0000] starting feeder AMQPInput2 INFO[0000] starting feeder HTTP Input INFO[0000] accepting submissions on port 8081 INFO[0000] starting feeder Socket Input INFO[0000] starting feeder Suricata Socket Input INFO[0000] ConsumeFeed() starting INFO[0000] serving GraphQL on port 8080 ... ``` 启动后,即可使用 feeder 进行数据摄取。例如,可以执行以下一些操作来测试数据消费(假设使用了上述 feeder): - 对于 AMQP: $ scripts/mkjson.py | rabbitmqadmin publish routing_key="" exchange=tdh.pdns ... - 对于 HTTP: $ scripts/mkjson.py | curl -d@- -qs --header "X-Sensor-ID: abcde" http://localhost:8081/submit ... - 对于 socket: $ sudo gopassivedns -dev eth0 | socat /tmp/balboa.sock STDIN ... ### 查询服务器 与服务器交互的预期主要接口是通过 GraphQL。例如,查询 ``` query { entries(rrname: "test.foobar.de", sensor_id: "abcde", limit: 1) { rrname rrtype rdata time_first time_last sensor_id count } } ``` 将返回类似如下内容 ``` { "data": { "entries": [ { "rrname": "test.foobar.de", "rrtype": "A", "rdata": "1.2.3.4", "time_first": 1531943211, "time_last": 1531949570, "sensor_id": "abcde", "count": 3 } ] } } ``` 这也适用于将 `rdata` 作为查询参数,但必须至少声明 `rrname` 或 `rdata` 中的一个。如果没有 `sensor_id` 参数,则无论 DNS 应答是在哪里观测到的,都会返回所有结果。 请分别使用 `time_first_rfc3339` 和 `time_last_rfc3339` 而不是 `time_first` 和 `time_last`,以获取人类可读的时间戳。 当配置了多个后端时,查询将被分发给每个后端。 因此,当观测数据存储在多个后端中时,查询结果将包含重复项。 ### 别名 有时,查询所有解析为相同 IP 地址的域名会很有趣。出于这个原因,GraphQL API 支持一个虚拟的 `aliases` 字段,该字段会返回所有 RRType 为 `A` 或 `AAAA` 且在 Rdata 字段中共享相同地址的条目 (Entry)。 示例: ``` { entries(rrname: "heise.de", rrtype: A) { rrname rdata rrtype time_first_rfc3339 time_last_rfc3339 aliases { rrname } } } ``` ``` { "data": { "entries": [ { "rrname": "heise.de", "rdata": "193.99.144.80", "rrtype": "A", "time_first_rfc3339": "2018-07-10T08:05:45Z", "time_last_rfc3339": "2018-10-18T09:24:38Z", "aliases": [ { "rrname": "ct.de" }, { "rrname": "ix.de" }, { "rrname": "redirector.heise.de" }, { "rrname": "www.ix.de" } ] } ] } } ``` ### 批量查询 还有一个快捷工具可以使“批量”查询变得更容易。例如,要获取传感器 `abcde` 观测到的范围 1.2.0.0/16 内主机的所有信息,可以使用: ``` $ balboa query --sensor abcde 1.2.0.0/16 {"count":6,"time_first":1531943211,"time_last":1531949570,"rrtype":"A","rrname":"test.foobar.de","rdata":"1.2.3.4","sensor_id":"abcde"} {"count":1,"time_first":1531943215,"time_last":1531949530,"rrtype":"A","rrname":"baz.foobar.de","rdata":"1.2.3.7","sensor_id":"abcde"} ``` 请注意,此工具目前实际上只是执行了大量并发的独立查询!为了在这些情况下提高性能,未来可能值得考虑同样允许在服务器端进行范围查询。 ### 其他工具 运行不带参数的 `balboa` 以列出可用的子命令,并获取有关其作用的简短说明。 另请参见 `backend` 目录中的 `README.md`。 ## 作者/联系方式 Sascha Steinbiss ## 许可证 BSD-3-clause
标签:Go, GraphQL, IP 地址批量处理, rizin, Ruby工具, 便携式工具, 威胁情报, 客户端加密, 开发者工具, 数据索引, 日志审计, 网络安全, 被动DNS, 隐私保护