news 2026/9/17 11:08:46

Fleet 与 osquery 实战:用 Community ID 把网络监控日志和端点进程行为关联起来

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Fleet 与 osquery 实战:用 Community ID 把网络监控日志和端点进程行为关联起来

Fleet 与 osquery 实战:用 Community ID 把网络监控日志和端点进程行为关联起来

【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet

本文以 Fleet 官方文章《Correlate network connections with community ID in osquery》为主体,讲解如何利用 Community ID 哈希将 Zeek、Suricata、Arkime 等网络监控工具的日志与 osquery 的端点数据精确关联:读完你将掌握从网络日志中提取 Community ID、用 osqueryi 实时定位连接所属进程、扩展二进制哈希富化,以及在 Fleet 中通过调度报告 + 外部日志目的地实现回溯式威胁调查的完整链路。

为什么需要把网络监控和端点监控关联起来

网络监控工具(Zeek、Suricata、Arkime 等)能看到"哪个 IP、哪个端口、什么协议在通信",但无法回答"这条连接是哪台主机上的哪个进程、以什么命令行参数发起的";反过来,osquery 的端点数据看不到完整的数据流与会话生命周期。两者之间缺少一个统一的关联键。

osquery 对 Community ID 哈希的支持恰好补上了这个缺口:只要网络侧和端点侧使用同一套哈希算法,就可以用一个确定性的字符串把两边的记录匹配起来。这套策略同样适用于任何支持 Community ID 的工具,包括 Arkime(原 Moloch)和 Suricata。

Community ID:连接参数的确定性哈希

Community ID 是对网络连接参数计算出的一个哈希值,用于在支持该哈希的多个监控方案之间匹配同一条连接。

其生成逻辑是:对**源和目的 IP 地址、源和目的端口、传输协议以及一个共享的 seed(种子)**共同执行哈希运算。关键特性在于:

  • 确定性:相同的五元组 + 协议 + seed 永远产生相同的哈希,因此不同软件、不同时间、不同机器计算出的结果可以逐字节比较;
  • 跨工具可比:网络监控侧(如 Zeek)算出的 Community ID,可以直接拿到端点侧(如 osquery)去反查,无需依赖 IP、时间戳等容易漂移的字段;
  • 粒度为连接级:它标识的是"这条连接",而不是"这个进程"或"这个会话",所以一条连接对应一个稳定的关联键。

osquery 在 SQL 层把该哈希暴露为community_id_v1()函数,接收本地地址、远端地址、本地端口、远端端口和协议五个参数,这正是后续所有查询的基础。

实战第一步:从 Zeek 的 conn.log 中提取 Community ID

假设我们用 Zeek 采集网络流量,其conn.log的最后一列就是每条连接的 Community ID。原文给出的真实日志片段如下:

$ cat /usr/local/zeek/logs/current/conn.log ... #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents community_id #types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] string 1582669704.509068 CEMnOh4OZTnzaUHWi 172.17.0.2 47434 192.168.65.1 53 udp dns 0.030783 0 36 SHR T T 0 Cd 0 0 164 - 1:M9OoSr2um69x5G8SikO3S7CVlKk= 1582669709.819653 CVTuEs4iasnpIw8nb7 172.17.0.2 35173 192.168.65.1 53 udp dns 0.004224 0 92 SHR T T 0 Cd 0 0 1120 - 1:1/6GSKCm6A8zk8jXFOEeZKTYccY= 1582669709.844549 CZX3af2jpkfeJzNItb 172.17.0.2 42716 13.227.76.23 443 tcp - 30.017714 0 0 SHR T F 0 ^hCf 0 0 288 - 1:l7a9beh8+bQe2MRtUW92OFmMMsM= 1582669741.641209 CQFgp24cLxMDaBPr03 172.17.0.2 50944 13.227.76.89 443 tcp - 1.691777 0 9653625 SHR T F 0 ^hCadCCCfA 1 406827 9926713 - 1:13GuW4mT6PnRwUi+zetPtsWWD3I= 1582669741.587538 CDvjoz2xAkMs4vbpo8 172.17.0.2 38330 192.168.65.1 53 udp dns 0.033607 0 352 SHR T T 0 Cd 0 0 2408 - 1:6tMXxnnFDfuiCIYTYXXCPMfB3fA=

假设安全分析师关注的是172.17.0.2:4271613.227.76.23:443的这条 TCP 连接。查看日志最后一列即可取出它的 Community ID:1:l7a9beh8+bQe2MRtUW92OFmMMsM=

注意该 ID 的版本前缀1:,以及 Base64 编码中出现的+/=字符——在 SQL 里引用它时务必原样用单引号包裹,不要做任何转义或截断处理。

