Filtr pakietów systemu Android (APF) umożliwia platformie kontrolowanie logiki sprzętowego filtrowania pakietów w czasie wykonywania. Pozwala to systemowi oszczędzać energię, odrzucając pakiety na sprzęcie, jednocześnie umożliwiając platformie Android zmianę reguł filtrowania w czasie wykonywania w oparciu o warunki sieciowe.
Przegląd APF
APF składa się z dwóch głównych komponentów:
- Interpreter APF działa na sprzęcie sieciowym (zazwyczaj na chipsecie Wi-Fi). Interpreter APF uruchamia kod bajtowy APF na pakietach odebranych przez sprzęt i decyduje, czy je zaakceptować, czy odrzucić.
- Kod generowania programu APF działa na głównym procesorze. Kod tworzy i aktualizuje programy APF zgodnie ze stanem sieci i urządzenia.
Metody Wi-Fi HAL umożliwiają frameworkowi Android zainstalowanie kodu bajtowego programu APF i odczytanie bieżących liczników. Moduł Network Stack Mainline może aktualizować kod bajtowy programu APF w dowolnym momencie, gdy APF jest uruchomiony.
Zaimplementowano kilka filtrów APF. Na przykład APF zawiera filtry usuwające niedozwolone typy eterów, filtrujące pakiety reklam routera IPv6 (RA), filtrujące ruch multiemisji i rozgłoszeniowy, jeśli blokada multiemisji nie jest utrzymywana, usuwające pakiety DHCP dla innych hostów i odrzucające niechciany protokół rozpoznawania adresów (ARP). oraz (odkrycie sąsiada) pakiety ND. Pełna lista filtrów jest zdefiniowana w ApfFilter
.
Ponieważ kod generowania programu APF jest częścią modułu Network Stack, można aktualizować logikę filtrowania i dodawać nowe filtry poprzez comiesięczne aktualizacje Mainline.
Integracja APF
Interfejs API APF jest zdefiniowany w apf_interpreter.h
. Kod oprogramowania sprzętowego Wi-Fi wywołuje int accept_packet()
w celu określenia, czy pakiet powinien zostać odrzucony (wartość zwrócona zerem), czy przekazany (wartość zwrócona różna od zera). Instrukcje APF mają zmienną długość. Każda instrukcja ma długość co najmniej jednego bajtu. Kody instrukcji APF są zdefiniowane w apf.h
APF opiera się na dedykowanej pamięci. Pamięć jest wykorzystywana zarówno przez sam program APF, jak i do przechowywania danych, a pamięć nie może być czyszczona ani zapisywana przez chipset inaczej niż za pomocą metod APF HAL. Kod bajtowy APF wykorzystuje pamięć danych do przechowywania liczników zaakceptowanych i odrzuconych pakietów. Obszar danych można odczytać z platformy Android. Minimalna ilość pamięci dostępna dla APF musi wynosić 1024 bajty.
Debuguj plik APF
Aby sprawdzić, czy na urządzeniu jest włączona funkcja APF, wyświetlić bieżący program i wyświetlić aktualne liczniki, uruchom polecenie adb shell dumpsys network_stack
. Poniżej znajduje się 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
obejmują:
-
ApfCapabilities{version: 4, maxSize: 4096, format: 1}
: Oznacza to, że chipy Wi-Fi obsługują APF (wersja 4). -
Last program
: Ta sekcja zawiera najnowszy zainstalowany plik binarny programu APF w formacie ciągu szesnastkowego. -
APF packet counters
: ta sekcja pokazuje, ile pakietów zostało przekazanych lub odrzuconych przez APF i konkretne przyczyny.
Aby zdekodować i zdezasemblować kod na czytelny dla człowieka język asemblera, użyj narzędzia apf_disassembler
. Aby skompilować plik wykonywalny, uruchom komendę m apf_disassembler
. Poniżej znajduje się przykład użycia 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 APF w trybie offline, użyj narzędzia apf_run
. Aby skompilować plik wykonywalny, uruchom komendę m apf_run
. Poniżej znajduje się przykład sprawdzania pojedynczego pakietu za pomocą komendy apf_run
.
Aby zapewnić prezentację surowego pakietu w postaci binarnego ciągu szesnastkowego, użyj opcji --packet
. Aby podać szesnastkowy ciąg binarny obszaru danych, który jest używany do przechowywania licznika APF , użyj --data option
. Ponieważ każdy licznik ma długość 4 bajtów, obszary danych muszą być wystarczająco długie, aby zapobiec przepełnieniu bufora.
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001
Aby sprawdzić wyniki APF w pliku pcap pobranym przez tcpdump, użyj komendy apf_run
w następujący sposób:
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea