eBPF ट्रैफ़िक मॉनिटरिंग

eBPF नेटवर्क ट्रैफ़िक टूल, डिवाइस के आखिरी बार बूट होने के बाद से, डिवाइस पर नेटवर्क के इस्तेमाल को मॉनिटर करने के लिए, कर्नेल और उपयोगकर्ता स्पेस के कॉम्बिनेशन का इस्तेमाल करता है. यह सोकेट टैगिंग, फ़ोरग्राउंड/बैकग्राउंड ट्रैफ़िक को अलग करने, और हर यूआईडी फ़ायरवॉल जैसी अतिरिक्त सुविधाएं उपलब्ध कराता है. इससे, फ़ोन की स्थिति के हिसाब से ऐप्लिकेशन को नेटवर्क ऐक्सेस करने से रोका जा सकता है. टूल से इकट्ठा किए गए आंकड़ों को 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 से, कर्नेल 4.9 या इसके बाद के वर्शन पर काम करने वाले Android डिवाइसों के लिए, xt_qtaguid के बजाय eBPF पर आधारित नेटवर्क ट्रैफ़िक मॉनिटरिंग अकाउंटिंग का इस्तेमाल करना ज़रूरी है. ये डिवाइस, मूल रूप से P रिलीज़ के साथ शिप किए गए हैं. नया इन्फ़्रास्ट्रक्चर ज़्यादा सुविधाजनक और आसानी से मैनेज किया जा सकता है. साथ ही, इसमें किसी भी तरह के आउट-ऑफ़-ट्री कर्नल कोड की ज़रूरत नहीं होती.

लेगसी और eBPF ट्रैफ़िक मॉनिटरिंग के बीच डिज़ाइन के मुख्य अंतर, चित्र 1 में दिखाए गए हैं.

लेगसी और eBPF ट्रैफ़िक मॉनिटरिंग डिज़ाइन के बीच अंतर

पहली इमेज. लेगसी (बाईं ओर) और eBPF (दाईं ओर) ट्रैफ़िक मॉनिटरिंग डिज़ाइन के बीच अंतर

trafficController का नया डिज़ाइन, हर cgroup eBPF फ़िल्टर के साथ-साथ, kernel में मौजूद xt_bpf netfilter मॉड्यूल पर आधारित है. ये eBPF फ़िल्टर, फ़िल्टर से गुज़रने पर पैकेट tx/rx पर लागू होते हैं. cgroup eBPF फ़िल्टर, ट्रांसपोर्ट लेयर पर मौजूद होता है. यह सॉकेट यूआईडी और यूज़रस्पेस सेटिंग के आधार पर, सही यूआईडी के हिसाब से ट्रैफ़िक की गिनती करता है. xt_bpf नेटफ़िल्टर, 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 से ट्रैफ़िक के आंकड़ों का डेटा पढ़ सकता है. ट्रैफ़िक के आंकड़े इकट्ठा करने वाले फ़ंक्शन के अलावा, trafficController और cgroup eBPF फ़िल्टर भी कुछ UID से आने वाले ट्रैफ़िक को ब्लॉक करने के लिए ज़िम्मेदार हैं. यह फ़िल्टर, फ़ोन की सेटिंग के हिसाब से काम करता है. यूआईडी पर आधारित नेटवर्किंग ट्रैफ़िक को ब्लॉक करने की सुविधा, कोर में मौजूद xt_owner मॉड्यूल की जगह लेती है. साथ ही, ज़्यादा जानकारी वाले मोड को traffic_powersave_uid_map, traffic_standby_uid_map, और traffic_dozable_uid_map में लिखकर कॉन्फ़िगर किया जा सकता है.

नया लागू करने का तरीका, लेगसी xt_qtaguid मॉड्यूल के लागू करने के तरीके के मुताबिक है, ताकि TrafficController और NetworkStatsService, लेगसी या नए लागू करने के तरीके के साथ चल सकें. अगर ऐप्लिकेशन, सार्वजनिक एपीआई का इस्तेमाल करता है, तो बैकग्राउंड में xt_qtaguid या eBPF टूल का इस्तेमाल करने से कोई फ़र्क़ नहीं पड़ेगा.

अगर डिवाइस का कर्नेल, Android के सामान्य कर्नेल 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 या इसके बाद के वर्शन) पर आधारित है, तो नया 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

    वीटीएस के kernel कॉन्फ़िगरेशन की जांच करने से, यह पुष्टि करने में मदद मिलती है कि सही कॉन्फ़िगरेशन चालू है या नहीं.

लेगसी xt_qtaguid को बंद करने की प्रोसेस

नया eBPF टूल, xt_qtaguid मॉड्यूल और उस पर आधारित xt_owner मॉड्यूल की जगह ले रहा है. हम Android के कोर से xt_qtaguid मॉड्यूल को हटाना शुरू कर देंगे और इसके ग़ैर-ज़रूरी कॉन्फ़िगरेशन को बंद कर देंगे.

