Мониторинг трафика 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 применяются к пакетам tx/rx при их прохождении через фильтр. Фильтр eBPF cgroup расположен на транспортном уровне и отвечает за подсчет трафика по правильному 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 в фоновом режиме.

Если ядро ​​устройства основано на общем ядре Android 4.9 (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 из ядра Android и отключать его ненужные конфигурации.

В Android 9 модуль xt_qtaguid включен на всех устройствах, но все публичные API, которые напрямую считывают файл proc модуля xt_qtaguid , перемещены в службу NetworkManagement . В зависимости от версии ядра устройства и первого уровня API служба NetworkManagement знает, включены ли инструменты eBPF, и выбирает правильный модуль для получения статистики использования сети для каждого приложения. Приложениям с уровнем SDK 28 и выше доступ к файлам proc xt_qtaguid блокируется политикой sepolicy.

В следующем релизе Android после версии 9 доступ приложений к файлам процесса xt_qtaguid будет полностью заблокирован. Мы начнем удалять модуль xt_qtaguid из новых стандартных ядер Android. После его удаления мы обновим базовую конфигурацию Android для этой версии ядра, чтобы явно отключить модуль xt_qtaguid . Модуль xt_qtaguid будет полностью устаревшим, когда минимальное требование к версии ядра для релиза Android достигнет 4.9 или выше.

В Android 9 новая функция eBPF требуется только для устройств, выпущенных с предустановленной версией Android 9. Для устройств, поставляемых с ядром, поддерживающим инструменты eBPF, мы рекомендуем обновить его до новой функции eBPF при обновлении до Android 9. Тест CTS для принудительного обновления отсутствует.

Валидация

Вам следует регулярно получать патчи из общих ядер Android и основной ветки Android AOSP. Убедитесь, что ваша реализация проходит соответствующие тесты VTS и CTS, netd_unit_test и libbpf_test .

Тестирование

В ядро ​​входят net_tests , которые гарантируют включение необходимых функций и перенос необходимых патчей ядра. Тесты интегрированы в состав тестов VTS для релиза Android 9. Некоторые модульные тесты находятся в system/netd/ ( netd_unit_test и libbpf_test ). В netd_integration_test находятся тесты для проверки общего поведения нового инструмента.

CTS и верификатор CTS

Поскольку оба модуля мониторинга трафика поддерживаются в релизе Android 9, нет теста CTS, который бы принудительно внедрял новый модуль на всех устройствах. Но для устройств с версией ядра выше 4.9, которые изначально поставлялись с релизом Android 9 (т.е. с первым уровнем API >= 28), существуют тесты CTS в GSI для проверки правильности настройки нового модуля. Для проверки соответствия поведения старому модулю UID можно использовать старые тесты CTS, такие как TrafficStatsTest , NetworkUsageStatsTest и CtsNativeNetTestCases .

Ручное тестирование

В 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/+/android17-release/net/test/bpf_test.py .

Модульные тесты находятся по адресу: