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:l7a9beh8bQe2MRtUW92OFmMMsM 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:13GuW4mT6PnRwUizetPtsWWD3I 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:42716到13.227.76.23:443的这条 TCP 连接。查看日志最后一列即可取出它的 Community ID1:l7a9beh8bQe2MRtUW92OFmMMsM。注意该 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:l7a9beh8bQe2MRtUW92OFmMMsM; community_id 1:l7a9beh8bQe2MRtUW92OFmMMsM 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-L3416name: 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 ! ;从源码结构看processes与process_open_sockets按pid关联是 Fleet 内置查询包中标准的网络连接取证模式本文 Community ID 的用法只是在此之上多算了一个哈希列作为跨系统关联键。实战第三步再 JOIN hash 表富化出二进制哈希processes process_open_sockets的回答止步于哪个进程连的。如果需要进一步回答这个二进制的指纹是什么可以在同一条查询里继续 JOINhash表按path关联取出该可执行文件的 MD5osquery 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:l7a9beh8bQe2MRtUW92OFmMMsM; 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 按调度执行报告结果回传 ServerServer 可选转发到外部日志系统把上面那条带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),仅供参考