Мониторинг трафика 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 per- cgroup и модуле сетевого фильтра xt_bpf внутри ядра. Эти фильтры eBPF применяются к передаваемым/принимаемым пакетам при их прохождении через фильтр. Фильтр eBPF cgroup расположен на транспортном уровне и отвечает за подсчёт трафика по правильному UID в зависимости от UID сокета и настроек пользовательского пространства. Сетевой фильтр 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 в зависимости от настроек телефона. Функция блокировки сетевого трафика на основе 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 Service. В зависимости от версии ядра устройства и первого уровня API служба NetworkManagement Service определяет, включены ли инструменты eBPF, и выбирает нужный модуль для получения статистики использования сети для каждого приложения. Приложениям с уровнем SDK 28 и выше доступ к proc-файлам xt_qtaguid запрещён политикой sepolicy.

В следующем релизе Android после 9 доступ приложений к этим proc-файлам 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 для проверки корректности настройки нового модуля. Старые тесты 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-release/net/test/bpf_test.py .

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