实战第二步:用 osqueryi 反查连接背后的进程

拿到 Community ID 后,就可以把它当作连接句柄,直接在目标主机的 osquery 会话中反查。核心思路是:用community_id_v1()函数对process_open_sockets表中的每个 socket 现场计算 Community ID,与目标值比对,再 JOINprocesses表补全进程信息:

osquery> SELECT community_id_v1(local_address,remote_address,local_port,remote_port,protocol) AS community_id, * ...> FROM processes JOIN process_open_sockets USING (pid) ...> WHERE local_address AND remote_address AND community_id = '1:l7a9beh8+bQe2MRtUW92OFmMMsM='; community_id = 1:l7a9beh8+bQe2MRtUW92OFmMMsM= pid = 23689 name = nc path = /bin/nc.traditional cmdline = nc osquery.io 443 state = T cwd = /root root = / uid = 0 gid = 0 euid = 0 egid = 0 suid = 0 sgid = 0 on_disk = 1 wired_size = 0 resident_size = 2088000 total_size = 10880000 user_time = 0 system_time = 0 disk_bytes_read = 0 disk_bytes_written = 0 start_time = 1582669708 parent = 1 pgroup = 23689 threads = 1 nice = 0 fd = 3 socket = 138425 family = 2 protocol = 6 local_address = 172.17.0.2 remote_address = 13.227.76.23 local_port = 42716 remote_port = 443 path = state = CLOSE_WAIT net_namespace = 4026532309

这一份输出对 Zeek 看到的那条网络连接提供了大量上下文:

  • cmdline = nc osquery.io 443——实际发起连接的命令行;
  • path = /bin/nc.traditional——可执行文件路径;
  • uid = 0——以 root 身份运行的进程;
  • start_time = 1582669708——进程启动时间,与 Zeek 日志中连接建立时间(1582669709 附近)吻合,进一步佐证了关联的正确性。

结论非常清晰:这条172.17.0.2:42716 → 13.227.76.23:443的连接就是主机上用netcat工具连向osquery.io的行为。仅凭网络侧日志,这个判断是下不出来的。

Fleet 仓库的查询库 docs/queries.yml 中同样采用了process_open_sockets JOIN processes这一模式,例如"MITRE - Process Network Connections"查询(约 L3404-L3416):

name: MITRE - Process Network Connections platform: linux, darwin, windows query: |- select DISTINCT p.name, p.path, pos.remote_address, pos.remote_port from process_open_sockets pos LEFT JOIN processes p ON pos.pid = p.pid WHERE pos.remote_port != 0 AND p.name != '';

从源码结构看,processesprocess_open_socketspid关联是 Fleet 内置查询包中标准的网络连接取证模式,本文 Community ID 的用法只是在此之上多算了一个哈希列作为跨系统关联键。

实战第三步:再 JOIN hash 表,富化出二进制哈希

processes + process_open_sockets的回答止步于"哪个进程连的"。如果需要进一步回答"这个二进制的指纹是什么",可以在同一条查询里继续 JOINhash表(按path关联),取出该可执行文件的 MD5:

osquery> SELECT pid, processes.path, cmdline, md5 ...> FROM processes JOIN process_open_sockets USING (pid) JOIN hash USING (path) ...> WHERE local_address AND remote_address AND community_id_v1(local_address,remote_address,local_port,remote_port,protocol) = '1:l7a9beh8+bQe2MRtUW92OFmMMsM='; pid = 23689 path = /bin/nc.traditional cmdline = nc osquery.io 443 md5 = 1c50c85a1472d0124194f21a12ade35e

拿到的md5 = 1c50c85a1472d0124194f21a12ade35e可以继续用于威胁情报比对、恶意样本库检索等下游动作。整个调查链条因此是:Zeek 发现可疑连接 → Community ID 反查进程 → 二进制哈希富化 → 情报比对,全程只靠一个确定性哈希串串联。

从实时调查到回溯分析:调度查询与日志管道

上面的例子是在事发时用osqueryi做的实时调查。但更常见的场景是:网络监控先报了警,事后才要去主机上复盘。这时需要让端点数据持续留痕

做法是在osqueryd中调度一条定时查询,把每条网络连接的 Community ID 连同关联进程细节一起记录下来:

SELECT *, community_id_v1(local_address,remote_address,local_port,remote_port,protocol) AS community_id FROM processes JOIN process_open_sockets USING (pid) JOIN hash USING (path)

这些结果日志可以汇入日志聚合管道/SIEM,之后网络监控侧出现的任何 Community ID 都能直接在历史结果里检索出对应的进程、命令行和二进制哈希。

