네트워크 활동 로깅

이 문서에서는 기기 정책 컨트롤러 (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 조회와 UTC 1970년 1월 1일 자정 사이의 밀리초 간격입니다.
ID 25 단조 증가하는 숫자 ID입니다. Android 9.0 (API 수준 28) 이상에서 사용할 수 있습니다.

DNS 조회는 IT 관리자의 네트워크 연결을 추적하는 데 도움이 되지만 네트워크 로깅은 범용 DNS 기록 솔루션이 아닙니다. 다음은 로깅되지 않는, 앱에서 수행할 수 있는 몇 가지 DNS 작업입니다.

  • DNS 네임서버와 직접 통신합니다.
  • 자바 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일 자정(UTC) 사이의 밀리초 간격입니다.
ID 26 단조 증가하는 숫자 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()를 호출하고 trueenabled 인수로 전달합니다. 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 조회 및 네트워크 연결의 데이터 필드에 대한 자세한 내용은 이벤트 로그를 참조하세요. 이벤트는 시간순이며 각 배치에는 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 디버그 브리지 (adb) 명령어를 실행합니다.

adb shell dpm force-network-logs

시스템은 도구 사용 빈도를 제한하고 터미널 출력의 의도적인 속도 저하를 보고합니다. 검색할 로그가 없으면 DPC가 콜백을 수신하지 않습니다.