Filtr pakietów Androida

Filtr pakietów Androida (APF) umożliwia platformie sterowania logiką filtrowania pakietów przez sprzęt w czasie działania. Dzięki temu system oszczędza energię przez upuszczanie pakietów w sprzęcie, a platforma Androida może zmieniać reguły filtrowania w czasie działania w zależności od warunków sieciowych.

Przegląd APF

Raport APF składa się z 2 głównych elementów:

  • Interpreter pliku APK działa na sprzęcie sieciowym (zwykle jest to chipset Wi-Fi). Interpreter APF uruchamia kod bajtowy APF na pakietach otrzymanych przez sprzęt i decyduje, czy je zaakceptować czy odrzucić.
  • Kod generowania programu APK działa na głównym CPU. Kod tworzy i aktualizuje programy APF odpowiednio do stanu sieci i urządzenia.

Metody HAL Wi-Fi pozwalają platformie Androida zainstalować kod bajtowy programu APF i odczytywać bieżące liczniki. Moduł Mainline stosu sieciowego może aktualizować kod bajtowy programu APF w dowolnym momencie, gdy jest on uruchomiony.

Zaimplementowaliśmy kilka filtrów APF. Na przykład APF obejmuje filtry pomijające niedozwolone typy etertypów, filtrowanie pakietów reklam routera IPv6 (RA), filtrowanie ruchu multiemisji i rozgłaszania, jeśli blokada multiemisji nie jest wstrzymywana, usuwanie pakietów DHCP innych hostów oraz usuwanie niezamówionych pakietów protokołu rozpoznawania adresów (ARP) i pakietu ND (znajdowania sąsiadów). Pełną listę filtrów znajdziesz tutaj: ApfFilter.

Ponieważ kod generowania programu APF jest częścią modułu stosu sieciowego, można zaktualizować logikę filtrowania i dodawać nowe filtry w ramach comiesięcznych aktualizacji Mainline.

Integracja APF

Interfejs APF API został zdefiniowany tutaj: apf_interpreter.h. Kod oprogramowania Wi-Fi wywołuje int accept_packet(), aby określić, czy pakiet powinien zostać utracony (wartość zwrócona) czy przekazywana (wartość zwracana niezerowa). Instrukcje APF mają zmienną długość. Każda instrukcja ma co najmniej jeden bajt. Kody instrukcji dotyczących APF są zdefiniowane tutaj: apf.h.

APF wykorzystuje dedykowaną pamięć. Pamięć jest używana zarówno na potrzeby programu APF, jak i do przechowywania danych, a pamięć nie może być czyszczona ani zapisywana przez chipset, poza metodami APF HAL. Kod bajtowy APF wykorzystuje pamięć masową do przechowywania liczników zaakceptowanych i porzuconych pakietów. Region danych można odczytywać z platformy Androida. Minimalna ilość pamięci dostępna dla dostępu APF musi wynosić 1024 bajty.

Debuguj APF

Aby sprawdzić, czy na urządzeniu jest włączony tryb APF, wyświetl bieżący program i bieżące liczniki, uruchom polecenie adb shell dumpsys network_stack. Oto przykład tego polecenia:

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

Dane wyjściowe tego przykładowego polecenia adb shell dumpsys network_stack zawierają te informacje:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1}: oznacza, że układy Wi-Fi obsługują APF (wersja 4).
  • Last program: ta sekcja zawiera ostatnio zainstalowany plik binarny programu APF w formacie szesnastkowym.
  • APF packet counters: w tej sekcji możesz sprawdzić, ile pakietów jest przekazywanych lub pomijanych przez APF oraz jakie są przyczyny ich utraty.

Do zdekodowania i dezasemblowania kodu do postaci zrozumiałego dla człowieka języka asemblera użyj narzędzia apf_disassembler. Aby skompilować plik binarny pliku wykonywalnego, uruchom polecenie m apf_disassembler. Poniżej znajdziesz przykład korzystania z narzędzia 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
......

Aby sprawdzić wyniki wyszukiwania offline, użyj narzędzia apf_run. Aby skompilować plik binarny pliku wykonywalnego, uruchom polecenie m apf_run. Poniżej pokazujemy, jak sprawdzić pojedynczy pakiet przy użyciu polecenia apf_run.

Aby zapewnić prezentację szesnastkowych ciągów binarnych surowego pakietu, użyj opcji --packet. Aby podać szesnastkowy ciąg binarny regionu danych, który jest używany do przechowywania licznika plików APK, użyj --data option. Ponieważ każdy licznik ma 4 bajty, regiony danych muszą być wystarczająco długie, aby nie doszło do przepełnienia bufora.

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

Aby porównać wyniki APF z plikiem pcap pobranym przez tcpdump, użyj polecenia apf_run w ten sposób:

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