在 Linux 上,socket_events表还能提供额外价值:它捕获的是所有发生过的socket 连接,而不只是查询执行瞬间仍然活跃的连接,对短暂连接的回溯分析尤其有用。

在 Fleet 中落地这条链路

Fleet 把这条"调度—上报—外发"链路做成了产品化能力,仓库中有两处可直接参照的实现依据:

1. 调度报告的执行流程。docs/Contributing/reports/scheduled-queries.md 描述了 Fleet 定时查询架构的三步数据流:

1. Fleet 用户创建报告(UI 或 API)→ Server → DB 2. osquery agent 向 Server 拉取配置(含调度报告),Server 合并 fleet 级与全局配置下发 3. agent 按调度执行报告,结果回传 Server,Server 可选转发到外部日志系统

把上面那条带community_id_v1的 SQL 建成报告并指派给目标主机/team,即可让每台主机的连接级端点数据按周期回传。

2. 结果日志外发到 SIEM。Fleet 的日志目的地机制(result log / status log)支持把报告结果转发到外部系统,articles/log-destinations.md 列出了可用的目的地。例如发送到 Splunk 时,通过 HEC 端点直发,配置形如:

osquery: status_log_plugin: splunk result_log_plugin: splunk splunk: url: https://splunk.example.com:8088 token: your-hec-token index: main source: fleet source_type: fleet:json

此外还支持 Amazon Kinesis Data Firehose(可再经 S3/Snowpipe 进入 Snowflake)、Webhook 等目的地。事件按批聚合后发送,超过批量上限的事件会被丢弃并在 Fleet 服务端日志中记录通知——在规划管道容量时需要注意这一点。

由此形成完整的闭环:

Zeek/Suricata 网络日志 ──(community_id)──▶ SIEM 告警 osquery 调度报告(含 community_id) ──(Fleet 日志目的地)──▶ 同一 SIEM └─▶ 按 community_id 关联出进程/cmdline/md5

适用前提与限制

  • 两侧算法必须一致:Community ID 的可比性建立在"相同参数 + 相同 seed"之上。若网络侧与端点侧使用了不同版本算法或不同 seed,哈希将无法匹配,关联失效;
  • 粒度限制:Community ID 标识的是连接而非会话,NAT 之后不同主机的连接在网络侧可能呈现为同一 ID,跨 NAT 边界做主机级归因时要结合其他字段;
  • 实时查询的时机性process_open_sockets只反映查询执行时刻仍存在的连接,事发即断开的短暂连接要靠调度留痕或 Linux 的socket_events表回溯;
  • 哈希富化的前提:JOINhash表要求path字段有效且文件在盘上可读(on_disk = 1),动态加载、无文件进程拿不到哈希。

小结

Community ID 用"连接五元组 + 协议 + seed 的确定性哈希"为网络监控与端点监控之间提供了一个稳定、跨工具、可直接比对的关联键。osquery 的community_id_v1()函数让端点侧可以现场计算该哈希,配合processes JOIN process_open_sockets(必要时再 JOINhash)即可把一条网络日志还原成"哪个进程、什么命令行、什么二进制、哪个用户"的完整画像;在 Fleet 中,把这条 SQL 建成调度报告并接入外部日志目的地,还能把这种关联能力从实时调查扩展到事后的全量回溯分析。

【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 11:08:20

Source SDK 2013 完整指南:从编译环境到跑通第一个游戏模组

Source SDK 2013 完整指南:从编译环境到跑通第一个游戏模组 【免费下载链接】source-sdk-2013 The 2013 edition of the Source SDK 项目地址: https://gitcode.com/GitHub_Trending/so/source-sdk-2013 Source SDK 2013 是 Valve 官方放出的 Source 引擎开发…

作者头像 李华
网站建设 2026/9/17 11:07:33

Hister 全文索引完全揭秘:语言分析器与倒排索引原理

Hister 全文索引完全揭秘:语言分析器与倒排索引原理 【免费下载链接】hister Your own search engine 项目地址: https://gitcode.com/GitHub_Trending/hi/hister Hister 是一个自托管的全文搜索引擎:它把访问过的网页和本地文件的内容完整存下来…

作者头像 李华
网站建设 2026/9/17 11:07:10

液晶屏选型与驱动实战:从段码屏到TFT的完整避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 11:06:59

d3dx9_26.dll缺失:DirectX旧组件与运行库排查指南

周末从柜子里翻出一张十几年前的老游戏光盘,装完、双击图标,屏幕正中弹出一行小字:找不到 d3dx9_26.dll。这个提示我前后遇到过不下几十次,从 Windows XP 时代一直到现在的 Windows 11,它出现的姿势几乎没变过。很多人…

作者头像 李华