การตรวจสอบการเข้าชมของ eBPF

เครื่องมือตรวจสอบการรับส่งข้อมูลเครือข่าย eBPF ใช้การใช้งานเคอร์เนลและพื้นที่ผู้ใช้ร่วมกันเพื่อตรวจสอบการใช้เครือข่ายในอุปกรณ์นับตั้งแต่การบูตอุปกรณ์ครั้งล่าสุด โดยจะมีฟังก์ชันการทำงานเพิ่มเติม เช่น การติดแท็กซ็อกเก็ต การแยกการรับส่งข้อมูลเบื้องหน้า/เบื้องหลัง และไฟร์วอลล์ต่อ UID เพื่อบล็อกแอปไม่ให้เข้าถึงเครือข่ายโดยขึ้นอยู่กับสถานะของโทรศัพท์ สถิติที่รวบรวมจากเครื่องมือจะจัดเก็บไว้ในโครงสร้างข้อมูลเคอร์เนลที่เรียกว่า eBPF maps และบริการต่างๆ เช่น NetworkStatsService จะใช้ผลลัพธ์เพื่อแสดงสถิติการเข้าชมแบบถาวรนับตั้งแต่การบูตครั้งล่าสุด

ตัวอย่างและแหล่งที่มา

การเปลี่ยนแปลงพื้นที่ผู้ใช้ส่วนใหญ่อยู่ในโปรเจ็กต์ system/netd และ framework/base การพัฒนาเกิดขึ้นใน AOSP ดังนั้นโค้ด AOSP จะอัปเดตอยู่เสมอ แหล่งที่มาส่วนใหญ่อยู่ที่ system/netd/server/TrafficController*, system/netd/bpfloader, และ system/netd/libbpf/ การเปลี่ยนแปลงเฟรมเวิร์กที่จำเป็นบางอย่างอยู่ใน framework/base/ และ system/core ด้วย

การใช้งาน

ตั้งแต่ Android 9 เป็นต้นไป อุปกรณ์ Android ที่ใช้เคอร์เนล 4.9 ขึ้นไปและมาพร้อมกับรุ่น P ต้องใช้การบัญชีการตรวจสอบการเข้าชมเครือข่ายแบบ eBPF แทน xt_qtaguid โครงสร้างพื้นฐานใหม่มีความยืดหยุ่นและบำรุงรักษาได้ง่ายกว่า และไม่ต้องใช้โค้ดเคอร์เนลนอกต้นไม้

ความแตกต่างที่สำคัญของการออกแบบระหว่างการตรวจสอบการเข้าชมแบบเดิมกับ eBPF แสดงอยู่ในรูปที่ 1

ความแตกต่างของการออกแบบการตรวจสอบการเข้าชมแบบเดิมและ eBPF

รูปที่ 1 ความแตกต่างของการออกแบบการตรวจสอบการเข้าชมแบบเดิม (ซ้าย) กับ eBPF (ขวา)

trafficController เวอร์ชันใหม่นี้ออกแบบตามตัวกรอง eBPF ต่อcgroup รวมถึงโมดูล xt_bpf netfilter ในเคอร์เนล ระบบจะใช้ตัวกรอง eBPF เหล่านี้กับการส่ง/รับแพ็กเก็ตเมื่อแพ็กเก็ตผ่านตัวกรอง cgroup ตัวกรอง eBPF จะอยู่ในเลเยอร์การขนส่งและมีหน้าที่รับผิดชอบในการนับการเข้าชมเทียบกับ UID ที่ถูกต้อง โดยขึ้นอยู่กับ UID ของซ็อกเก็ตและการตั้งค่าพื้นที่ผู้ใช้ xt_bpf netfilter เชื่อมต่ออยู่ที่เชนbw_raw_PREROUTINGและ bw_mangle_POSTROUTING และมีหน้าที่รับผิดชอบในการนับการรับส่งข้อมูลกับอินเทอร์เฟซที่ถูกต้อง

ในเวลาบูต กระบวนการพื้นที่ผู้ใช้ trafficController จะสร้างแผนที่ eBPF ใช้สำหรับรวบรวมข้อมูลและปักหมุดแผนที่ทั้งหมดเป็นไฟล์เสมือนที่ sys/fs/bpf จากนั้นกระบวนการที่มีสิทธิ์ bpfloader จะโหลดโปรแกรม eBPF ที่คอมไพล์ไว้ล่วงหน้าลงในเคอร์เนลและแนบไปกับ cgroup ที่ถูกต้อง มีรูทเดียว cgroup สําหรับการเข้าชมทั้งหมด ดังนั้นกระบวนการทั้งหมดควรรวมอยู่ใน cgroup นั้นโดยค่าเริ่มต้น

