نظارت بر ترافیک eBPF

ابزار ترافیک شبکه eBPF از ترکیبی از پیاده‌سازی هسته و فضای کاربری برای نظارت بر میزان استفاده از شبکه در دستگاه از آخرین بوت دستگاه استفاده می‌کند. این ابزار قابلیت‌های اضافی مانند برچسب‌گذاری سوکت، جداسازی ترافیک پیش‌زمینه/پس‌زمینه و فایروال per-UID را برای مسدود کردن دسترسی برنامه‌ها به شبکه بسته به وضعیت تلفن فراهم می‌کند. آمار جمع‌آوری‌شده از این ابزار در یک ساختار داده هسته به نام eBPF maps ذخیره می‌شود و نتیجه توسط سرویس‌هایی مانند NetworkStatsService برای ارائه آمار ترافیک مداوم از آخرین بوت استفاده می‌شود.

مثال‌ها و منابع

تغییرات فضای کاربری عمدتاً در پروژه‌های system/netd و framework/base اعمال می‌شود. توسعه در AOSP انجام می‌شود، بنابراین کد AOSP همیشه به‌روز خواهد بود. منبع عمدتاً در system/netd/server/TrafficController* ، system/netd/bpfloader و system/netd/libbpf/ قرار دارد. برخی از تغییرات ضروری چارچوب نیز در framework/base/ و system/core اعمال می‌شوند.

پیاده‌سازی

با شروع از اندروید ۹، دستگاه‌های اندرویدی که روی هسته ۴.۹ یا بالاتر کار می‌کنند و در ابتدا با نسخه P عرضه شده‌اند، باید به جای xt_qtaguid از حسابداری نظارت بر ترافیک شبکه مبتنی بر eBPF استفاده کنند. زیرساخت جدید انعطاف‌پذیرتر و قابل نگهداری‌تر است و به هیچ کد هسته خارج از درخت نیاز ندارد.

تفاوت‌های عمده طراحی بین نظارت بر ترافیک سنتی و eBPF در شکل 1 نشان داده شده است.

تفاوت‌های طراحی نظارت بر ترافیک قدیمی و eBPF

شکل ۱. تفاوت‌های طراحی نظارت بر ترافیک قدیمی (چپ) و eBPF (راست)

طراحی جدید trafficController بر اساس فیلتر per- cgroup eBPF و همچنین ماژول xt_bpf netfilter در داخل هسته است. این فیلترهای eBPF هنگام عبور بسته‌های tx/rx از فیلتر، روی آنها اعمال می‌شوند. فیلتر 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 بخواند. علاوه بر تابع جمع‌آوری آمار ترافیک، trafficController و فیلتر cgroup eBPF بسته به تنظیمات تلفن، مسئول مسدود کردن ترافیک از UID های خاص نیز هستند. ویژگی مسدود کردن ترافیک شبکه مبتنی بر UID جایگزینی برای ماژول xt_owner در داخل هسته است و حالت جزئیات را می‌توان با نوشتن در traffic_powersave_uid_map ، traffic_standby_uid_map و traffic_dozable_uid_map پیکربندی کرد.

پیاده‌سازی جدید از پیاده‌سازی ماژول قدیمی xt_qtaguid پیروی می‌کند، بنابراین TrafficController و NetworkStatsService با پیاده‌سازی قدیمی یا جدید اجرا خواهند شد. اگر برنامه از APIهای عمومی استفاده می‌کند، نباید هیچ تفاوتی بین استفاده از ابزارهای xt_qtaguid یا eBPF در پس‌زمینه وجود داشته باشد.

اگر هسته دستگاه بر اساس هسته رایج اندروید ۴.۹ (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 یا بالاتر) باشد، برای پیاده‌سازی ابزار جدید eBPF نیازی به هیچ تغییری در HALها، درایورها یا کد هسته نیست.

الزامات

  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 از هسته اندروید و غیرفعال کردن پیکربندی‌های غیرضروری آن خواهیم کرد.

در نسخه اندروید ۹، ماژول xt_qtaguid در همه دستگاه‌ها فعال است، اما تمام APIهای عمومی که مستقیماً فایل proc ماژول xt_qtaguid را می‌خوانند، به سرویس NetworkManagement منتقل می‌شوند. بسته به نسخه هسته دستگاه و سطح اول API، سرویس NetworkManagement می‌داند که آیا ابزارهای eBPF فعال هستند یا خیر و ماژول مناسب را برای دریافت آمار استفاده از شبکه هر برنامه انتخاب می‌کند. برنامه‌هایی با سطح SDK 28 و بالاتر از طریق seppolicy از دسترسی به فایل‌های proc ماژول xt_qtaguid مسدود می‌شوند.

در نسخه بعدی اندروید پس از نسخه ۹، دسترسی برنامه به فایل‌های xt_qtaguid proc کاملاً مسدود خواهد شد و ما شروع به حذف ماژول xt_qtaguid از هسته‌های جدید رایج اندروید خواهیم کرد. پس از حذف آن، پیکربندی پایه اندروید را برای آن نسخه هسته به‌روزرسانی خواهیم کرد تا ماژول xt_qtaguid را به صراحت غیرفعال کند. ماژول xt_qtaguid زمانی که حداقل نسخه هسته مورد نیاز برای انتشار اندروید ۴.۹ یا بالاتر باشد، کاملاً منسوخ خواهد شد.

در نسخه اندروید ۹، فقط دستگاه‌هایی که با نسخه اندروید ۹ عرضه می‌شوند، ملزم به داشتن ویژگی جدید eBPF هستند. برای دستگاه‌هایی که با هسته‌ای عرضه شده‌اند که می‌تواند از ابزارهای eBPF پشتیبانی کند، توصیه می‌کنیم هنگام ارتقا به نسخه اندروید ۹، آن را به ویژگی جدید eBPF به‌روزرسانی کنید. هیچ آزمایش CTS برای اعمال این به‌روزرسانی وجود ندارد.

اعتبارسنجی

شما باید مرتباً وصله‌هایی را از هسته‌های رایج اندروید و هسته اصلی AOSP اندروید دریافت کنید. مطمئن شوید که پیاده‌سازی شما تست‌های VTS و CTS مربوطه، netd_unit_test و libbpf_test با موفقیت پشت سر می‌گذارد.

آزمایش

برای اطمینان از فعال بودن ویژگی‌های مورد نیاز و بک‌پورت شدن پچ‌های مورد نیاز کرنل ، net_test های هسته وجود دارد. این تست‌ها به عنوان بخشی از تست‌های VTS نسخه اندروید ۹ ادغام شده‌اند. برخی تست‌های واحد در system/netd/ ( netd_unit_test و libbpf_test ) وجود دارد. برخی تست‌ها در netd_integration_test برای اعتبارسنجی رفتار کلی ابزار جدید وجود دارد.

CTS و تأییدکننده CTS

از آنجا که هر دو ماژول نظارت بر ترافیک در نسخه اندروید ۹ پشتیبانی می‌شوند، هیچ تست CTS برای اجرای اجباری ماژول جدید روی همه دستگاه‌ها وجود ندارد. اما برای دستگاه‌هایی با نسخه هسته بالاتر از ۴.۹ که در ابتدا با نسخه اندروید ۹ عرضه می‌شوند (یعنی اولین سطح API >= ۲۸)، تست‌های CTS روی 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/+/android16-qpr1-release/net/test/bpf_test.py قرار دارند.

تست‌های واحد در آدرس زیر قرار دارند: