网络活动日志记录

本文档介绍了设备政策控制器 (DPC) 如何记录网络活动。继续阅读以了解如何将网络日志记录添加到您的 DPC。

概览

记录网络活动可以帮助企业检测和跟踪恶意软件在其设备上的传播。您的 DPC 可以调用网络日志记录 API,以报告系统网络调用中的 TCP 连接和 DNS 查找。

通常,您的 DPC 会将日志传送到服务器,以便 IT 管理员查看。您可能希望在服务器上或设备本地进一步处理日志。例如,您可以设置 DNS 拒绝列表,以检测可疑行为并提醒 IT 管理员。

可用性

网络日志记录在 Android 8 及更高版本中支持设备所有者。如果启用,它会收集设备的网络活动数据。它还在 Android 12 及更高版本中支持受管资料的资料所有者和具有 DELEGATION_NETWORK_LOGGING 的委托应用。当资料所有者启用网络日志记录时,网络日志仅包含工作资料网络活动,不收集个人资料的数据。

要了解更多信息,请阅读 关联用户

事件日志

当网络日志记录处于活动状态时,Android 会记录使用系统网络库的应用中的每个事件。网络日志记录会记录两种类型的事件

  • DNS 查找
  • 网络连接

DNS 查找

网络日志记录会记录作为系统网络请求一部分的 DNS 查找事件。日志会捕获将主机名解析为 IP 地址的每个 DNS 请求。其他支持性 DNS 查询(例如名称服务器发现)不会被记录。

网络活动日志记录 API 将每个 DNS 查找表示为一个 DnsEvent 实例。表 1 描述了记录到 DnsEvent 的字段和典型值。

表 1. DNS 事件字段

数据 示例 描述
主机名 host.example.com DNS 查询中发送的主机名。
Inet 地址 203.0.113.9, 198.51.100.25 DNS 查询为主机名解析出的 IPv4 或 IPv6 地址列表。为了控制日志大小,结果可能不包含所有 IP 地址——请参阅下一行中的地址计数。
地址计数 4 DNS 查询解析返回的 IP 地址数量。使用此字段可了解记录的 IP 地址是否为结果的子集。值为 0(零)表示主机名未解析为 IP 地址。
软件包名称 com.android.chrome 发起 DNS 查询的应用的软件包名称。
时间戳 1506297600000 记录 DNS 查找发生时的时间戳。该值是 DNS 查找与协调世界时 1970 年 1 月 1 日午夜之间的毫秒间隔。
ID 25 单调递增的数字 ID。在 Android 9.0(API 级别 28)或更高版本中可用。

虽然 DNS 查找可以帮助 IT 管理员跟踪 网络连接,但网络日志记录并非通用的 DNS 记录解决方案。以下是应用可能执行的一些未记录的 DNS 任务

  • 直接与 DNS 名称服务器通信。
  • 调用 Java DNS 库进行 DNS 查询。
  • 通过连接到固定 IP 地址来避免 DNS 查询。

网络连接

网络日志记录会记录作为系统网络请求一部分的每次尝试连接的事件。日志会捕获成功和失败的 TCP 连接——UDP 传输不会被记录。

网络活动日志记录 API 将每个连接表示为一个 ConnectEvent 实例。表 2 描述了记录到 ConnectEvent 的字段和典型值。

表 2. 连接事件字段

数据 示例 描述
Inet 地址 2001:db8::2f:abc:0 设备连接到的 IP 地址。这可能是 IPv4 或 IPv6 地址。
端口 80 设备连接到的 TCP 端口号。
软件包名称 com.android.chrome 发起连接的应用的软件包名称。
时间戳 1506297600000 记录网络连接发生时的时间戳。该值是连接与协调世界时 1970 年 1 月 1 日午夜之间的毫秒间隔。
ID 26 单调递增的数字 ID。在 Android 9.0(API 级别 28)或更高版本中可用。

当应用调用标准网络库(例如 Android 的内置 API 或流行的第三方库)连接到主机时,网络日志记录会记录一个事件。直接发出系统调用进行通信的应用不会被记录。请记住,UDP 网络连接不会被记录,因此某些媒体流、消息传递和游戏应用可能不会出现在日志中。

告知用户

系统会提醒设备用户网络活动日志记录处于活动状态。用户会在界面中看到以下警告

  • 设备管理 对话框中有一个部分解释了您的 DPC 正在监控网络流量。用户可以通过在“快速设置”中点击托管设备信息标签来查看此对话框。
  • 当用户刚接触网络日志记录时,会显示一个可关闭的系统通知。点击该通知会显示 设备监控 对话框,其中网络监控部分提供了进一步的解释。当您的 DPC 禁用网络日志记录时,该通知会消失。

将网络日志记录添加到您的 DPC

为了帮助 IT 管理员审核网络日志,您的 DPC 需要能够完成以下任务

  • 启用和禁用网络日志记录。
  • 当新批次准备就绪时检索所有已记录的日志。
  • 将日志中有用的数据发送到服务器。

要求