ขณะรันไทม์ trafficController จะติด/เลิกติดแท็กซ็อกเก็ตได้โดยเขียนลงใน traffic_cookie_tag_map และ traffic_uid_counterSet_map NetworkStatsService สามารถอ่านข้อมูลสถิติการเข้าชมจาก traffic_tag_stats_map, traffic_uid_stats_map และ traffic_iface_stats_map นอกจากฟังก์ชันการเก็บรวบรวมสถิติการเข้าชมแล้ว ตัวกรอง eBPF trafficController และ cgroup ยังมีหน้าที่บล็อกการเข้าชมจาก UID บางรายการด้วย ทั้งนี้ขึ้นอยู่กับการตั้งค่าโทรศัพท์ ฟีเจอร์การบล็อกการรับส่งข้อมูลเครือข่ายตาม UID จะมาแทนที่โมดูล xt_owner ในเคอร์เนล และคุณกำหนดค่าโหมดรายละเอียดได้โดยเขียนลงใน traffic_powersave_uid_map, traffic_standby_uid_map และ traffic_dozable_uid_map

การติดตั้งใช้งานใหม่จะเป็นไปตามการติดตั้งใช้งานโมดูล xt_qtaguid เดิม ดังนั้น TrafficController และ NetworkStatsService จะทํางานได้กับการติดตั้งใช้งานเดิมหรือใหม่ หากแอปใช้ API สาธารณะ ผู้ใช้ไม่ควรพบความแตกต่างใดๆ ไม่ว่าจะมีการใช้ xt_qtaguid หรือเครื่องมือ eBPF ในเบื้องหลัง

หากเคอร์เนลของอุปกรณ์อิงตามเคอร์เนลทั่วไปของ Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 ขึ้นไป) ก็ไม่จำเป็นต้องแก้ไข HAL, ไดรเวอร์ หรือโค้ดเคอร์เนลเพื่อใช้เครื่องมือ eBPF ใหม่

ข้อกำหนด

  1. การกําหนดค่าเคอร์เนลต้องเปิดการกําหนดค่าต่อไปนี้

    1. CONFIG_CGROUP_BPF=y
    2. CONFIG_BPF=y
    3. CONFIG_BPF_SYSCALL=y
    4. CONFIG_NETFILTER_XT_MATCH_BPF=y
    5. CONFIG_INET_UDP_DIAG=y

    การทดสอบการกําหนดค่าเคอร์เนล VTS มีประโยชน์เมื่อยืนยันการเปิดใช้การกําหนดค่าที่ถูกต้อง

กระบวนการเลิกใช้งาน xt_qtaguid เดิม

เครื่องมือ eBPF ใหม่จะแทนที่xt_qtaguidโมดูลและxt_ownerโมดูลที่ใช้เป็นพื้นฐาน เราจะเริ่มนำโมดูล xt_qtaguid ออกจากเคอร์เนล Android และปิดใช้การกำหนดค่าที่ไม่จำเป็น

ในรุ่น Android 9 ระบบจะเปิดโมดูล xt_qtaguid ในอุปกรณ์ทุกเครื่อง แต่ระบบจะย้าย API สาธารณะทั้งหมดที่อ่านไฟล์ proc ของโมดูล xt_qtaguid โดยตรงไปยังบริการ NetworkManagement NetworkManagement บริการจะทราบว่าเครื่องมือ eBPF เปิดอยู่หรือไม่ และเลือกข้อบังคับที่เหมาะสมเพื่อรับสถิติการใช้งานเครือข่ายของแอปแต่ละรายการ ทั้งนี้ขึ้นอยู่กับเวอร์ชันเคอร์เนลของอุปกรณ์และระดับ API แรก แอปที่มี SDK ระดับ 28 ขึ้นไปจะถูกบล็อกไม่ให้เข้าถึงไฟล์ xt_qtaguid proc โดย sepolicy

