Android-Paketfilter

Mit dem Android Packet Filter (APF) kann das Framework die Filterlogik für Hardwarepakete zur Laufzeit steuern. Auf diese Weise spart das System Energie, indem Pakete auf der Hardware gelöscht werden, während das Android-Framework die Filterregeln zur Laufzeit basierend auf den Netzwerkbedingungen ändern kann.

APF-Übersicht

APF besteht aus zwei Hauptkomponenten:

  • Der APF-Interpreter wird auf Netzwerkhardware ausgeführt (in der Regel auf dem WLAN-Chipsatz). Der APF-Interpreter führt den APF-Bytecode für Pakete aus, die von der Hardware empfangen werden, und entscheidet, ob sie akzeptiert oder gelöscht werden sollen.
  • Der APF-Code zur Programmgenerierung wird auf der Haupt-CPU ausgeführt. Der Code erstellt und aktualisiert APF-Programme entsprechend dem Netzwerk- und Gerätestatus.

Mit WLAN-HAL-Methoden kann das Android-Framework den Bytecode des APF-Programms installieren und die aktuellen Zähler lesen. Das Mainline-Modul des Network Stack kann den Bytecode des APF-Programms jederzeit aktualisieren, während APF ausgeführt wird.

Es sind mehrere APF-Filter implementiert. Beispielsweise enthält APF Filter, um nicht zugelassene Ethertypen zu löschen, IPv6 Router Advertising-Pakete (RA) zu filtern, Multicast- und Broadcast-Traffic zu filtern, wenn die Multicast-Sperre nicht gehalten wird, DHCP-Pakete für andere Hosts löschen und ND-Pakete unerwünschter Adressauflösungsprotokoll (ARP) und (Nachbar Discovery) ND-Pakete löschen. Die vollständige Liste der Filter ist in ApfFilter definiert.

Da der Code zur Generierung des APF-Programms Teil des Network Stack-Moduls ist, kann die Filterlogik über monatliche Mainline-Aktualisierungen aktualisiert und neue Filter hinzugefügt werden.

APF-Integration

Die APF API ist in apf_interpreter.h definiert. Der WLAN-Firmwarecode ruft int accept_packet() auf, um zu ermitteln, ob das Paket gelöscht (Null-Rückgabewert) oder übergeben werden soll (Rückgabewert ungleich null). APF-Anweisungen haben variable Länge. Jeder Befehl hat mindestens ein Byte. Die APF-Anleitungscodes sind in apf.h definiert.

APF nutzt dedizierten Arbeitsspeicher. Der Arbeitsspeicher wird sowohl für das APF-Programm selbst als auch für die Datenspeicherung verwendet und darf nicht vom Chipsatz gelöscht oder geschrieben werden, außer mit den APF HAL-Methoden. Der APF-Bytecode verwendet den Datenspeicher, um Zähler für akzeptierte und verworfene Pakete zu speichern. Der Speicherort für Daten kann aus dem Android-Framework gelesen werden. Der für das ADF verfügbare Mindestspeichervolumen muss 1.024 Byte betragen.

Fehler in APF beheben

Mit dem Befehl adb shell dumpsys network_stack können Sie prüfen, ob APF auf dem Gerät aktiviert ist, das aktuelle Programm und die aktuellen Zähler aufrufen. Das folgende Beispiel zeigt diesen Befehl:

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

Die Ausgabe für diesen adb shell dumpsys network_stack-Beispielbefehl enthält Folgendes:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1}: Das bedeutet, dass die WLAN-Chips APF (Version 4) unterstützen.
  • Last program: Dieser Abschnitt ist das zuletzt installierte APF-Programmbinärprogramm im Hexadezimalstringformat.
  • APF packet counters: In diesem Abschnitt wird angezeigt, wie viele Pakete von APF übergeben oder gelöscht werden und aus welchen Gründen sie es löschen.

Verwenden Sie das apf_disassembler-Tool, um den Code in eine für Menschen lesbare Assembler-Sprache zu decodieren und zu zerlegen. Führen Sie den Befehl m apf_disassembler aus, um die ausführbare Binärdatei zu kompilieren. Das folgende Beispiel zeigt die Verwendung des apf_disassembler-Tools.

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
......

Mit dem apf_run-Tool können Sie die APF-Ergebnisse offline prüfen. Führen Sie den Befehl m apf_run aus, um die ausführbare Binärdatei zu kompilieren. Das folgende Beispiel zeigt, wie Sie mit dem Befehl apf_run ein einzelnes Paket prüfen können.

Verwenden Sie die Option --packet, um das Rohpaket als binären Hexadezimalstring des Rohpakets bereitzustellen. Verwenden Sie --data option, um den binären Hexadezimalstring des Speicherorts für Daten anzugeben, in dem der APF-Zähler gespeichert wird. Da jeder Zähler 4 Byte lang ist, müssen die Speicherorte für Daten lang genug sein, damit kein Pufferüberlauf auftritt.

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

Verwenden Sie den Befehl apf_run, um die APF-Ergebnisse mit der von „tcpdump“ aufgenommenen pcap-Datei zu vergleichen:

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