网络日志记录适用于 Android 8.0(API 级别 26)或更高版本的设备所有者,以及 Android 12(API 级别 31)或更高版本的托管资料的资料所有者。在记录网络活动之前,您的 DPC 应检查它是否是设备所有者或托管资料的资料所有者。如果由资料所有者启用,则具有工作资料的设备所有者中的网络日志不包含个人资料上的网络活动。

启用网络日志记录

要开始记录网络活动,请调用 DevicePolicyManager 方法 setNetworkLoggingEnabled() 并将 true 作为 enabled 参数传递。您的 DPC 可以调用 isNetworkLoggingEnabled() 来检查网络活动是否已记录。

DPC 启用网络日志记录后,可能需要一段时间才能准备好第一批日志。您可能希望在用户界面中为 IT 管理员设置交付预期。

要停止记录网络活动,请调用 setNetworkLoggingEnabled() 并传递 false。当 IT 管理员关闭网络日志记录时,系统会删除所有已收集但未报告的日志。

检索日志

您的 DPC 可以批量检索日志——网络日志记录 API 不提供对过去单个条目的随机访问。当新批次日志可用时,您的 DPC 的 DeviceAdminReceiver 子类会收到 onNetworkLogsAvailable() 回调。回调包含一个批次令牌,您的 DPC 可以使用它来检索日志。您的 DPC 调用 DevicePolicyManager 方法 retrieveNetworkLogs() 来获取网络事件列表。

以下示例展示了您如何在 DeviceAdminReceiver 子类中检索日志

Kotlin

fun onNetworkLogsAvailable(
        context: Context, intent: Intent, batchToken: Long, networkLogsCount: Int) {

    val dpm = getManager(context)
    var logs: List<NetworkEvent>? = null

    // Fetch the batch of logs with the batch token from the callback's arguments.
    try {
        logs = dpm.retrieveNetworkLogs(getWho(context), batchToken)
    } catch (e: SecurityException) {
        // Perhaps an unaffiliated user - handle the exception ...
    }

    // Process any logs ...
}

Java

public void onNetworkLogsAvailable(
    Context context, Intent intent, long batchToken, int networkLogsCount) {

  DevicePolicyManager dpm = getManager(context);
  List<NetworkEvent> logs = null;

  // Fetch the next batch of logs using the callback's batch token argument.
  try {
    logs = dpm.retrieveNetworkLogs(getWho(context), batchToken);
  } catch (SecurityException e) {
    // Perhaps an unaffiliated user - handle the exception ...
  }

  // Process any logs ...
}

您的 DPC 应立即检索日志,因为系统会删除日志以为新批次腾出空间。您可能希望保留日志的本地副本,直到确定您的 DPC 已无问题地处理完所有日志。

处理日志

一批日志通常包含 DnsEventConnectEvent 实例的混合。要了解有关 DNS 查找和网络连接数据字段的更多信息,请参阅 事件日志。事件按时间顺序排列,每个批次包含不超过 1200 个事件。

调用检索日志后,请检查返回值是否不为 null。如果发生以下任一情况,该值可能为 null

  • 由批次令牌表示的批次不再可用。您的 DPC 无法检索该批次,应等待下一批次。
  • IT 管理员禁用了网络日志记录。

以下简化示例展示了 DPC 如何提取已解析的 DNS 主机名。您的 DPC 需要更复杂的处理和报告功能。

Kotlin

// Here, logs might be null. We can't fix because either the token doesn't match
// the current batch or network logging was deactivated.
// Confirm with isNetworkLoggingEnabled().

logs?.forEach {
    // For this example, report the DNS hosts and discard all other data.
    // Because we use the event ID, this example requires API level 28.
    if (it is DnsEvent) {
        reportDnsHostToServer(it.hostname, it.getTimestamp(), it.getId())
    }
}

Java

if (logs == null) {
  // Abandon processing because either the token doesn't match the current batch
  // or network logging was deactivated - confirm with isNetworkLoggingEnabled().
  return;
}

for (NetworkEvent event : logs) {
  // For this example, report the DNS hosts and discard all other data.
  // This example requires API level 28 because we use the event ID.
  if (event instanceof DnsEvent) {
    reportDnsHostToServer(
        ((DnsEvent) event).getHostname(), event.getTimestamp(), event.getId());
  }
}

前面的示例还展示了如何获取 Android 9.0(API 级别 28)或更高版本中包含的事件的数字 ID。由于 ID 会为每个事件单调递增,因此您可以帮助 IT 管理员发现日志中的空白。每当 DPC 启用日志记录或设备重新启动时,系统都会重置 ID。

您的 DPC 可以将整个集合发送到服务器,或者您可以选择在设备上过滤事件。例如,您可以为 IT 管理员提供允许列表报告。

开发和测试

在开发和测试期间,您可能希望接收 onNetworkLogsAvailable() 回调,而无需浏览数百个网页。在 Android 9.0(API 级别 28)或更高版本中,您可以发出一些示例网络请求,并强制系统发送日志可用回调。在您的终端中运行以下 Android 调试桥 (adb) 命令

adb shell dpm force-network-logs

系统限制了您使用该工具的频率,并在终端输出中报告任何故意的减速。如果没有可检索的日志,您的 DPC 不会收到回调。