LAN (Local Area Network)에 있는 기기는 INTERNET 권한이 있는 모든 앱에서 액세스할 수 있습니다.
이렇게 하면 앱이 로컬 기기에 쉽게 연결할 수 있지만 사용자의 지문을 형성하고 위치의 프록시가 되는 등 개인 정보 보호 관련 영향도 있습니다.
로컬 네트워크 보호 프로젝트는 새로운 런타임 권한 뒤에 로컬 네트워크 액세스를 제한하여 사용자의 개인 정보를 보호하는 것을 목표로 합니다.
영향
Android 16에서는 이 권한이 선택 기능이므로 선택한 앱만 영향을 받습니다. 선택의 목표는 앱 개발자가 앱의 어떤 부분이 암시적 로컬 네트워크 액세스에 의존하는지 파악하여 향후 Android 출시에서 권한으로 보호할 수 있도록 하는 것입니다.
다음 방법을 사용하여 사용자의 로컬 네트워크에 액세스하는 앱은 영향을 받습니다.
- 로컬 네트워크 주소(예:
Multicast DNS (mDNS)또는Simple Service Discovery Protocol (SSDP))에서 원시 소켓을 직접 또는 라이브러리 사용 - 로컬 네트워크에 액세스하는 프레임워크 수준 클래스 사용(예:
NsdManager)
영향 세부정보
로컬 네트워크 주소로 오가는 트래픽에는 로컬 네트워크 액세스 권한이 필요합니다. 다음 표에는 몇 가지 일반적인 사례가 나와 있습니다.
| 앱 하위 수준 네트워크 작업 | 로컬 네트워크 권한 필요 |
|---|---|
| 아웃바운드 TCP 연결 만들기 | 예 |
| 수신 TCP 연결 수락 | 예 |
| UDP 유니캐스트, 멀티캐스트, 브로드캐스트 전송 | 예 |
| 수신 UDP 유니캐스트, 멀티캐스트, 브로드캐스트 수신 | 예 |
이러한 제한사항은 네트워킹 스택 깊숙이 구현되므로 모든 네트워킹 API에 적용됩니다. 여기에는 플랫폼이나 관리 코드에서 생성된 소켓, Cronet 및 OkHttp와 같은 네트워킹 라이브러리, 이러한 라이브러리 위에 구현된 API가 포함됩니다. .local 접미사가 있는 로컬 네트워크의 서비스를 확인하려면 로컬 네트워크 권한이 필요합니다.
위 규칙의 예외:
- 기기의 DNS 서버가 로컬 네트워크에 있는 경우 포트 53에서 오가는 트래픽에는 로컬 네트워크 액세스 권한이 필요하지 않습니다.
- 출력 전환기를 인앱 선택기로 사용하는 애플리케이션에는 로컬 네트워크 권한이 필요하지 않습니다 (자세한 안내는 추후 제공 예정).
Android 17 시행
Android 17부터 로컬 네트워크 보호는 Android 17 이상을 타겟팅하는 앱에 필수이며 적용됩니다.
| 특성 | Android 16 | Android 17 |
|---|---|---|
| 타겟 SDK | 36 | 37 이상 |
| 권한 | 일시적으로 NEARBY_WIFI_DEVICES 사용 | ACCESS_LOCAL_NETWORK |
| 기본 액세스 | 로컬 네트워크 액세스가 열려 있음 | 타겟 SDK를 업데이트하는 모든 앱의 로컬 네트워크가 기본적으로 차단됨 |
| 권한 그룹 | 기존 NEARBY_DEVICES 권한 그룹의 일부 | |
강제 시행 후 앱 기능이 중단되지 않도록 하려면 SDK 37 이상을 타겟팅하는 애플리케이션이 다음 경로 중 하나를 채택하여 로컬 네트워크 액세스를 관리해야 합니다.
경로 A: 개인 정보를 보호하는 선택기 사용
시스템 중재 검색 및 연결 작업의 경우 선택기를 사용하여 광범위한 런타임 권한을 완전히 요청하지 마세요. 사용 사례에 따라 다음 선택기를 사용하세요.
- 미디어 스트리밍: Google Cast를 지원하는 애플리케이션의 경우 출력 전환기 기능을 사용할 수 있습니다. 이를 통해 개발자는 앱에서 광범위한
ACCESS_LOCAL_NETWORK권한을 요청하지 않아도 사용자가 특정 스트리밍 기기를 선택할 수 있도록 허용할 수 있습니다. - 일반 연결:
NsdManager에는 mDNS 검색을 위한 시스템 실행 서비스 선택기가 포함됩니다. 앱이 전체 네트워크를 검색하는 대신 시스템에서 사용자가 앱이 액세스할 단일 기기를 선택할 수 있는 대화상자를 표시합니다.
val discoveryRequest = DiscoveryRequest.Builder("_http._tcp")
.setFlags(DiscoveryRequest.FLAG_SHOW_PICKER)
.build()
nsdManager.registerServiceInfoCallback(discoveryRequest, executor, object : NsdManager.ServiceInfoCallback {
override fun onServiceUpdated(serviceInfo: NsdServiceInfo) {
// Handle the user-selected and discovered service
// NsdServiceInfo.getHostAddresses() can now be connected to
// without ACCESS_LOCAL_NETWORK permission
}
})
경로 B: 런타임 권한 요청 (광범위한 액세스)
이 경로는 로컬 네트워크에 대한 광범위하고 지속적인 액세스가 필요한 홈 자동화나 IoT 기기 관리와 같은 복잡한 사용 사례에 필요합니다.
매니페스트에서 권한 선언:
AndroidManifest.xml에서ACCESS_LOCAL_NETWORK를 명시적으로 선언합니다.런타임에 권한 요청: 애플리케이션은 로컬 네트워크 액세스를 시도하기 전에 권한이 부여되었는지 확인해야 합니다. 그렇지 않은 경우
Activity.requestPermission()를 호출하여 표준 시스템 프롬프트를 트리거해야 합니다.미리 부여된 시나리오:
ACCESS_LOCAL_NETWORK권한은NEARBY_DEVICES권한 그룹에 속합니다. 사용자가 이 그룹에서 이미 다른 권한 (예: 블루투스 권한)을 부여한 경우 로컬 네트워크 액세스 권한을 다시 묻지 않습니다.거부 및 취소 처리: 사용자가 요청을 거부하거나 나중에 시스템 설정에서 권한을 취소하는 경우 앱에서 적절히 처리해야 합니다. 이러한 시나리오에서는 로컬 네트워크 트래픽이 차단됩니다.
권한 요청 재설정 카운터 전략
플랫폼은 앱의 이전 NEARBY_DEVICES 권한 그룹(이제 ACCESS_LOCAL_NETWORK 포함) 거부로 인해 앱이 충분한 근거를 제시한 후 권한을 요청할 수 없는 시나리오를 해결하는 카운터 재설정 전략을 구현합니다. 이 메커니즘은 앱이 requestPermission() API를 호출할 수 있는 추가 기회를 제공하여 ACCESS_LOCAL_NETWORK 권한의 거부 횟수를 효과적으로 재설정합니다. 이를 통해 특히 앱이 핵심 기능에 로컬 네트워크 액세스가 필요하다는 점을 전달하기 전에 초기 거부가 발생한 경우 사용자와 더 미묘하게 재참여할 수 있습니다.
분할 권한 모델
로컬 네트워크 권한은 분할 권한 이전 전략을 활용하여 타겟 SDK에 따라 신규 애플리케이션과 기존 애플리케이션을 다르게 처리합니다.
| 카테고리 | 타겟 SDK 수준 | 로컬 네트워크 액세스 동작 | 필요한 개발자 작업 |
|---|---|---|---|
| 신규 앱 / 업데이트된 앱 | >= 37 (Android 17) | 기본적으로 차단됨 | ACCESS_LOCAL_NETWORK 런타임 권한 선언 및 요청 |
| 기존 앱 | < 37 | 인터넷 권한이 있는 앱은 ACCESS_LOCAL_NETWORK에 대한 암시적 권한 부여를 받아 액세스 권한을 유지할 수 있습니다. 이는 임시이며 앱이 타겟 SDK를 37로 올리면 기본적으로 차단됩니다. |
즉각적인 코드 변경이 필요하지 않음 |
사용 사례별 LNP 전략
전송: 미디어 전송 기능의 경우 가장 적절하고 개인 정보 보호를 준수하는 전략은 출력 전환기를 사용하는 것입니다. 이 메서드를 사용하면 시스템에서 사용자를 대신하여 로컬 네트워크 검색 및 연결을 처리할 수 있으므로 앱에서
ACCESS_LOCAL_NETWORK권한을 요청할 필요가 없습니다.브라우저: 오류 처리는 프로토콜에 따라 다른 접근 방식이 필요합니다. UDP 오류로 인해
EPERM오류 코드가 발생합니다. TCP 연결의 경우 브라우저는 NDK APIandroid_getnetworkblockedreason(int sockFd)를 사용하여 패킷이 LNP에 의해 차단되었는지 확인해야 합니다. 이 API는ANDROID_NETWORK_BLOCKED_REASON_LNP를 반환합니다.기타 사용 사례 (예: IoT): mDNS를 사용하여 기기를 찾는 애플리케이션은 권한 없이 기기를 찾을 수 있는
android.net.nsd.DiscoveryRequest#FLAG_SHOW_PICKER와 IP 주소를 가져오는NsdManager#registerServiceInfoCallback/NsdManager#resolveService를 사용해야 합니다. 이 방식으로 획득한 IP 주소에 대한 연결에는ACCESS_LOCAL_NETWORK권한이 필요하지 않습니다.
직접 로컬 네트워크 통신이 필요하고 시스템 중재 선택기를 사용할 수 없는 애플리케이션의 경우 권한 재설정 카운터 전략을 사용하는 것이 좋습니다. ACCESS_LOCAL_NETWORK 권한이 사용자에 의해 취소되면 이 메커니즘은 앱이 권한을 다시 요청할 수 있는 추가 기회를 제공하여 개발자가 사용자에게 더 명확한 근거를 제시할 수 있도록 합니다.
Android 16 안내
로컬 네트워크 제한을 선택하려면 다음 단계를 따르세요.
- Android 16 베타 3 이상이 적용된 빌드로 기기 플래시
- 테스트할 앱 설치
adb를 사용하여 Appcompat 구성 전환
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>기기 재부팅하기
이제 앱의 로컬 네트워크 액세스가 제한되며 로컬 네트워크에 액세스하려고 하면 소켓 오류가 발생합니다.
앱 프로세스 외부에서 로컬 네트워크 작업을 실행하는 API (예: NsdManager)를 사용하는 경우 선택 기간 동안 영향을 받지 않습니다.
액세스 권한을 복원하려면 앱에 NEARBY_WIFI_DEVICES 권한을 부여해야 합니다.
- 앱이
manifest에서NEARBY_WIFI_DEVICES권한을 선언하는지 확인합니다. - 설정 > 앱 > [앱 이름] > 권한 > 주변 기기 > 허용으로 이동합니다.
이제 앱의 로컬 네트워크 액세스가 복원되고 모든 시나리오가 앱 선택 전과 같이 작동합니다. 앱 네트워크 트래픽이 영향을 받는 방식은 다음과 같습니다.
| 권한 | 아웃바운드 LAN 요청 | 아웃바운드/인바운드 인터넷 요청 | 인바운드 LAN 요청 |
|---|---|---|---|
| 승인됨 | 작동의 원리 | 작동의 원리 | 작동의 원리 |
| 허용되지 않음 | 실패 경험 | 작동의 원리 | 실패 경험 |
다음 명령어를 사용하여 Appcompat 구성을 전환하여 사용 중지합니다.
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
오류
권한 누락으로 인해 로컬 네트워크 액세스 요청이 실패하는 경우:
TCP 연결은 일반적으로 시간 초과 오류를 발생시킵니다.
UDP 오류 및 일반적인 권한 거부는 일반적으로 EPERM 오류 코드를 발생시킵니다.
버그
다음에 대한 버그 제출 및 의견:
- LAN 액세스 불일치 (특정 액세스가 '로컬 네트워크' 액세스로 간주되어서는 안 된다고 생각함)
- LAN 액세스가 차단되어야 하지만 차단되지 않는 버그
- LAN 액세스가 차단되지 않아야 하는데 차단되는 버그
다음은 이번 변경사항의 영향을 받지 않습니다.
- 인터넷 액세스
- 모바일 네트워크