Query-farm/vgi-tlsfp

GitHub: Query-farm/vgi-tlsfp

一个 DuckDB SQL 扩展,直接在查询中从 TLS 握手数据计算 JA3/JA3S/JA4 指纹,用于聚类和追踪 C2 与僵尸网络基础设施。

Stars: 0 | Forks: 0

Query.Farm

# vgi-tlsfp — 在 DuckDB SQL 中进行 TLS 客户端/服务器指纹识别 **直接在 SQL 中计算 JA3、JA3S 以及基础 JA4(TLS 客户端)指纹** 基于原始的 `ClientHello`/`ServerHello` 字节 —— 或者基于你已经使用 Zeek/pcap 工具提取出的字段。将指纹计算应用于捕获的握手数据列,并对其执行 `GROUP BY` 以发现 C2 或僵尸网络家族,然后将生成的 VARCHAR 哈希值 JOIN 到证书([`vgi-x509`](https://github.com/Query-farm))和流量 ([`vgi-netflow`](https://github.com/Query-farm))数据上,从而实现从指纹 到其背后证书和网络流量的关联追踪。 `tlsfp` 是一个 [VGI](https://query.farm) worker:一个独立的二进制文件,由 DuckDB 启动 并通过 Apache Arrow 进行通信。每个函数都是**纯的、确定性的计算 — 没有网络请求,没有状态。** 格式错误或截断的字节会按行返回 `NULL`,而 不会导致查询失败。 ## 快速开始 `client_hello`/`server_hello` 输入是原始的 TLS 握手记录(例如 来自 Zeek 的 `ssl.log` 原始字段或 pcap 读取器)—— 可以是完整的 TLS 记录 (以 `0x16…` 开头)或是裸握手消息(`0x01…` / `0x02…`)。这是一个 *指纹识别*原语,而不是一个数据包捕获工具。 ## 函数参考 (`tlsfp.main`) | 函数 | 返回值 | 描述 | | --- | --- | --- | | `ja3(client_hello BLOB)` | `VARCHAR` | ClientHello 的 JA3 指纹(MD5,32 位十六进制)。无法解析时返回 `NULL`。 | | `ja3_string(client_hello BLOB)` | `VARCHAR` | 哈希前的 JA3 字符串(用于审计 / 自定义重新哈希)。 | | `ja3_from_parts(version INT, ciphers INT[], extensions INT[], curves INT[], point_formats INT[])` | `VARCHAR` | 基于已提取字段的 JA3。 | | `ja3s(server_hello BLOB)` | `VARCHAR` | ServerHello 的 JA3S 指纹(MD5)。 | | `ja3s_from_parts(version INT, cipher INT, extensions INT[])` | `VARCHAR` | 基于已提取字段的 JA3S。 | | `ja4(client_hello BLOB)` | `VARCHAR` | JA4 基础 TLS 客户端指纹,例如 `t13d1516h2_8daaf6152771_e5627efa2ab1`。 | | `ja4_raw(client_hello BLOB)` | `VARCHAR` | 未哈希的 JA4_r 格式。 | | `ja4_from_parts(version INT, ciphers INT[], extensions INT[], sig_algs INT[], alpn VARCHAR)` | `VARCHAR` | 基于已提取字段的 JA4(`version` 是有效的 TLS 版本代码,例如 `772`)。 | | `parse_client_hello(client_hello BLOB)` | `STRUCT(version INT, sni VARCHAR, ciphers INT[], extensions INT[], curves INT[], alpn VARCHAR[])` | ClientHello 的精确解码(保留 GREASE)。 | | `is_tls_handshake(bytes BLOB)` | `BOOLEAN` | 彻底的防护:输入看起来像 TLS 握手吗?`NULL` 输入 → `NULL`。 | | `tlsfp_version()` | `VARCHAR` | 正在运行的 worker 版本字符串。 | ### 约定 - **`*_string` / `*_raw` 配套函数**公开了哈希前的 JA3 字符串和 未哈希的 JA4_r 格式,用于审计/调试,以便你可以根据自己的策略重新进行哈希。 - **GREASE** 值(RFC 8701)已从每个指纹中剔除;两种输入 模式(字节 vs 字段)共享同一个实现且结果始终一致。 - **逐行安全性:** 格式错误/截断的字节将返回 `NULL`,绝不会因为报错而导致 扫描失败。如果你愿意,可以先使用 `is_tls_handshake(bytes)` 进行过滤。 - 输出是普通的 VARCHAR 哈希值,可以 JOIN 到 `vgi-x509`(服务器证书 指纹)和 `vgi-netflow`(5 元组),用于威胁狩猎的追踪。 ## 示例 ``` -- JA4 of a captured handshake SELECT ja4(client_hello) FROM captured_handshakes; -- JA3S of the server side SELECT ja3s(server_hello) FROM captured_handshakes; -- guard then fingerprint (skip non-handshake rows) SELECT ja3(client_hello) FROM captured_handshakes WHERE is_tls_handshake(client_hello); -- decode a ClientHello's fields SELECT (parse_client_hello(client_hello)).sni, (parse_client_hello(client_hello)).ciphers FROM captured_handshakes; -- the two input modes agree SELECT ja3(client_hello) = ja3_from_parts(771, ciphers, extensions, curves, point_formats) FROM zeek_ssl; ``` ## 构建与测试 ``` cargo build --release # produces target/release/tlsfp-worker cargo test # unit + integration + proptest (no-panic fuzz) cargo clippy --all-targets -- -D warnings cargo fmt --check ``` ### 端到端 SQL (haybarn) `test/sql/*.test` sqllogictest 测试套件针对真实的 DuckDB `vgi` 扩展运行,覆盖**所有传输方式**(subprocess / http / unix)。请参见 [`ci/README.md`](ci/README.md): ``` cargo build --release HAYBARN_UNITTEST=/path/to/haybarn-unittest \ WORKER_BIN="$PWD/target/release/tlsfp-worker" \ TRANSPORT=subprocess ci/run-integration.sh ``` ### 元数据质量 (vgi-lint) ``` uvx --from vgi-lint-check vgi-lint lint "$PWD/target/release/tlsfp-worker" --fail-on info ``` ## 架构 包含两个 crate: - **`tlsfp-core`** —— 纯净、可模糊测试的引擎:一个最小化的边界检查 `ClientHello`/`ServerHello` 解析器以及 JA3/JA3S/JA4 字符串 + 哈希构建器。 没有 Arrow,没有 VGI,没有 I/O 操作。禁止使用 `unsafe`。**不包含 JA4+ / JARM 代码。** - **`tlsfp-worker`** —— 轻量级的 Arrow 适配器,用于注册标量函数并通过 VGI 提供服务。 ## 许可证 MIT —— 请参见 [LICENSE](LICENSE)。版权所有 2026 Query Farm LLC。是 [Query.Farm](https://query.farm) DuckDB worker 的 VGI 生态系统的一部分。
标签:可视化界面, 通知系统