แอปที่มี
INTERNET สิทธิ์จะเข้าถึงอุปกรณ์ในเครือข่าย LAN ได้
ซึ่งช่วยให้แอปเชื่อมต่อกับอุปกรณ์ในพื้นที่ได้ง่าย แต่ก็มีผลกระทบต่อความเป็นส่วนตัวด้วย เช่น การสร้างลายนิ้วมือของผู้ใช้และการเป็นพร็อกซีสำหรับตำแหน่ง
โปรเจ็กต์การป้องกันเครือข่าย LAN มีเป้าหมายเพื่อปกป้องความเป็นส่วนตัวของผู้ใช้โดย จำกัดการเข้าถึงเครือข่าย LAN ไว้เบื้องหลังสิทธิ์รันไทม์ใหม่
ผลกระทบ
ใน Android 16 สิทธิ์นี้จะเป็นฟีเจอร์แบบเลือกใช้ ซึ่งหมายความว่าจะมีเพียง แอปที่เลือกใช้เท่านั้นที่จะได้รับผลกระทบ เป้าหมายของการเลือกใช้คือเพื่อให้นักพัฒนาแอป เข้าใจว่าส่วนใดของแอปที่ต้องอาศัยการเข้าถึงเครือข่าย LAN แบบไม่เจาะจงปลายทาง เพื่อเตรียมพร้อมที่จะใช้การป้องกันสิทธิ์ใน Android รุ่นต่อๆ ไป
แอปจะได้รับผลกระทบหากเข้าถึงเครือข่ายท้องถิ่นของผู้ใช้โดยใช้สิ่งต่อไปนี้
- การใช้ซ็อกเก็ตดิบโดยตรงหรือในไลบรารีในที่อยู่เครือข่ายภายใน เช่น
Multicast DNS (mDNS)หรือSimple Service Discovery Protocol (SSDP) - การใช้คลาสระดับเฟรมเวิร์กที่เข้าถึงเครือข่ายภายใน เช่น
NsdManager
รายละเอียดผลกระทบ
การรับส่งข้อมูลไปยังและจากที่อยู่เครือข่ายภายในต้องมีสิทธิ์เข้าถึงเครือข่ายภายใน ตารางต่อไปนี้แสดงกรณีที่พบบ่อย
| การดำเนินการเครือข่ายระดับต่ำของแอป | ต้องมีสิทธิ์เข้าถึงเครือข่ายภายใน |
|---|---|
| สร้างการเชื่อมต่อ TCP ขาออก | ใช่ |
| การยอมรับการเชื่อมต่อ TCP ขาเข้า | ใช่ |
| การส่ง Unicast, Multicast, Broadcast แบบ UDP | ใช่ |
| รับการรับส่งข้อมูลแบบ UDP ยูนิแคสต์ มัลติแคสต์ บรอดแคสต์ | ใช่ |
ข้อจำกัดเหล่านี้ได้รับการติดตั้งใช้งานในส่วนลึกของสแต็กเครือข่าย จึงมีผลกับAPI เครือข่ายทั้งหมด ซึ่งรวมถึงซ็อกเก็ตที่สร้างในแพลตฟอร์ม
หรือโค้ดที่มีการจัดการ ไลบรารีเครือข่าย เช่น Cronet และ OkHttp และ API ใดๆ
ที่ใช้งานอยู่ด้านบน การพยายามแก้ไขบริการในเครือข่ายภายใน
ที่มีคำต่อท้าย .local ต้องใช้สิทธิ์เข้าถึงเครือข่ายภายใน
ข้อยกเว้นสำหรับกฎข้างต้น
- หากเซิร์ฟเวอร์ DNS ของอุปกรณ์อยู่ในเครือข่ายภายใน การรับส่งข้อมูลไปยัง / จากเซิร์ฟเวอร์ (ที่พอร์ต 53) ไม่จำเป็นต้องมีสิทธิ์เข้าถึงเครือข่ายภายใน
- แอปพลิเคชันที่ใช้ Output Switcher เป็นตัวเลือกในแอปจะไม่ต้องมีสิทธิ์เข้าถึงเครือข่ายในพื้นที่ (คำแนะนำเพิ่มเติมจะมาในการเปิดตัวในอนาคต)
การบังคับใช้ Android 17
ตั้งแต่ Android 17 เป็นต้นไป การปกป้องเครือข่ายในเครื่องจะเป็นข้อบังคับและจะมีการบังคับใช้กับ แอปที่กำหนดเป้าหมายเป็น Android 17 ขึ้นไป
| อัตราส่วน | Android 16 | Android 17 |
|---|---|---|
| SDK เป้าหมาย | 36 | 37 ขึ้นไป |
| สิทธิ์ | ใช้ NEARBY_WIFI_DEVICES ชั่วคราว | ACCESS_LOCAL_NETWORK |
| สิทธิ์เข้าถึงเริ่มต้น | การเข้าถึงเครือข่ายภายในเปิดอยู่ | ระบบจะบล็อกเครือข่าย LAN โดยค่าเริ่มต้นสำหรับแอปทั้งหมดที่อัปเดต 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
}
})
เส้นทาง B: ขอสิทธิ์รันไทม์ (การเข้าถึงแบบกว้าง)
เส้นทางนี้จำเป็นสำหรับกรณีการใช้งานที่ซับซ้อน เช่น ระบบอัตโนมัติในบ้านหรือการจัดการอุปกรณ์ IoT ที่ต้องมีการเข้าถึงเครือข่ายในพื้นที่อย่างกว้างขวางและต่อเนื่อง
ประกาศสิทธิ์ในไฟล์ Manifest: นักพัฒนาแอปต้องประกาศ
ACCESS_LOCAL_NETWORKอย่างชัดเจนในAndroidManifest.xmlขอสิทธิ์ขณะรันไทม์: ก่อนพยายามเข้าถึงเครือข่ายในพื้นที่ใดๆ แอปพลิเคชันต้องตรวจสอบว่าได้รับสิทธิ์หรือไม่ หากไม่เป็นเช่นนั้น ผู้ใช้ต้อง โทรหา
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 |
ไม่จำเป็นต้องเปลี่ยนแปลงโค้ดในทันที |
กลยุทธ์ 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ซึ่งอนุญาตให้ ค้นหาอุปกรณ์ได้โดยไม่ต้องมีสิทธิ์ และNsdManager#registerServiceInfoCallback/NsdManager#resolveServiceเพื่อรับ ที่อยู่ IP การเชื่อมต่อกับที่อยู่ IP ที่ได้รับด้วยวิธีนี้ไม่จำเป็นต้องมีสิทธิ์ACCESS_LOCAL_NETWORK
สำหรับแอปพลิเคชันที่ต้องมีการสื่อสารในเครือข่ายเฉพาะที่โดยตรงและใช้เครื่องมือเลือกที่ระบบเป็นสื่อกลางไม่ได้ แนวทางที่แนะนำคือการใช้กลยุทธ์ตัวนับการรีเซ็ตสิทธิ์ หากผู้ใช้เพิกถอนสิทธิ์ ACCESS_LOCAL_NETWORK กลไกนี้จะช่วยให้แอปมีโอกาสเพิ่มเติมในการขอสิทธิ์อีกครั้ง ซึ่งจะช่วยให้นักพัฒนาแอปแสดงเหตุผลที่ชัดเจนยิ่งขึ้นแก่ผู้ใช้ได้
คำแนะนำสำหรับ Android 16
หากต้องการเลือกใช้ข้อจำกัดเครือข่ายในเครื่อง ให้ทำดังนี้
- แฟลชอุปกรณ์เป็นบิลด์ที่มี Android 16 เบต้า 3 ขึ้นไป
- ติดตั้งแอปที่จะทดสอบ
สลับการกำหนดค่า Appcompat โดยใช้ adb
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>รีบูตอุปกรณ์
ตอนนี้การเข้าถึงเครือข่าย LAN ของแอปจะถูกจำกัด และความพยายามใดๆ ในการ
เข้าถึงเครือข่าย LAN จะทำให้เกิดข้อผิดพลาดของซ็อกเก็ต
หากคุณใช้ API ที่ดำเนินการในเครือข่ายภายในนอกกระบวนการของแอป (เช่น NsdManager) API เหล่านั้นจะไม่ได้รับผลกระทบในระหว่างการเลือกใช้
หากต้องการคืนค่าสิทธิ์เข้าถึง คุณต้องให้สิทธิ์แอปในการเข้าถึง NEARBY_WIFI_DEVICES
- ตรวจสอบว่าแอปประกาศสิทธิ์
NEARBY_WIFI_DEVICESในmanifest - ไปที่การตั้งค่า > แอป > [ชื่อแอป] > สิทธิ์ > อุปกรณ์ที่อยู่ใกล้เคียง > อนุญาต
ตอนนี้สิทธิ์เข้าถึงเครือข่าย LAN ของแอปควรได้รับการกู้คืนแล้ว และสถานการณ์ทั้งหมดควรทํางานได้เหมือนก่อนที่จะเลือกใช้แอป ผลกระทบต่อการรับส่งข้อมูลเครือข่ายของแอปมีดังนี้
| สิทธิ์ | คำขอ LAN ขาออก | คำขออินเทอร์เน็ตขาออก/ขาเข้า | คำขอ LAN ขาเข้า |
|---|---|---|---|
| ให้สิทธิ์ | Works | Works | Works |
| ไม่ให้สิทธิ์ | เรื่องหน้าแตก | Works | เรื่องหน้าแตก |
ใช้คำสั่งต่อไปนี้เพื่อเปิด/ปิดการกำหนดค่า Appcompat
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
ข้อผิดพลาด
หากคำขอเข้าถึงเครือข่าย LAN ไม่สำเร็จเนื่องจากไม่มีสิทธิ์ ให้ทำดังนี้
โดยปกติแล้ว การเชื่อมต่อ TCP จะทำให้เกิดข้อผิดพลาดหมดเวลา
โดยปกติแล้ว ข้อผิดพลาด UDP และการปฏิเสธสิทธิ์ทั่วไปจะส่งผลให้เกิดรหัสข้อผิดพลาด EPERM
ข้อบกพร่อง
ส่งข้อบกพร่องและความคิดเห็นสำหรับ
- ความคลาดเคลื่อนในการเข้าถึง LAN (คุณไม่คิดว่าการเข้าถึงบางอย่างควรได้รับการพิจารณาเป็นการเข้าถึง "เครือข่ายในพื้นที่")
- ข้อบกพร่องที่ควรบล็อกการเข้าถึง LAN แต่ไม่ได้บล็อก
- ข้อบกพร่องที่ควรอนุญาตให้เข้าถึง LAN แต่กลับถูกบล็อก
รายการต่อไปนี้จะไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนี้
- การเข้าถึงอินเทอร์เน็ต
- เครือข่ายมือถือ