Фильтр пакетов Android

Android Packet Filter (APF) позволяет платформе управлять логикой аппаратной фильтрации пакетов во время выполнения. Это позволяет системе экономить электроэнергию, отбрасывая пакеты на оборудовании, в то же время позволяя платформе Android изменять правила фильтрации во время выполнения в зависимости от условий сети.

Обзор НПФ

АПФ состоит из двух основных компонентов:

  • Интерпретатор APF работает на сетевом оборудовании (обычно на чипсете Wi-Fi). Интерпретатор APF запускает байт-код APF для пакетов, полученных оборудованием, и решает, принять или отбросить их.
  • Код генерации программы APF выполняется на главном процессоре. Код создает и обновляет программы APF в соответствии с состоянием сети и устройства.

Методы Wi-Fi HAL позволяют платформе Android устанавливать байт-код программы APF и считывать текущие счетчики. Модуль Network Stack Mainline может обновлять байт-код программы APF в любое время во время работы APF.

Реализовано несколько фильтров APF. Например, APF включает в себя фильтры для отбрасывания запрещенных типов Ethernet, фильтрации пакетов объявления маршрутизатора IPv6 (RA), фильтрации многоадресного и широковещательного трафика, если блокировка многоадресной рассылки не удерживается, отбрасывания пакетов DHCP для других хостов и отбрасывания незапрошенного протокола разрешения адресов (ARP). и (обнаружение соседей) пакеты ND. Полный список фильтров определен в ApfFilter .

Поскольку код создания программы APF является частью модуля Network Stack, логику фильтрации можно обновлять и добавлять новые фильтры посредством ежемесячных обновлений Mainline.

Интеграция НПФ

API APF определен в apf_interpreter.h . Код прошивки Wi-Fi вызывает int accept_packet() , чтобы определить, должен ли пакет быть отброшен (нулевое возвращаемое значение) или передан (ненулевое возвращаемое значение). Инструкции APF имеют переменную длину. Каждая инструкция имеет длину не менее одного байта. Коды инструкций APF определены в apf.h

APF использует выделенную память. Память используется как для самой программы APF, так и для хранения данных, и память не должна очищаться или записываться чипсетом, кроме как с помощью методов APF HAL. Байт-код APF использует хранилище данных для хранения счетчиков принятых и отброшенных пакетов. Область данных можно прочитать из платформы Android. Минимальный объем памяти, доступный APF, должен составлять 1024 байта.

Отладка АПФ

Чтобы проверить, включен ли APF на устройстве, отобразить текущую программу и показать текущие счетчики, запустите команду adb shell dumpsys network_stack . Ниже приведен пример этой команды:

adb shell dumpsys network_stack
......
IpClient.wlan0 APF dump:
    Capabilities: ApfCapabilities{version: 4, maxSize: 4096, format: 1}
......
    Last program:
      6bfcb03a01b8120c6b9494026506006b907c025e88a27c025988a47c025488b87c024f88cd7c024a88e17c024588e384004408066a0e6bdca4022b000600010800060412147a1e016bd884021f00021a1c6b8c7c021c0000686bd4a402080006ffffffffffff6a266bbca402010004c0a801eb6bf87401f6120c84005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506c2fc393057dd6bf47401cb0a1e52f06bac7c01c600e06bb41a1e7e000001b9ffffffff6bb07e000001aec0a801ff6be868a4019a0006ffffffffffff6bb874019b6bf07401907c001386dd686bd0a4017d0006ffffffffffff6bc874017e0a147a0e3a6b980a267c017000ff6be07401650a366ba87c016200858219886a26a2050fff02000000000000000000000000006ba4740146aa0e84013700e6aa0f8c0130006068a4011b000f33330000000184c9b26aed4c86dd606a12a2f02600b03afffe8000000000000086c9b2fffe6aed4cff02000000000000000000000000000186006a3aa2e9024000123c92e4606a3ea2d70800000000000000006a56a2ce04030440c01a5a92c9601a5e92c4606a62a2bb04000000006a66a2a6102401fa00049c048400000000000000006a76a29d04030440c01a7a9298601a7e9293606c0082a28904000000006c0086a27310fdfd9ed67950000400000000000000006c0096a2690418033c001a9a9264606c009ea24e102401fa00049c048000000000000000006c00aea24404180330001ab2923f606c00b6a22910fdfd9ed67950000000000000000000006c00c6a21f04190300001aca921a606c00cea20410fdfd9ed67950000400000000000000016bc472086be4b03a01b87206b03a01b87201
    APF packet counters:
      TOTAL_PACKETS: 469
      PASSED_DHCP: 4
      PASSED_IPV4: 65
      PASSED_IPV6_NON_ICMP: 64
      PASSED_IPV4_UNICAST: 64
      PASSED_IPV6_ICMP: 223
      PASSED_IPV6_UNICAST_NON_ICMP: 6
      PASSED_ARP_UNICAST_REPLY: 4
      PASSED_NON_IP_UNICAST: 1
      DROPPED_RA: 4
      DROPPED_IPV4_BROADCAST_ADDR: 7
      DROPPED_IPV4_BROADCAST_NET: 27