ใน Android เวอร์ชันถัดไปหลังเวอร์ชัน 9 เราจะบล็อกการเข้าถึงไฟล์ xt_qtaguid proc ของแอปโดยสมบูรณ์ และจะเริ่มนำข้อบังคับ xt_qtaguid ออกจากเคอร์เนลทั่วไปของ Android เวอร์ชันใหม่ หลังจากนำออกแล้ว เราจะอัปเดตการกำหนดค่าพื้นฐานของ Android สำหรับเวอร์ชันเคอร์เนลนั้นเพื่อปิดโมดูล xt_qtaguid อย่างชัดเจน เราจะเลิกใช้งานโมดูล xt_qtaguid โดยสมบูรณ์เมื่อข้อกำหนดเวอร์ชันเคอร์เนลขั้นต่ำสำหรับรุ่น Android ต้องเป็น 4.9 ขึ้นไป

ในรุ่น Android 9 เฉพาะอุปกรณ์ที่เปิดตัวพร้อมกับรุ่น Android 9 เท่านั้นที่ต้องมีฟีเจอร์ eBPF ใหม่ สำหรับอุปกรณ์ที่มาพร้อมกับเคอร์เนลที่รองรับเครื่องมือ eBPF เราขอแนะนำให้อัปเดตเป็นฟีเจอร์ eBPF ใหม่เมื่ออัปเกรดเป็น Android 9 ไม่มีการทดสอบ CTS เพื่อบังคับใช้การอัปเดตดังกล่าว

การตรวจสอบความถูกต้อง

คุณควรใช้แพตช์จากเคอร์เนลทั่วไปของ Android และ AOSP หลักของ Android เป็นประจํา ตรวจสอบว่าการติดตั้งใช้งานของคุณผ่านการทดสอบ VTS และ CTS ที่เกี่ยวข้อง, netd_unit_test และ libbpf_test

การทดสอบ

มีkernel net_tests เพื่อให้แน่ใจว่าคุณได้เปิดใช้ฟีเจอร์ที่จำเป็นและพอร์ตแพตช์เคอร์เนลที่จำเป็นแล้ว การทดสอบจะผสานรวมเป็นส่วนหนึ่งของการทดสอบ VTS ของ Android 9 เวอร์ชันต่างๆ มียูนิตเทสต์บางอย่างใน system/netd/ (netd_unit_test และ libbpf_test) และมีการทดสอบบางอย่างใน netd_integration_test เพื่อตรวจสอบลักษณะการทำงานโดยรวมของเครื่องมือใหม่

CTS และเครื่องมือตรวจสอบ CTS

เนื่องจากรุ่น Android 9 รองรับทั้ง 2 โมดูลการตรวจสอบการเข้าชม จึงไม่มีการทดสอบ CTS เพื่อบังคับให้ติดตั้งใช้งานโมดูลใหม่ในอุปกรณ์ทั้งหมด แต่สำหรับอุปกรณ์ที่มีเคอร์เนลเวอร์ชันสูงกว่า 4.9 ซึ่งเดิมมาพร้อมกับรุ่น Android 9 (เช่น API ระดับแรก >= 28) จะมี CTS Test ใน GSI เพื่อตรวจสอบว่ามีการกําหนดค่าข้อบังคับใหม่อย่างถูกต้อง คุณสามารถใช้การทดสอบ CTS เวอร์ชันเก่า เช่น TrafficStatsTest, NetworkUsageStatsTest และ CtsNativeNetTestCases เพื่อตรวจสอบลักษณะการทำงานให้สอดคล้องกับโมดูล UID เวอร์ชันเก่า

การทดสอบด้วยตนเอง

มียูนิตเทสต์บางส่วนใน system/netd/ (netd_unit_test, netd_integration_test และ libbpf_test) รองรับ dumpsys สำหรับการตรวจสอบสถานะด้วยตนเอง คำสั่ง dumpsys netd จะแสดงสถานะพื้นฐานของโมดูล trafficController และระบุว่า eBPF เปิดอยู่อย่างถูกต้องหรือไม่ หากเปิด eBPF ไว้ คำสั่ง dumpsys netd trafficcontroller จะแสดงเนื้อหาโดยละเอียดของแผนที่ eBPF แต่ละรายการ ซึ่งรวมถึงข้อมูลซ็อกเก็ตที่ติดแท็ก สถิติต่อแท็ก UID และ iface และการจับคู่ UID ของเจ้าของ

สถานที่ทดสอบ

การทดสอบ CTS อยู่ที่

การทดสอบ VTS จะอยู่ที่นี่ https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py

การทดสอบ 1 หน่วยจะอยู่ที่นี่