Android-Paketfilter

Mit Android Packet Filter (APF) kann das Framework die Hardware-Paketfilterlogik zur Laufzeit steuern. Dadurch kann das System Strom sparen, indem es Pakete in der Hardware verwirft, während das Android-Framework gleichzeitig die Filterregeln zur Laufzeit basierend auf den Netzwerkbedingungen ändern kann.

APF-Übersicht

APF besteht aus zwei Hauptkomponenten:

  • Der APF-Interpreter läuft auf Netzwerkhardware (typischerweise dem Wi-Fi-Chipsatz). Der APF-Interpreter führt APF-Bytecode auf von der Hardware empfangenen Paketen aus und entscheidet, ob er diese akzeptiert oder verwirft.
  • Der APF-Programmgenerierungscode wird auf der Haupt-CPU ausgeführt. Der Code erstellt und aktualisiert APF-Programme entsprechend dem Netzwerk- und Gerätestatus.

Wi-Fi-HAL-Methoden ermöglichen es dem Android-Framework, den APF-Programmbytecode zu installieren und die aktuellen Zähler zu lesen. Das Network Stack Mainline-Modul kann den Bytecode des APF-Programms jederzeit aktualisieren, während APF ausgeführt wird.

Es sind mehrere APF-Filter implementiert. APF umfasst beispielsweise Filter zum Verwerfen unzulässiger Ethertypen, zum Filtern von IPv6-Router-Advertisement-(RA)-Paketen, zum Filtern von Multicast- und Broadcast-Verkehr, wenn die Multicast-Sperre nicht aufrechterhalten wird, zum Verwerfen von DHCP-Paketen für andere Hosts und zum Verwerfen von Unsolicited Address Resolution Protocol (ARP). und (Nachbarnerkennung) ND-Pakete. Die vollständige Liste der Filter ist in ApfFilter definiert.

Da der APF-Programmgenerierungscode Teil des Network Stack-Moduls ist, kann die Filterlogik durch monatliche Mainline-Updates aktualisiert und neue Filter hinzugefügt werden.

APF-Integration

Die APF-API ist in apf_interpreter.h definiert. Der Wi-Fi-Firmware-Code ruft int accept_packet() auf, um zu bestimmen, ob das Paket verworfen (Rückgabewert Null) oder weitergeleitet (Rückgabewert ungleich Null) werden soll. APF-Anweisungen haben eine variable Länge. Jede Anweisung ist mindestens ein Byte lang. Die APF-Anweisungscodes sind in apf.h definiert.

APF ist auf dedizierten Speicher angewiesen. Der Speicher wird sowohl für das APF-Programm selbst als auch zur Datenspeicherung verwendet und darf vom Chipsatz nur über die APF-HAL-Methoden gelöscht oder beschrieben werden. Der APF-Bytecode verwendet den Datenspeicher, um Zähler für akzeptierte und verworfene Pakete zu speichern. Der Datenbereich kann aus dem Android-Framework gelesen werden. Die für APF verfügbare Mindestspeichermenge muss 1024 Byte betragen.

APF debuggen

Um zu überprüfen, ob APF auf dem Gerät aktiviert ist, das aktuelle Programm anzuzeigen und die aktuellen Zähler anzuzeigen, führen Sie den Befehl adb shell dumpsys network_stack aus. Das Folgende ist ein Beispiel für 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 dieses Beispielbefehls adb shell dumpsys network_stack umfasst Folgendes:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1} : Dies bedeutet, dass die Wi-Fi-Chips APF (Version 4) unterstützen.
  • Last program : Dieser Abschnitt ist die zuletzt installierte APF-Programmbinärdatei im Hex-String-Format.
  • APF packet counters : In diesem Abschnitt wird angezeigt, wie viele Pakete von APF weitergeleitet oder verworfen werden und aus welchen Gründen.

Um den Code zu dekodieren und in eine für Menschen lesbare Assemblersprache zu zerlegen, verwenden Sie das Tool apf_disassembler . Um die ausführbare Binärdatei zu kompilieren, führen Sie den Befehl m apf_disassembler aus. Im Folgenden finden Sie ein Beispiel für die Verwendung des Tools 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
......

Um die APF-Ergebnisse offline zu überprüfen, verwenden Sie das Tool apf_run . Um die ausführbare Binärdatei zu kompilieren, führen Sie den Befehl m apf_run aus. Im Folgenden finden Sie ein Beispiel für die Prüfung eines einzelnen Pakets mithilfe des Befehls apf_run .

Um die Hex-Binärzeichenfolgendarstellung des Rohpakets bereitzustellen, verwenden Sie die Option --packet . Um die hexadezimale Binärzeichenfolge des Datenbereichs bereitzustellen, der zum Speichern des APF-Zählers verwendet wird, verwenden Sie die --data option . Da jeder Zähler 4 Byte lang ist, müssen die Datenbereiche lang genug sein, um sicherzustellen, dass kein Pufferüberlauf auftritt.

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

Um die APF-Ergebnisse mit der von tcpdump erstellten pcap-Datei zu vergleichen, verwenden Sie den Befehl apf_run wie folgt:

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