區域網路權限

只要應用程式具備 INTERNET 權限,就能存取區域網路 (LAN) 上的裝置。這項功能可讓應用程式輕鬆連線至本機裝置,但也會造成隱私權問題,例如形成使用者指紋,以及成為位置資訊的 Proxy。

「區域網路保護」專案的目標是透過新的執行階段權限,限制區域網路的存取權,進而保護使用者隱私權。

影響

在 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 具有 INTERNET 權限的應用程式會獲得 ACCESS_LOCAL_NETWORK 的隱性授權,因此可以保留存取權。這項功能是暫時性措施,應用程式將目標 SDK 升級至 37 後,系統就會預設封鎖這項功能 目前不需要立即變更程式碼

依用途區分的攜碼策略

  • 投放:如要使用媒體投放功能,最合適且能保護隱私權的策略是使用輸出切換器。這個方法可讓系統代表使用者處理本機網路探索和連線作業,因此應用程式不需要要求 ACCESS_LOCAL_NETWORK 權限。

  • 瀏覽器:處理錯誤時,需要根據通訊協定採取不同做法。UDP 錯誤會導致 EPERM 錯誤代碼。如果是 TCP 連線,瀏覽器應使用 NDK API android_getnetworkblockedreason(int sockFd) 判斷封包是否遭 LNP 封鎖,這個 API 會傳回 ANDROID_NETWORK_BLOCKED_REASON_LNP

  • 其他用途 (例如 IoT):使用 mDNS 尋找裝置的應用程式應使用 android.net.nsd.DiscoveryRequest#FLAG_SHOW_PICKER,這樣就能在沒有權限的情況下尋找裝置,並使用 NsdManager#registerServiceInfoCallback / NsdManager#resolveService 取得 IP 位址。連線至以這種方式取得的 IP 位址時,不需要「ACCESS_LOCAL_NETWORK」權限。

如果應用程式需要直接進行本機網路通訊,且無法使用系統中介的挑選器,建議採用權限重設計數器策略。如果使用者撤銷 ACCESS_LOCAL_NETWORK 權限,這個機制會提供更多機會讓應用程式重新要求權限,開發人員可以向使用者清楚說明原因。

Android 16 指南

如要啟用區域網路限制,請按照下列步驟操作:

  1. 將裝置刷新至搭載 Android 16 Beta 3 以上版本的建構版本
  2. 安裝要測試的應用程式
  3. 使用 adb 切換 Appcompat 設定

    adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>
    
  4. 重新啟動裝置

現在應用程式的區域網路存取權受到限制,任何存取區域網路的嘗試都會導致通訊端錯誤。如果您使用的 API 會在應用程式程序外部執行區域網路作業 (例如 NsdManager),則這些 API 不會在選擇加入期間受到影響。

如要還原存取權,請授予應用程式 NEARBY_WIFI_DEVICES 權限。

  • 請確認應用程式在 manifest 中宣告了 NEARBY_WIFI_DEVICES 權限。
  • 依序前往「設定」 >「應用程式」 >「[應用程式名稱]」 >「權限」 >「鄰近裝置」 >「允許」

現在應用程式應該已恢復區域網路存取權,所有情境也應與應用程式加入測試前相同。應用程式網路流量受到的影響如下。

權限 傳出 LAN 要求 傳出/傳入網際網路要求 傳入 LAN 要求
已授權 Works Works Works
未授予 凸槌影片 Works 凸槌影片

使用下列指令切換關閉 Appcompat 設定

adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>

錯誤

如果因缺少權限而無法存取區域網路,請按照下列步驟操作:

  • TCP 連線通常會導致逾時錯誤

  • UDP 錯誤和一般權限遭拒通常會導致 EPERM 錯誤代碼

錯誤

回報錯誤並提供意見回饋:

  • 區域網路存取權有差異 (您認為特定存取權不應視為「區域網路」存取權)
  • 應封鎖但未封鎖 LAN 存取權的錯誤
  • LAN 存取權不應遭到封鎖,但卻遭到封鎖的錯誤

下列項目應不受這項異動影響:

  • 連上網際網路
  • 行動網路