แอปใดก็ตามที่มีสิทธิ์ INTERNET จะเข้าถึงอุปกรณ์ในเครือข่าย LAN ได้
ซึ่งช่วยให้แอปเชื่อมต่อกับอุปกรณ์ในเครือข่ายภายในได้ง่าย แต่ก็มีผลกระทบต่อความเป็นส่วนตัวด้วย เช่น การสร้างลายนิ้วมือของผู้ใช้และการทำหน้าที่เป็นพร็อกซีสำหรับตำแหน่ง
โปรเจ็กต์การป้องกันเครือข่ายภายในมีเป้าหมายเพื่อปกป้องความเป็นส่วนตัวของผู้ใช้โดยการจำกัดการเข้าถึงเครือข่ายภายในด้วยสิทธิ์รันไทม์ใหม่
ผลกระทบ
ใน Android 16 สิทธิ์นี้เป็นฟีเจอร์ที่เลือกใช้ได้ ซึ่งหมายความว่าจะมีเฉพาะแอปที่เลือกใช้เท่านั้นที่จะได้รับผลกระทบ เป้าหมายของการเลือกใช้คือให้นักพัฒนาแอปเข้าใจว่าส่วนใดของแอปที่ต้องใช้การเข้าถึงเครือข่ายภายในโดยนัย เพื่อให้เตรียมพร้อมที่จะป้องกันสิทธิ์ใน Android เวอร์ชันต่อๆ ไปได้
แอปจะได้รับผลกระทบหากเข้าถึงเครือข่ายภายในของผู้ใช้โดยใช้สิ่งต่อไปนี้
- การใช้ซ็อกเก็ตดิบโดยตรงหรือผ่านไลบรารีในที่อยู่เครือข่ายภายใน เช่น
Multicast DNS (mDNS)หรือSimple Service Discovery Protocol (SSDP) - การใช้คลาสระดับเฟรมเวิร์กที่เข้าถึงเครือข่ายภายใน เช่น
NsdManager
รายละเอียดของผลกระทบ
การรับส่งข้อมูลไปยังและจากที่อยู่เครือข่ายภายในต้องใช้สิทธิ์เข้าถึงเครือข่ายภายใน ตารางต่อไปนี้แสดงกรณีที่พบบ่อยบางกรณี
| App Low Level Network Operation | Local Network Permission Required |
|---|---|
| Making an outgoing TCP connection | ใช่ |
| Accepting an incoming TCP connection | ใช่ |
| Sending a UDP unicast, multicast, broadcast | ใช่ |
| Receiving a incoming UDP unicast, multicast, broadcast | ใช่ |
ข้อจำกัดเหล่านี้ได้รับการติดตั้งใช้งานในส่วนลึกของสแต็กเครือข่าย จึงมีผลกับ API เครือข่ายทั้งหมด ซึ่งรวมถึงซ็อกเก็ตที่สร้างขึ้นในแพลตฟอร์มหรือโค้ดที่มีการจัดการ ไลบรารีเครือข่าย เช่น Cronet และ OkHttp รวมถึง API ใดก็ตามที่ติดตั้งใช้งานบนไลบรารีเหล่านั้น การพยายามแก้ไขบริการในเครือข่ายภายในที่มีคำต่อท้าย .local ต้องใช้สิทธิ์เข้าถึงเครือข่ายภายใน
ข้อยกเว้นของกฎข้างต้น
- หากเซิร์ฟเวอร์ DNS ของอุปกรณ์อยู่ในเครือข่ายภายใน การรับส่งข้อมูลไปยัง / จากเซิร์ฟเวอร์ (ที่พอร์ต 53) ไม่ต้องใช้สิทธิ์เข้าถึงเครือข่ายภายใน
- แอปพลิเคชันที่ใช้ Output Switcher เป็นเครื่องมือเลือกในแอปจะไม่ต้องใช้สิทธิ์เข้าถึงเครือข่ายภายใน (คำแนะนำเพิ่มเติมจะมาในรุ่นต่อๆ ไป)
การบังคับใช้ใน Android 17
ตั้งแต่ Android 17 เป็นต้นไป การป้องกันเครือข่ายภายในเป็นสิ่งที่จำเป็นและมีการบังคับใช้กับแอปที่กำหนดเป้าหมายเป็น Android 17 ขึ้นไป
| Aspect | Android 16 | Android 17 |
|---|---|---|
| Target SDK | 36 | 37 ขึ้นไป |
| Permission | NEARBY_WIFI_DEVICES ที่ใช้ชั่วคราว | ACCESS_LOCAL_NETWORK |
| Default Access | การเข้าถึงเครือข่ายภายในเปิดอยู่ | ระบบจะบล็อกเครือข่ายภายในโดยค่าเริ่มต้นสำหรับแอปทั้งหมดที่อัปเดต SDK เป้าหมาย |
| Permission Group | เป็นส่วนหนึ่งของกลุ่มสิทธิ์ NEARBY_DEVICES ที่มีอยู่ | |
หากต้องการยืนยันว่าฟังก์ชันการทำงานของแอปไม่เสียหายหลังจากการบังคับใช้ แอปพลิเคชันที่กำหนดเป้าหมายเป็น SDK 37 ขึ้นไปต้องใช้เส้นทางใดเส้นทางหนึ่งต่อไปนี้เพื่อจัดการการเข้าถึงเครือข่ายภายใน
เส้นทาง ก: การใช้เครื่องมือเลือกที่เน้นความเป็นส่วนตัว
สำหรับงานการค้นพบและการเชื่อมต่อที่ระบบเป็นสื่อกลาง ให้ใช้เครื่องมือเลือกเพื่อหลีกเลี่ยงการขอสิทธิ์รันไทม์แบบกว้างทั้งหมด ใช้เครื่องมือเลือกต่อไปนี้ตามกรณีการใช้งาน
- การสตรีมสื่อ: สำหรับแอปพลิเคชันที่รองรับ Google Cast จะใช้
ฟีเจอร์ Output Switcher ได้ ซึ่งช่วยให้นักพัฒนาแอปอนุญาตให้ผู้ใช้เลือกอุปกรณ์การสตรีมที่เฉพาะเจาะจงได้โดยไม่ต้องให้แอปขอสิทธิ์แบบกว้าง
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 ที่ต้องมีการเข้าถึงเครือข่ายภายในแบบกว้างและต่อเนื่อง
ประกาศสิทธิ์ในไฟล์ Manifest: ประกาศ
ACCESS_LOCAL_NETWORKอย่างชัดเจนในAndroidManifest.xmlขอสิทธิ์ขณะรันไทม์: ก่อนที่จะพยายามเข้าถึงเครือข่ายภายใน แอปพลิเคชันต้องตรวจสอบว่าได้รับสิทธิ์แล้วหรือไม่ หากไม่ได้รับสิทธิ์ แอปพลิเคชันต้องเรียกใช้
Activity.requestPermission()เพื่อทริกเกอร์ข้อความแจ้งมาตรฐานของระบบสถานการณ์ที่ได้รับสิทธิ์ล่วงหน้า: สิทธิ์
ACCESS_LOCAL_NETWORKเป็นส่วนหนึ่ง ของกลุ่มสิทธิ์NEARBY_DEVICESหากผู้ใช้ให้สิทธิ์อื่นในกลุ่มนี้แล้ว (เช่น สิทธิ์ Bluetooth) ระบบจะไม่แจ้งให้ขอสิทธิ์เข้าถึงเครือข่ายภายในอีกการจัดการการปฏิเสธและการเพิกถอน: แอปต้องจัดการอย่างเหมาะสมในกรณีที่ผู้ใช้ปฏิเสธคำขอหรือเพิกถอนสิทธิ์ในภายหลังในการตั้งค่าระบบ ในสถานการณ์ดังกล่าว ระบบจะบล็อกการรับส่งข้อมูลเครือข่ายภายใน
กลยุทธ์ตัวนับรีเซ็ตคำขอสิทธิ์
แพลตฟอร์มใช้กลยุทธ์การรีเซ็ตตัวนับที่จัดการสถานการณ์ที่
การปฏิเสธกลุ่มสิทธิ์ NEARBY_DEVICES ก่อนหน้านี้ของแอป
(ซึ่งตอนนี้รวมถึง ACCESS_LOCAL_NETWORK) ทำให้แอปขอ
สิทธิ์ไม่ได้หลังจากแสดงเหตุผลอย่างเพียงพอแล้ว กลไกนี้
ให้โอกาสเพิ่มเติมแก่แอปในการเรียกใช้ API requestPermission()
ซึ่งจะรีเซ็ตจำนวนการปฏิเสธสิทธิ์ ACCESS_LOCAL_NETWORK
ซึ่งช่วยให้มีการกลับมามีส่วนร่วมกับผู้ใช้ในลักษณะที่ละเอียดมากขึ้น โดยเฉพาะอย่างยิ่งเมื่อการปฏิเสธครั้งแรกเกิดขึ้นก่อนที่แอปจะสื่อสารความจำเป็นในการเข้าถึงเครือข่ายภายในสำหรับฟังก์ชันหลักของแอปได้
โมเดลสิทธิ์แบบแยก
สิทธิ์เข้าถึงเครือข่ายภายในใช้กลยุทธ์การย้ายข้อมูลสิทธิ์แบบแยกเพื่อจัดการแอปพลิเคชันใหม่และแอปพลิเคชันเดิมแตกต่างกันไปตาม SDK เป้าหมาย
| Category | Target SDK level | Local network access behavior | Required developer action |
|---|---|---|---|
| New Apps / Updated Apps | >= 37 (Android 17) | Blocked By Default | Declare and request ACCESS_LOCAL_NETWORK runtime permission |
| Legacy Apps | < 37 | Apps with INTERNET permission receive an implicit permission grant for ACCESS_LOCAL_NETWORK, allowing them to retain access. This is temporary and will be blocked by default once app bumps target SDK to 37 |
No immediate code change needed. Don't request ACCESS_LOCAL_NETWORK at runtime prior to targeting SDK 37. |
กลยุทธ์ LNP ตามกรณีการใช้งาน
การแคสต์: สำหรับฟังก์ชันการทำงานของการแคสต์สื่อ กลยุทธ์ที่เหมาะสมที่สุดและ เน้นความเป็นส่วนตัวคือการใช้ Output Switcher วิธีนี้ ช่วยให้ระบบจัดการการค้นพบและการเชื่อมต่อเครือข่ายภายในในนามของผู้ใช้ ได้ จึงไม่จำเป็นต้องให้แอปขอสิทธิ์
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ซึ่งอนุญาตให้ค้นหาอุปกรณ์ได้โดยไม่ต้องมีสิทธิ์ และNsdManager#registerServiceInfoCallback/NsdManager#resolveServiceเพื่อรับที่อยู่ IP การเชื่อมต่อกับที่อยู่ IP ที่ได้รับด้วยวิธีนี้ไม่จำเป็นต้องมีสิทธิ์ACCESS_LOCAL_NETWORK
สำหรับแอปพลิเคชันที่ต้องมีการสื่อสารเครือข่ายภายในโดยตรงและไม่สามารถใช้เครื่องมือเลือกที่ระบบเป็นสื่อกลางได้ วิธีที่แนะนำคือใช้กลยุทธ์ตัวนับรีเซ็ตสิทธิ์เมื่อกำหนดเป้าหมายเป็น Android 17 (SDK 37) ขึ้นไป หากผู้ใช้เพิกถอนสิทธิ์
ACCESS_LOCAL_NETWORK กลไกนี้
จะให้โอกาสเพิ่มเติมแก่แอปในการขอสิทธิ์อีกครั้ง
ซึ่งช่วยให้นักพัฒนาแอปแสดงเหตุผลที่ชัดเจนยิ่งขึ้นแก่ผู้ใช้ได้
คำแนะนำสำหรับ Android 16
หากต้องการเลือกใช้ข้อจำกัดเครือข่ายภายใน ให้ทำดังนี้
- แฟลชอุปกรณ์เป็นบิลด์ที่มี Android 16 Beta 3 ขึ้นไป
- ติดตั้งแอปที่จะทดสอบ
สลับการกำหนดค่า Appcompat โดยใช้ adb
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>รีบูตอุปกรณ์
ตอนนี้การเข้าถึงเครือข่ายภายในของแอปถูกจำกัดแล้ว และการพยายามเข้าถึงเครือข่ายภายในจะทำให้เกิดข้อผิดพลาดของซ็อกเก็ต
หากคุณใช้ API ที่ดำเนินการเครือข่ายภายในนอกกระบวนการของแอป (เช่น NsdManager) API เหล่านี้จะไม่ได้รับผลกระทบระหว่างการเลือกใช้
หากต้องการคืนสิทธิ์เข้าถึง คุณต้องให้สิทธิ์ NEARBY_WIFI_DEVICES แก่แอป
- ตรวจสอบว่าแอปประกาศสิทธิ์
NEARBY_WIFI_DEVICESในmanifest - ไปที่การตั้งค่า > แอป > [ชื่อแอป] > สิทธิ์ > อุปกรณ์ใกล้เคียง > อนุญาต
ตอนนี้การเข้าถึงเครือข่ายภายในของแอปควรได้รับการคืนค่าแล้ว และสถานการณ์ทั้งหมดควรทำงานได้เหมือนก่อนที่จะเลือกใช้แอป ต่อไปนี้คือผลกระทบต่อการรับส่งข้อมูลเครือข่ายของแอป
| Permission | Outbound LAN Request | Outbound/Inbound Internet Request | Inbound LAN Request |
|---|---|---|---|
| Granted | Works | Works | Works |
| Not Granted | Fails | Works | Fails |
ใช้คำสั่งต่อไปนี้เพื่อปิดการกำหนดค่า Appcompat
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
ข้อผิดพลาด
หากคำขอเข้าถึงเครือข่ายภายในไม่สำเร็จเนื่องจากไม่มีสิทธิ์ ให้ทำดังนี้
การเชื่อมต่อ TCP มักจะส่งผลให้เกิดข้อผิดพลาดการหมดเวลา
ข้อผิดพลาด UDP และการปฏิเสธสิทธิ์ทั่วไปมักจะส่งผลให้เกิดรหัสข้อผิดพลาด EPERM
ข้อบกพร่อง
ส่งข้อบกพร่องและความคิดเห็นสำหรับกรณีต่อไปนี้
- ความคลาดเคลื่อนในการเข้าถึง LAN (คุณคิดว่าการเข้าถึงบางอย่างไม่ควรพิจารณาเป็นการเข้าถึง "เครือข่ายภายใน")
- ข้อบกพร่องที่ควรบล็อกการเข้าถึง LAN แต่ไม่บล็อก
- ข้อบกพร่องที่ควรไม่บล็อกการเข้าถึง LAN แต่บล็อก
สิ่งต่อไปนี้ไม่ควรได้รับผลกระทบจากการเปลี่ยนแปลงนี้
- การเข้าถึงอินเทอร์เน็ต
- เครือข่ายมือถือ