Android 9 रिलीज़ में, xt_qtaguid मॉड्यूल सभी डिवाइसों में चालू होता है. हालांकि, xt_qtaguid मॉड्यूल की प्रोसेस फ़ाइल को सीधे तौर पर पढ़ने वाले सभी सार्वजनिक एपीआई, NetworkManagement सेवा में ले जाए जाते हैं. डिवाइस के कर्नेल वर्शन और पहले एपीआई लेवल के आधार पर, NetworkManagement सेवा यह जानती है कि eBPF टूल चालू हैं या नहीं. साथ ही, हर ऐप्लिकेशन के नेटवर्क इस्तेमाल के आंकड़े के लिए सही मॉड्यूल चुनती है. SDK टूल के लेवल 28 और उसके बाद के वर्शन वाले ऐप्लिकेशन, sepolicy की वजह से xt_qtaguid प्रोसेस फ़ाइलों को ऐक्सेस नहीं कर सकते.

Android 9 के बाद रिलीज़ होने वाले अगले वर्शन में, उन xt_qtaguid प्रोसेस फ़ाइलों का ऐप्लिकेशन ऐक्सेस पूरी तरह से ब्लॉक कर दिया जाएगा. साथ ही, हम Android के नए सामान्य कर्नेल से xt_qtaguid मॉड्यूल को हटाना शुरू कर देंगे. इसे हटाने के बाद, हम उस कर्नेल वर्शन के लिए Android बेस कॉन्फ़िगरेशन को अपडेट करेंगे, ताकि xt_qtaguid मॉड्यूल को साफ़ तौर पर बंद किया जा सके. जब Android रिलीज़ के लिए, कर्नेल के कम से कम 4.9 या इसके बाद के वर्शन की ज़रूरत होगी, तब xt_qtaguid मॉड्यूल को पूरी तरह बंद कर दिया जाएगा.

Android 9 रिलीज़ में, सिर्फ़ उन डिवाइसों में नई eBPF सुविधा होनी चाहिए जो Android 9 रिलीज़ के साथ लॉन्च किए गए हैं. जिन डिवाइसों में eBPF टूल के साथ काम करने वाला कर्नेल पहले से मौजूद है उनके लिए, हमारा सुझाव है कि Android 9 रिलीज़ पर अपग्रेड करते समय, उन्हें नई eBPF सुविधा पर अपडेट करें. उस अपडेट को लागू करने के लिए, सीटीएस टेस्ट नहीं किया जाता.

पुष्टि करें

आपको समय-समय पर Android के सामान्य कर्नेल और Android AOSP के मुख्य वर्शन से पैच लेते रहना चाहिए. पक्का करें कि आपने जो तरीका लागू किया है वह लागू होने वाले VTS और CTS टेस्ट, netd_unit_test, और libbpf_test के मुताबिक हो.

टेस्ट करना

kernel net_tests की मदद से यह पक्का किया जा सकता है कि आपने ज़रूरी सुविधाएं चालू की हों और ज़रूरी kernel पैच बैकपोर्ट किए गए हों. ये टेस्ट, Android 9 रिलीज़ के VTS टेस्ट के हिस्से के तौर पर इंटिग्रेट किए गए हैं. system/netd/ (netd_unit_test और libbpf_test) में कुछ यूनिट टेस्ट मौजूद हैं. netd_integration_test में कुछ टेस्ट मौजूद हैं, ताकि नए टूल के पूरे व्यवहार की पुष्टि की जा सके.

सीटीएस और सीटीएस की पुष्टि करने वाला टूल

Android 9 रिलीज़ में, ट्रैफ़िक मॉनिटरिंग के दोनों मॉड्यूल काम करते हैं. इसलिए, सभी डिवाइसों पर नए मॉड्यूल को लागू करने के लिए, सीटीएस टेस्ट नहीं किया जाता. हालांकि, जिन डिवाइसों का कर्नेल वर्शन 4.9 से ज़्यादा है और जो मूल रूप से Android 9 रिलीज़ (यानी पहला एपीआई लेवल >= 28) के साथ शिप होते हैं उनके लिए, GSI पर CTS टेस्ट किए जाते हैं. इससे यह पुष्टि की जाती है कि नया मॉड्यूल सही तरीके से कॉन्फ़िगर किया गया है या नहीं. TrafficStatsTest, NetworkUsageStatsTest, और CtsNativeNetTestCases जैसे पुराने CTS टेस्ट का इस्तेमाल करके, यह पुष्टि की जा सकती है कि व्यवहार, पुराने यूआईडी मॉड्यूल के मुताबिक है या नहीं.

मैन्युअल टेस्टिंग

system/netd/ में कुछ यूनिट टेस्ट (netd_unit_test, netd_integration_test और libbpf_test) मौजूद हैं. स्थिति की मैन्युअल जांच करने के लिए, dumpsys की सुविधा उपलब्ध है. कमांड dumpsys netd, trafficController मॉड्यूल की बुनियादी स्थिति दिखाता है. साथ ही, यह भी बताता है कि eBPF सही तरीके से चालू है या नहीं. अगर eBPF चालू है, तो कमांड dumpsys netd trafficcontroller हर eBPF मैप का ज़्यादा जानकारी वाला कॉन्टेंट दिखाता है. इसमें टैग किए गए सॉकेट की जानकारी, हर टैग के आंकड़े, यूआईडी और इंटरफ़ेस, और मालिकाना हक वाले यूआईडी का मैच शामिल है.

टेस्टिंग की जगहें

CTS टेस्ट यहां मौजूद हैं:

VTS टेस्ट https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py पर मौजूद हैं.

यूनिट टेस्ट यहां मौजूद हैं: