ネットワーク アクティビティ ログ

このドキュメントでは、Device Policy Controller(DPC)がネットワーク アクティビティを記録する方法について説明します。引き続き、DPC にネットワーク ロギングを追加する方法をご確認ください。

概要

ネットワーク アクティビティのロギングは、企業がデバイス上でマルウェアの拡散を検出して追跡するのに役立ちます。DPC はネットワーク ロギング API を呼び出して、システム ネットワーキング呼び出しからの TCP 接続と DNS ルックアップを報告できます。

通常、DPC は IT 管理者に提示するためにログをサーバーに配信します。サーバー上でログをさらに処理することも、デバイス上でローカルに処理することもできます。たとえば、DNS 拒否リストを設定して、不審な動作を検出して IT 管理者に通知できます。

提供状況

Android 8 以降では、デバイス所有者のネットワーク ロギングがサポートされています。有効にすると、デバイスのネットワーク アクティビティに関するデータが収集されます。Android 12 以降では、DELEGATION_NETWORK_LOGGING を使用して、管理対象プロファイルのプロファイル所有者と委任されたアプリもサポートされています。プロファイル オーナーがネットワーク ロギングを有効にしている場合、ネットワーク ログには仕事用プロファイルのネットワーク アクティビティのみが含まれ、個人用プロファイルからはデータは収集されません。

詳しくは、関係のあるユーザーをご覧ください。

イベントログ

ネットワーク ロギングが有効な場合、Android はシステム ネットワーキング ライブラリを使用してアプリからの各イベントを記録します。ネットワーク ロギングでは、次の 2 種類のイベントが記録されます。

  • DNS ルックアップ
  • ネットワーク接続

DNS ルックアップ

ネットワーク ロギングは、システム ネットワーク リクエストの一部である DNS ルックアップのイベントを記録します。このログには、ホスト名を IP アドレスに解決する各 DNS リクエストが記録されます。ネームサーバーの検出など、他のサポート DNS クエリは記録されません。

ネットワーク アクティビティ ロギング API は、各 DNS ルックアップを DnsEvent インスタンスとして提示します。表 1 は、DnsEvent に記録されるフィールドと一般的な値を示しています。

表 1. DNS イベント フィールド

データ 説明
ホスト名 host.example.com DNS クエリで送信されたホスト名。
Inet アドレス 203.0.113.9198.51.100.25 DNS クエリがホスト名に対して解決した IPv4 または IPv6 アドレスのリスト。ログのサイズを扱いやすいように、結果にすべての IP アドレスが含まれない場合があります。次の行のアドレス数をご覧ください。
住所数 4 DNS クエリ解決から返された IP アドレスの数。これを使用して、ログに記録された IP アドレスが結果のサブセットであるかどうかを確認できます。値 0(ゼロ)は、ホスト名が IP アドレスに解決されなかったことを示します。
パッケージ名 com.android.chrome DNS クエリを実行したアプリのパッケージ名。
タイムスタンプ 1506297600000 DNS ルックアップが行われたときの記録。この値は、DNS ルックアップから 1970 年 1 月 1 日 UTC 午前 0 時からのミリ秒間隔です。
ID 25 単調に増加する数値 ID。Android 9.0(API レベル 28)以降で使用できます。

DNS ルックアップは、IT 管理者はネットワーク接続の追跡に役立ちますが、ネットワーク ロギングは汎用の DNS 記録ソリューションではありません。ログに記録されない、アプリで実行される可能性がある DNS タスクは次のとおりです。

  • DNS ネームサーバーと直接通信する。
  • Java DNS ライブラリを呼び出して DNS クエリを実行します。
  • 固定 IP アドレスに接続して DNS クエリを回避する

ネットワーク接続

ネットワーク ロギングは、システム ネットワーク リクエストの一部として、接続が試行されるたびにイベントを記録します。ログには、成功した TCP 接続と失敗した 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 日(UTC)の深夜 0 時からのミリ秒単位の間隔です。
ID 全角 13 文字相当 単調に増加する数値 ID。Android 9.0(API レベル 28)以降で使用できます。

ネットワーク ロギングは、アプリが Android の組み込み API や一般的なサードパーティ ライブラリなどの標準のネットワーク ライブラリを呼び出してホストに接続したときに、イベントを記録します。通信するためにシステムコールを直接発行するアプリはログに記録されません。UDP ネットワークはログに記録されないため、一部のメディア ストリーミング、メッセージング、ゲームアプリはログに表示されない場合があります。

ユーザーに通知する

ネットワーク アクティビティ ロギングがアクティブであることを、システムによってデバイスのユーザーに通知されます。ユーザーのインターフェースには、次の警告が表示されます。

  • DPC がネットワーク トラフィックをモニタリングしていることを示す [デバイス管理] ダイアログのセクション。ユーザーは、クイック設定で管理対象デバイスの情報ラベルをタップすると、ダイアログが表示されます。
  • ユーザーがネットワーク ロギングを初めて行う間に表示される、閉じることができるシステム通知。通知をタップすると、[Device monitoring] ダイアログとネットワーク モニタリングのセクションに詳しい説明が表示されます。DPC がネットワーク ロギングを無効にすると、通知は表示されなくなります。

ネットワーク ロギングを DPC に追加する

IT 管理者がネットワーク ログを確認できるように、DPC は次のタスクを実行できる必要があります。

  • ネットワーク ロギングをオンまたはオフにします。
  • 新しいバッチの準備ができたら、記録されたログを取得します。
  • ログに含まれる有用なデータをサーバーに送信する。

要件

ネットワーク ロギングは、デバイス所有者は Android 8.0(API レベル 26)以降、管理対象プロファイルのプロファイル所有者は Android 12(API レベル 31)以降で使用できます。DPC は、ネットワーク アクティビティをログに記録する前に、それが管理対象プロファイルのデバイス所有者かプロファイル所有者かを確認する必要があります。仕事用プロファイルを持つデバイス所有者のネットワーク ログに個人用プロファイルのネットワーク アクティビティは含まれません(個人用プロファイルがネットワーク アクティビティを有効にしている場合)。

ネットワーク ロギングを有効にする

ネットワーク アクティビティのロギングを開始するには、DevicePolicyManager メソッド setNetworkLoggingEnabled() を呼び出し、enabled 引数として true を渡します。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 がログをすべて問題なく処理したことを確認するまで、ログのローカルコピーを保持することをおすすめします。

ログを処理する

通常、ログのバッチには DnsEvent インスタンスと ConnectEvent インスタンスが混在しています。DNS ルックアップとネットワーク接続のデータ フィールドの詳細については、イベントログをご覧ください。イベントは時系列で表示され、各バッチには 1,200 個以下のイベントが含まれます。

ログを取得する呼び出しの後、戻り値が 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 Debug Bridge(adb)コマンドを実行します。

adb shell dpm force-network-logs

システムはツールの使用頻度を制限し、意図的な速度低下をターミナル出力に報告します。取得するログがない場合、DPC はコールバックを受信しません。