> ## Documentation Index
> Fetch the complete documentation index at: https://hilt.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 端到端数据流

> 一条 macOS 端点事件如何从 ESensor 系统扩展出发，经本机转发器与边缘采集器，进入 MSK 与富化，最终到达 ClickHouse 和仪表盘。

在 Mac 上观察到的每一条事件，都沿同一条路径从内核抵达仪表盘。macOS 采集器就是已公证的 **Hilt EDR** 应用（`EDRApp.app`，Team ID `MVMB6LCP2A`），它内嵌 **ESensor** Endpoint Security 系统扩展作为遥测来源。ESensor 发出 JSON，本机转发器 LaunchDaemon 将其批量打包并经出站 HTTPS 发送，而服务于 Linux 采集器的同一套 Hilt 控制平面对其进行富化与存储 — 唯一的平台差异在于富化配置和目标表。

本页端到端地追踪单条事件。关于主机侧架构见[采集器概览](https://hilt.ai/docs/zh/macos-collector/layout.md)；关于采集内容与列式模式见[事件数据模型](https://hilt.ai/docs/zh/macos-collector/event-data-model.md)。

## 管道全景

**1. ESensor (Endpoint Security extension)**

ESensor 系统扩展订阅 Apple Endpoint Security 的 `NOTIFY` 事件，并将每一条事件作为单行 JSON 发出，同时打上代码签名信任与应用归因信息。不涉及任何内核扩展 — ESensor 是运行在 Apple 现代框架之上的纯用户态 System Extension。

**2. Local forwarder (LaunchDaemon)**

一个小型转发器 LaunchDaemon 跟踪 ESensor 的 JSON 流，将事件批量打包，并经出站 HTTPS 以 HTTP-POST 发送到配置的 Hilt 摄取端点。若端点不可达，它会将事件溢写到磁盘，并在连接恢复时排空。

**3. edr-collector /ingest (edge VPC)**

采集器在其 `/ingest` 端点终结 HTTPS POST，校验批次，并按事件类别将每条事件路由到对应的 Kafka 主题。它独立部署在公网边缘 VPC 中，因此漫游中的 Mac 可直接通过互联网到达 — 无需 VPN。

**4. MSK Kafka (dag.endpoint.\*)**

采集器将事件生产到核心 Amazon MSK 集群的 `dag.endpoint.exec`、`dag.endpoint.file` 与 `dag.endpoint.net` 主题上，这些主题缓冲事件流，并将摄取与富化解耦。

**5. Enrichment (ENRICH\_PLATFORM=macos)**

富化服务以 macOS 配置消费 `dag.endpoint.*` 主题。它将每条事件的 `responsible_pid` 解析为归属应用与逐实例会话，规范化代码签名标识，并写入带类型的行。

**6. ClickHouse (endpoint\_events)**

富化后的行落入专门构建的 macOS 原生 ClickHouse 表 `endpoint_events`，按 `event_class` / `event_type` 定型，携带代码签名列与应用归因列，外加用于安全长尾的 `attrs` 映射。

**7. Dashboard**

macOS 主机以 macOS 主机类型徽章出现在采集器机群中，其事件遍布 Investigate、Networks、Files 与 Users 视图 — 可按签名信任与归属应用查询。

***

## 阶段 1 — ESensor 发出 JSON

ESensor 是一个内嵌于 Hilt EDR 应用的 **Endpoint Security (ES) 系统扩展**（bundle id `Hilt.EDRApp.ESensor`）。它打开一个 ES 客户端，订阅一组固定的 `NOTIFY` 事件，施加激进的用户态过滤，并将每条幸存事件写为单行 JSON。

**订阅内容。** ESensor 采集进程、文件、持久化、设备与网络遥测：

| Class | Event types |
| :- | :- |
| **process** | `exec`（含 `argv` + 签名标识）、`fork`、`signal`（kill 尝试） |
| **file** | `file_open`（open/create）、`file_unlink`、`file_rename`、`file_chmod`、`xattr_set` / `xattr_delete`（Gatekeeper 隔离篡改） |
| **persistence** | `btm_add` — 安装 launch agent/daemon/登录项（macOS 13+ Background Task Management） |
| **device** | `mount` — 可移动介质 |
| **network** | `net_flow` — 出站 TCP 流，含目的地、端口、字节数与 bundle id |

**流量现实。** `file_open` 主导整个流，约占全部事件的 95%+，因此 ESensor 在发出任何内容前会在用户态激进过滤。只有与安全相关的剩余部分才被写入 JSON 流并交给转发器。

> [!NOTE]
>
> 网络来源是逐流的 Network Extension 内容过滤器（`Hilt.EDRApp.NetFilter`，带 `lsof` 回退），而非 Endpoint Security。ES 没有网络事件；这正是网络归因以 `net_flow` 而非某个 ES `NOTIFY` 类型出现的原因。见[事件数据模型](https://hilt.ai/docs/zh/macos-collector/event-data-model.md)。

### 信任与归因在源头打戳

macOS 采集器的决定性特性在于：**每一条事件**都携带一等的代码签名信任与应用归因 — 这些是 Linux 采集器无法表达的字段。它们在发出时从 Endpoint Security 进程记录中解析而来，而非事后附加：

| Field | Meaning |
| :- | :- |
| `code_signature` | 信任判定：`platform`、`developer_id`、`adhoc` 或 `unsigned_or_invalid` |
| `signing_id` | 执行二进制的 bundle id，例如 `com.google.Chrome` |
| `team_id` | Apple 开发者 Team ID（对 Apple 平台二进制为空，这是正确的） |
| `cdhash` | 代码目录哈希 — 二进制完整性，在 `exec` 时设置 |
| `application_id` / `application_display_name` | 归属应用 — 辅助进程折叠回父应用（例如 `Google Chrome Helper` → `Google Chrome`） |
| `responsible_pid` | Apple ES 的"responsible process" — 应用与会话归因的依据 |
| `session_id` | 逐应用实例的会话 |
| `device_name` | 人类可读的 Mac 名称 |

由于信任与应用标识随事件一同传递，像"哪个**未签名**应用读取了 `~/.ssh`"这样的查询，在下游只是单个 `WHERE` 子句。

***

## 阶段 2 — 本机转发器批量打包并经 HTTPS 发送

转发器是与 Hilt EDR 应用一同安装的轻量 LaunchDaemon。它掌管网络路径；ESensor 本身不打开任何 socket。

* **跟踪与批处理。** 它读取 ESensor 的 JSON 行流，将事件累积成批，并 POST 到采集器的 `/ingest` 端点。
* **仅出站 HTTPS。** 唯一目的地是配置的 Hilt 摄取端点，经出站 HTTPS 到达。**没有入站 socket，也不回连（phone-home）** — 每个连接都由主机发起。
* **漫游友好。** 由于采集器位于公网边缘 VPC，转发器无论 Mac 身处何地都能直接通过互联网到达。无需 VPN 或企业网络。

### 断连时溢写

当摄取端点不可达时 — 合上的笔记本、不稳定的网络、强制门户（captive portal）— 转发器不会丢弃事件。它**将事件在本地溢写到磁盘**，并继续接收来自 ESensor 的新事件。连接恢复后，溢写会按顺序排空到采集器，因此曾离线的 Mac 会回填其时间线，而不会留下空白。

> [!NOTE]
>
> 溢写让 macOS 采集器能够耐受笔记本常见的间歇性连接。代价是：事件在仪表盘中出现的时刻反映的是主机重新连接的时间，未必是活动实际发生的时间 — 事件自身的内核时间戳仍是排序的权威来源。

***

## 阶段 3 — edr-collector /ingest

**edr-collector** 是边缘摄取服务。它独立运行在**公网边缘 VPC** 中，以便漫游中的 Mac 能通过互联网到达，也是主机唯一会对话的组件。

* **接收** 批量的 HTTPS POST 于 `/ingest`，校验载荷，并确认批次，使转发器能将其从溢写中释放。
* **按类别路由。** 它将每条事件映射到一个 Kafka 主题 — 进程事件到 `dag.endpoint.exec`，文件事件到 `dag.endpoint.file`，网络流到 `dag.endpoint.net`。
* **生产** 到核心 MSK 集群，走一条只写路径：采集器可以向 `dag.endpoint.*` 主题发布，但不能回读，也不能到达核心网络中的任何其他内容。

采集器不持有长期状态，也不执行富化；它只是公网互联网与内部 Kafka 总线之间的一个路由与缓冲跳。关于信任边界见[网络与安全](https://hilt.ai/docs/zh/macos-collector/networking-security.md)。

***

## 阶段 4 — MSK Kafka (dag.endpoint.\*)

事件在 **Amazon MSK** 上跨三个主题缓冲，按事件类别分区：

| Topic | Carries |
| :- | :- |
| `dag.endpoint.exec` | 进程事件 — `exec`、`fork`、`signal` |
| `dag.endpoint.file` | 文件事件 — `file_open`、`file_unlink`、`file_rename`、`file_chmod`、`xattr_set`、`xattr_delete` |
| `dag.endpoint.net` | 网络事件 — `net_flow` |

Kafka 将摄取与富化解耦：即使富化短暂落后，采集器也能持续接收事件；而富化可以重启或扩缩容而不丢失流。同样的 `dag.endpoint.*` 主题也承载 Linux 采集器的端点流 — 平台的区分在下游完成，而非靠主题区分。

***

## 阶段 5 — 富化 (ENRICH\_PLATFORM=macos)

一个专用、故障隔离的富化部署以 **`ENRICH_PLATFORM=macos`** 消费 `dag.endpoint.*` 主题。正是这一配置让行成为 macOS 原生，而非 Linux 形态：

* **解析 `responsible_pid` → 应用 + 会话。** Apple ES 的"responsible process"被转换为归属的 `application_id` / `application_display_name` 以及逐实例的 `session_id`，将辅助进程折叠回其父应用。正是这一步让仪表盘能按应用而非原始进程对活动分组。
* **规范化代码签名标识。** `code_signature` 判定、`signing_id`、`team_id` 与 `cdhash` 被校验并作为一等的带类型列写入。
* **为事件定型。** 每条事件以 `event_class` / `event_type` 为键，因此文件、进程、持久化、设备与网络事件共享同一张表，而不带 Linux 的 cgroup/k8s/container 杂项。
* **保留长尾。** 那些不值得单列的安全相关属性（例如隔离剥离时的 `xattr` 名称、`mount` 上的可移动介质标志）被写入 `attrs` 映射。

macOS 富化作为独立于 Linux 端点路径的消费者运行，从而使一个平台流上的问题不会拖垮另一个。

***

## 阶段 6 — ClickHouse (endpoint\_events)

富化后的行被写入专门构建的 ClickHouse 表 **`endpoint_events`** — 实时的 macOS 遥测表。它在设计上即为 macOS 原生：

* 按 `event_class` / `event_type` 定型，而非从 Linux 模式克隆而来；
* 将代码签名标识列（`code_signature`、`signing_id`、`team_id`、`cdhash`）与应用归因列（`application_id`、`application_display_name`、`responsible_pid`、`session_id`、`device_name`）作为一等字段携带；
* 包含用于安全长尾的 `attrs` 映射；
* 完全省略仅 Linux 的概念（cgroup、container、pod、node、k8s）。

这张单一的表是仪表盘中每个 macOS 视图的免连接（join-free）后备存储 — `device_name` 意味着渲染一台主机无需做主机清单连接。

> [!NOTE]
>
> 早期的 macOS 行曾写入 Linux 模式的克隆表（`dag_events_endpoint`）；该表已退役，不再写入。`endpoint_events` 是权威目标。完整列清单见[事件数据模型](https://hilt.ai/docs/zh/macos-collector/event-data-model.md)。

***

## 阶段 7 — 仪表盘视图

macOS 主机及其事件遍布仪表盘：

* **采集器机群** — 每台已注册的 Mac 都带 **macOS 主机类型徽章**出现，由其 `device_name` 标识，与同一机群视图中的 Linux 采集器并列。
* **Investigate** — 进程、文件与持久化活动，可按签名信任（`code_signature`）与归属应用（`application_display_name`）过滤。
* **Networks** — 出站 `net_flow` 活动，归因到 responsible 应用与 bundle id。
* **Files** — 文件的 open、delete、rename、chmod 与隔离篡改事件。
* **Users** — 按执行用户与会话分组的活动。

由于信任与应用标识是列而非派生字段，仪表盘支持 Linux 采集器无法表达的查询 — 例如，找出每一个触及敏感路径的 `developer_id` 但非 `platform` 二进制，或每一个 `code_signature` 为 `unsigned_or_invalid` 的应用。

***

## 此数据流不做什么

macOS 采集器仅在元数据级别观察系统活动。该数据流明确**不**包含：

* **入站连接或回连（phone-home）。** 转发器只做到配置的摄取端点的出站 HTTPS；没有任何组件监听入站 socket。
* **文件内容、报文载荷、内存或环境变量。** 事件仅携带元数据 — 路径、标识符、签名标识与流元组 — 从不携带进程读取或写入的数据本身。
* **内核扩展。** ESensor 与 NetFilter 都是用户态 System Extension；没有 kext，也无需 `csrutil disable`。采集器在**启用 System Integrity Protection** 的情况下运行。见[系统要求](https://hilt.ai/docs/zh/macos-collector/system-requirements.md)。
* **设备端响应或自动更新。** 在早期访问期间，管道仅做遥测；自动更新与设备端隔离响应在 macOS 上尚未提供。

> [!NOTE]
>
> **状态：早期访问。** 已公证的、以 SIP 开启方式安装的 `.pkg`，以及本页所述的数据流，即为交付模型。设备端响应与 agent 自动更新已在规划中，但在 macOS 上尚未提供。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.