Доступ к устройствам в локальной вычислительной сети (LAN) может получить любое приложение, у которого есть разрешение INTERNET.
С одной стороны, это упрощает подключение приложений к локальным устройствам, но с другой – влияет на конфиденциальность, например позволяет создавать цифровой отпечаток пользователя и определять его местоположение.
Проект "Защита локальной сети" направлен на защиту конфиденциальности пользователей. Для этого мы ограничиваем доступ к локальной сети с помощью нового динамического разрешения.
Влияние
Начиная с Android 17 (уровень API 37), защита локальной сети применяется к приложениям, предназначенным для Android 17 или более поздней версии. Прежняя конфигурация Android 16 больше не поддерживается. Ознакомьтесь с требованиями к реализации для Android 17.
Изменения затронут приложения, которые получают доступ к локальной сети пользователя с помощью:
- Прямое или библиотечное использование необработанных сокетов на адресах локальной сети, например
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 или более поздней версии, должны использовать один из следующих способов управления доступом к локальной сети:
Путь А. Использование инструментов выбора, обеспечивающих конфиденциальность
Для обнаружения и подключения, выполняемых системой, используйте средства выбора, чтобы не запрашивать динамическое разрешение. Используйте следующие средства выбора в зависимости от вашего случая использования:
- Потоковая передача медиаконтента. В приложениях с поддержкой 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
}
})
Вариант Б. Запрос динамического разрешения (широкий доступ)
Этот путь необходим для сложных сценариев использования, таких как автоматизация дома или управление устройствами IoT, для которых требуется широкий и постоянный доступ к локальной сети.
Объявите разрешение в манифесте. Явно объявите
ACCESS_LOCAL_NETWORKв файлеAndroidManifest.xml.Запрашивайте разрешение во время выполнения. Прежде чем пытаться получить доступ к локальной сети, приложения должны проверить, предоставлено ли разрешение. В противном случае необходимо вызвать
Activity.requestPermission(), чтобы запустить стандартную системную подсказку.Разрешение предоставлено заранее. Разрешение
ACCESS_LOCAL_NETWORKвходит в группу разрешенийNEARBY_DEVICES. Если пользователь уже предоставил другое разрешение в этой группе (например, разрешение на использование Bluetooth), он не будет повторно запрашивать доступ к локальной сети.Обработка отказа и отзыва. Приложения должны корректно обрабатывать случаи, когда пользователь отклоняет запрос или позже отзывает разрешение в системных настройках. В таких случаях трафик локальной сети будет заблокирован.
Стратегия сброса счетчика запросов разрешений
На платформе реализована стратегия сброса счетчика, которая решает проблему, когда предыдущий отказ приложения в группе разрешений NEARBY_DEVICES (которая теперь включает ACCESS_LOCAL_NETWORK) не позволял приложению запрашивать разрешение после адекватного обоснования. Этот механизм предоставляет приложению дополнительные возможности для вызова API requestPermission(), фактически сбрасывая счетчик отказов для разрешения ACCESS_LOCAL_NETWORK. Это позволяет более деликатно повторно взаимодействовать с пользователем, особенно если первоначальный отказ произошел до того, как приложение смогло сообщить о необходимости доступа к локальной сети для его основных функций.
Раздельная модель разрешений
Для разрешения на доступ к локальной сети используется стратегия разделения разрешений, чтобы по-разному обрабатывать новые и устаревшие приложения в зависимости от целевого SDK.
| Категория | Целевой уровень SDK | Режим работы доступа к локальной сети | Что нужно сделать разработчику |
|---|---|---|---|
| Новые и обновленные приложения | >= 37 (Android 17) | Заблокировано по умолчанию | Объявите и запросите динамическое разрешение ACCESS_LOCAL_NETWORK |
| Устаревшие приложения | < 37 | Приложения с разрешением INTERNET получают неявное разрешение ACCESS_LOCAL_NETWORK, которое позволяет им сохранять доступ. Это временная мера. Когда целевой SDK приложения будет обновлен до версии 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.Другие сценарии использования (например, интернет вещей). Приложения, которые находят устройства с помощью mDNS, должны использовать
android.net.nsd.DiscoveryRequest#FLAG_SHOW_PICKER, чтобы находить устройства без разрешения, иNsdManager#registerServiceInfoCallback/NsdManager#resolveService, чтобы получать IP-адреса. Для подключения к IP-адресам, полученным таким образом, разрешениеACCESS_LOCAL_NETWORKне требуется.
Если приложению требуется прямая связь по локальной сети и оно не может использовать системные инструменты выбора, рекомендуем использовать стратегию сброса счетчика разрешений для Android 17 (SDK 37) или более поздней версии. Если пользователь отзовет разрешение ACCESS_LOCAL_NETWORK, этот механизм позволит приложению запросить его повторно, а разработчикам – объяснить пользователю, зачем оно нужно.
Руководство по Android 16 (устарело)
Чтобы включить ограничения локальной сети в Android 16, выполните следующие действия:
- Прошейте устройство сборкой с Android 16 Beta 3 или более поздней версией
- Установите приложение, которое нужно протестировать.
Как переключить конфигурацию Appcompat с помощью adb
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>Перезагрузить устройство
Теперь доступ приложения к локальной сети ограничен, и любая попытка получить его приводит к ошибкам сокета.
Если вы используете API, которые выполняют операции в локальной сети вне процесса приложения (например, NsdManager), то они не будут затронуты во время согласия.
Чтобы восстановить доступ, предоставьте приложению разрешение на NEARBY_WIFI_DEVICES.
- Убедитесь, что в файле
manifestприложения объявлено разрешениеNEARBY_WIFI_DEVICES. - Выберите Настройки > Приложения > [Название приложения] > Разрешения > Устройства поблизости > Разрешить.
Теперь доступ приложения к локальной сети должен быть восстановлен, а все сценарии должны работать так же, как и до включения приложения. Вот как это влияет на сетевой трафик приложения.
| Разрешение | Исходящий запрос LAN | Исходящий/входящий интернет-запрос | Входящий запрос в локальной сети |
|---|---|---|---|
| Разрешения даны | YouTube | YouTube | YouTube |
| Доступ не предоставлен | Глупые и смешные | YouTube | Глупые и смешные |
Чтобы отключить конфигурацию Appcompat, используйте следующую команду:
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
Ошибки
Если запрос на доступ к локальной сети не выполняется из-за отсутствия разрешения:
При подключении по протоколу TCP обычно возникает ошибка, связанная с истечением времени ожидания.
Ошибки UDP и общий отказ в разрешениях обычно приводят к коду ошибки EPERM.
Ошибки
Сообщайте об ошибках и оставляйте отзывы о следующих продуктах:
- Расхождения в доступе к локальной сети (вы считаете, что определенный доступ не должен считаться доступом к локальной сети).
- Ошибки, из-за которых доступ к локальной сети не блокируется, хотя должен.
- Ошибки, из-за которых доступ к LAN блокируется, когда этого не должно происходить.
Изменение не затронет:
- доступ к интернету;
- Мобильная сеть