Вывод для этого примера команды adb shell dumpsys network_stack включает следующее:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1} : это означает, что чипы Wi-Fi поддерживают APF (версия 4).
  • Last program : этот раздел представляет собой последний установленный двоичный файл программы APF в формате шестнадцатеричной строки.
  • APF packet counters . В этом разделе показано, сколько пакетов было пропущено или отброшено APF, а также указаны конкретные причины.

Чтобы декодировать и дизассемблировать код на удобочитаемый язык ассемблера, используйте инструмент apf_disassembler . Чтобы скомпилировать исполняемый двоичный файл, запустите команду m apf_disassembler . Ниже приведен пример использования инструмента apf_disassembler .

echo "6bfcb03a01b8120c6b949401e906006b907c01e288a27c01dd88a47c01d888b87c01d388cd7c01ce88e17c01c988e384004008066a0e6bdca401af000600010800060412147a1e016bd88401a300021a1c6b8c7c01a00000686bd4a4018c0006ffffffffffff1a266bc07c018900006bf874017e120c84005408000a17821f1112149c00181fffab0d2a108211446a3239a205065a56483ac3146bf47401530a1e52f06bac7c014e00e06bb41a1e7e00000141ffffffff6be868a4012d0006ffffffffffff6bb874012e6bf07401237c001386dd686bd0a401100006ffffffffffff6bc87401110a147a0d3a6b980a267c010300ff6be072f90a366ba87af8858218886a26a2040fff02000000000000000000000000006ba472ddaa0e82d0aeaa0f8c00c9025868a2b60f5a56483ac3140c8126f3895186dd606a12a28b2600783afffe8000000000000002005efffe00026fff02000000000000000000000000000186006a3aa284024000123c94007d02586a3ea2700800000000000000006a56a26704190500001a5a94006002586a5ea23b2020014860486000000000000000006464200148604860000000000000000000646a7ea23204030440c01a8294002b02581a8694002402586c008aa21a04000000006c008ea204102a0079e10abcf60500000000000000006bc472086be4b03a01b87206b03a01b87201" | out/host/linux-x86/bin/apf_disassembler
       0: li    r1, -4
       2: lddw  r0, [r1+0]
       3: add   r0, 1
       5: stdw  r0, [r1+0]
       6: ldh   r0, [12]
       8: li    r1, -108
      10: jlt   r0, 0x600, 504
      15: li    r1, -112
      17: jeq   r0, 0x88a2, 504
      22: jeq   r0, 0x88a4, 504
      27: jeq   r0, 0x88b8, 504
      32: jeq   r0, 0x88cd, 504
      37: jeq   r0, 0x88e1, 504
      42: jeq   r0, 0x88e3, 504
      47: jne   r0, 0x806, 116
......

Чтобы проверить результаты APF в автономном режиме, используйте инструмент apf_run . Чтобы скомпилировать исполняемый двоичный файл, запустите команду m apf_run . Ниже приведен пример проверки отдельного пакета с помощью команды apf_run .

Чтобы предоставить представление необработанного пакета в виде шестнадцатеричной двоичной строки, используйте опцию --packet . Чтобы предоставить шестнадцатеричную двоичную строку области данных, которая используется для хранения счетчика APF , используйте --data option . Поскольку длина каждого счетчика составляет 4 байта, области данных должны быть достаточно длинными, чтобы исключить переполнение буфера.

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001

Чтобы сравнить результаты APF с файлом pcap, полученным tcpdump, используйте команду apf_run следующим образом:

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea