Android Packet Filter (APF) permite que el marco controle la lógica de filtrado de paquetes de hardware en tiempo de ejecución. Esto permite que el sistema ahorre energía al colocar paquetes en el hardware, al tiempo que permite que el marco de Android cambie las reglas de filtrado en tiempo de ejecución según las condiciones de la red.
Descripción general de la APF
APF consta de dos componentes principales:
- El intérprete de APF se ejecuta en hardware de red (normalmente, el chipset Wi-Fi). El intérprete de APF ejecuta el código de bytes APF en los paquetes recibidos por el hardware y decide si los acepta o descarta.
- El código de generación del programa APF se ejecuta en la CPU principal. El código crea y actualiza programas APF según el estado de la red y del dispositivo.
Los métodos Wi-Fi HAL permiten que el marco de Android instale el código de bytes del programa APF y lea los contadores actuales. El módulo Network Stack Mainline puede actualizar el código de bytes del programa APF en cualquier momento mientras APF se está ejecutando.
Hay varios filtros APF implementados. Por ejemplo, APF incluye filtros para eliminar tipos de ether no permitidos, filtrar paquetes de anuncios de enrutadores (RA) IPv6, filtrar el tráfico de transmisión y multidifusión si no se mantiene el bloqueo de multidifusión, eliminar paquetes DHCP para otros hosts y eliminar el protocolo de resolución de direcciones (ARP) no solicitada. y paquetes ND (descubrimiento de vecinos). La lista completa de filtros se define en ApfFilter
.
Debido a que el código de generación del programa APF es parte del módulo Network Stack, la lógica de filtrado se puede actualizar y se pueden agregar nuevos filtros a través de actualizaciones mensuales de Mainline.
Integración APF
La API de APF se define en apf_interpreter.h
. El código de firmware de Wi-Fi llama int accept_packet()
para determinar si el paquete debe descartarse (valor de retorno cero) o pasarse (valor de retorno distinto de cero). Las instrucciones APF tienen una longitud variable. Cada instrucción tiene al menos un byte de longitud. Los códigos de instrucciones APF se definen en apf.h
APF depende de una memoria dedicada. La memoria se utiliza tanto para el programa APF como para el almacenamiento de datos, y el chipset no debe borrar ni escribir la memoria excepto a través de los métodos APF HAL. El código de bytes APF utiliza el almacenamiento de datos para almacenar contadores de paquetes aceptados y descartados. La región de datos se puede leer desde el marco de Android. La cantidad mínima de memoria disponible para APF debe ser 1024 bytes.
Depurar APF
Para verificar si APF está habilitado en el dispositivo, mostrar el programa actual y mostrar los contadores actuales, ejecute el comando adb shell dumpsys network_stack
. El siguiente es un ejemplo de este comando:
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
El resultado de este ejemplo del comando adb shell dumpsys network_stack
incluye lo siguiente:
-
ApfCapabilities{version: 4, maxSize: 4096, format: 1}
: esto significa que los chips Wi-Fi son compatibles con APF (versión 4). -
Last program
: esta sección es el último programa binario APF instalado en formato de cadena hexadecimal. -
APF packet counters
: esta sección muestra cuántos paquetes pasa o descarta APF y los motivos específicos.
Para decodificar y desmontar el código en un lenguaje ensamblador legible por humanos, utilice la herramienta apf_disassembler
. Para compilar el binario ejecutable, ejecute el comando m apf_disassembler
. El siguiente es un ejemplo de cómo utilizar la herramienta 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
......
Para comprobar los resultados de APF sin conexión, utilice la herramienta apf_run
. Para compilar el binario ejecutable, ejecute el comando m apf_run
. El siguiente es un ejemplo de cómo comparar un solo paquete usando el comando apf_run
.
Para proporcionar la presentación de cadena binaria hexadecimal del paquete sin formato, utilice la opción --packet
. Para proporcionar la cadena binaria hexadecimal de la región de datos, que se utiliza para almacenar el contador APF , utilice la --data option
. Dado que cada contador tiene una longitud de 4 bytes, las regiones de datos deben ser lo suficientemente largas para garantizar que no se produzca un desbordamiento del búfer.
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001
Para comparar los resultados de APF con el archivo pcap tomado por tcpdump, use el comando apf_run
de la siguiente manera:
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea