El blog de seguridad de FireAI

Por FireAI Security & Research Team · Publicado

El firewall pf de macOS: qué puede hacer y por qué no puede ser el firewall de su aplicación

El firewall pf de macOS: qué puede hacer y por qué no puede ser el firewall de su aplicación

Cada Mac viene con dos cosas que la gente llama "el firewall". Uno es el Firewall de aplicaciones en Configuración del sistema, un conmutador por aplicación para conexiones entrantes. El otro, más silencioso, es pf, el filtro de paquetes BSD que macOS heredó del linaje FreeBSD/OpenBSD y que la propia Apple utiliza bajo el capó para compartir Internet, VPN y NAT. Los usuarios avanzados y los administradores pueden hablar con él directamente con pfctl, y muchas guías muestran un fragmento de pf.conf y terminan el día. Lo que esas guías rara vez explican es dónde deja de ser útil pf para lo que la mayoría de la gente realmente quiere: ver y controlar lo que envían sus propias aplicaciones. Este es un laboratorio, no una conferencia: activaremos pf, escribiremos una regla, leeremos el estado que mantiene y luego veremos exactamente por qué ese estado tiene la forma incorrecta para un firewall de aplicación.

¿Qué es realmente pf?

pf es un filtro de paquetes a nivel de kernel: inspecciona los paquetes a medida que cruzan las interfaces de red y decide, regla por regla, si pasarlos o bloquearlos. No tiene el concepto de "aplicaciones": funciona únicamente con encabezados de paquetes: dirección de origen y destino, puerto, protocolo, interfaz, dirección. Esa no es una limitación que alguien haya olvidado solucionar; es el diseño. pf fue creado para filtrar el tráfico en la capa de red, la misma capa en la que operan los enrutadores y puertas de enlace, y es muy bueno en ese trabajo.

Le hablas con pfctl, la utilidad de control. Su página de manual es explícita sobre la división entre las dos cosas que hace: carga conjuntos de reglas desde un archivo de configuración e informa sobre el estado que mantiene el núcleo. Dos indicadores son los más importantes para habilitar y deshabilitar el filtro, en las propias palabras de la página de manual: -e (“Habilitar el filtro de paquetes”) y -d (“Deshabilitar el filtro de paquetes”). Nada más sobre pf está activado o desactivado: todo el conjunto de reglas se mueve al mismo tiempo.

Encendiéndolo y leyendo su estado

Una práctica de laboratorio rápida, en una Mac donde se sienta cómodo usando sudo. Primero, verifique si el filtro ya está habilitado y vea sus contadores:

Terminal: estado y contadores de pf
sudo pfctl -s info
# example output, trimmed — the real thing includes per-rule and per-source-tracking stats with -v
Status: Enabled for 0 days 02:14:07		Debug: err
State Table                          Total             Rate
  current entries                       42
  searches                           88213             9.7/s
  inserts                              611             0.1/s
  removals                             569             0.1/s

Luego, enumere las reglas que tiene actualmente el núcleo. pfctl -s rules hace exactamente esto; la página de manual señala que con -v también imprime recuentos, paquetes y bytes de evaluación por regla:

Terminal: reglas actualmente cargadas
sudo pfctl -s rules
# example output, trimmed
scrub-anchor "com.apple/*" all fragment reassemble
anchor "com.apple/*" all
block drop in log quick from <blocklist> to any

Esa línea com.apple/* no es decoración. Apple carga sus propias reglas en anclajes con nombre, el término de pf para un conjunto de subreglas autónomo que se puede intercambiar dentro y fuera sin recargar todo lo demás. La bandera -a de pfctl apunta a un ancla específica y, según la página de manual, usarla con un comodín permite la impresión recursiva de anclas anidadas, que es como ves lo que Apple ha cargado junto con todo lo que agregas:

Terminal: enumera cada ancla cargada de forma recursiva
sudo pfctl -a '*' -s rules
# example output, trimmed to the anchors that exist on a stock Mac

Escribir y cargar una regla de prueba

Un archivo ancla mínimo que bloquea una dirección IP saliente, guardado como /etc/pf.anchors/test-block:

/etc/pf.anchors/test-block
block drop out quick on en0 proto tcp to 203.0.113.10 port 443

Para cargar un único archivo ancla, pfctl -f lee las reglas de un archivo, según su página de manual, que describe que el archivo contiene macros, tablas, opciones y reglas de filtrado:

Terminal: cargar y confirmar la regla
sudo pfctl -f /etc/pf.anchors/test-block
sudo pfctl -s rules
block drop out quick on en0 proto tcp from any to 203.0.113.10 port = 443

¿Por qué pf no puede ser el firewall de tu aplicación?

Nada de lo que sigue es un error. Es lo que sucede cuando apunta un filtro de paquetes de capa de red a un trabajo que requiere saber qué proceso envió el paquete.

No tiene idea de qué aplicación envió el paquete.

Las reglas de pf coinciden en IP, puerto, protocolo, interfaz y dirección. No hay ningún campo para "nombre de proceso", "identificador de paquete" o "firma de código", porque pf se encuentra en la capa donde existen paquetes pero no procesos. Dos aplicaciones completamente diferentes que abren conexiones TCP a la misma IP y puerto son indistinguibles para pf. Si desea permitir que Slack llegue a un host mientras bloquea el resto de aplicaciones para que no lleguen a ese mismo host, pf por sí solo no puede expresar esa regla.

Una regla sobre un nombre de host es una regla sobre cualquier IP que tuviera ese nombre de host en el momento de la carga.

Los archivos pf.conf a menudo hacen referencia a un nombre de host para facilitar la lectura: block from evil.example.com. Lo que realmente se carga no es ese nombre; es cualquier dirección a la que resolvió. La página de manual de OpenBSD pf.conf dice esto claramente: "La resolución del nombre del host y la traducción de la interfaz para abordar se realizan en el momento de la carga del conjunto de reglas". No hay búsqueda de DNS en tiempo de ejecución a medida que fluye el tráfico: la sustitución ocurre una vez, cuando ejecuta pfctl -f, y la regla sigue coincidiendo con esa dirección hasta que la vuelve a cargar. Eso está bien para un servidor con una IP estática. Se desmorona en el momento en que el nombre detrás de esto es CDN, un equilibrador de carga en la nube o cualquier servicio que rote o equilibre la carga en muchas direcciones, lo que describe la mayor parte de Internet en 2026. Una regla destinada a bloquear "este servicio" se reduce silenciosamente a "cualquiera de las IP de ese servicio que respondiera cuando cargué la regla", y el tráfico a todas las demás direcciones que el mismo nombre de host resuelve navega directamente.

Sin indicaciones, sin conversación: solo un conjunto de reglas estáticas

pf no tiene modelo de interacción. No puede pausar una conexión y preguntar "El correo quiere llegar a 51.x.x.x en el puerto 993 por primera vez. ¿Permitirlo?". O coincide con una regla que ya escribió o no cumple con la regla predeterminada. Cada decisión debe anticiparse y anotarse con antelación, en términos de IP y puerto, antes de que se produzca el tráfico. No existe un equivalente a un aviso de primera conexión, porque el aviso requiere saber qué aplicación está solicitando y, para empezar, pf no tiene esa información.

Su configuración escrita a mano no sobrevive a una actualización

Apple trata a /etc/pf.conf y los anclajes que carga como una configuración administrada por el sistema vinculada a las partes internas de macOS: el uso compartido de Internet, la VPN y los propios anclajes del firewall de aplicaciones dependen de ello. Las actualizaciones de macOS son gratuitas para reescribir o reemplazar ese archivo. Si lo ha editado manualmente para agregar sus propias reglas, no hay garantía de que sobrevivan a la próxima actualización; descubres por las malas, después del hecho, que tu regla silenciosamente dejó de aplicarse. Un archivo de configuración que una persona mantiene a mano y que el sistema operativo sobrescribe periódicamente es un mal lugar para guardar lo único que realmente le importaba: "¿mi Mac volvió a comunicarse con esa dirección?".

Sin visor de registros, sin historial, sin mapa

pf puede registrar paquetes coincidentes en una pseudointerfaz, pflog0, si una regla incluye la palabra clave log, visible arriba en la regla de lista de bloqueo de la salida anterior -s rules. Pero ese registro es un flujo de captura de paquetes, legible con tcpdump -i pflog0, no un historial con capacidad de búsqueda. No hay un visor integrado, ni una lista por aplicación de lo que se bloqueó y cuándo, ningún país u organización adjunta a una dirección, nada que le mostrarías a alguien para responder "¿a qué intentó llegar esta Mac la semana pasada?". Obtienes paquetes sin procesar y puedes construir el resto tú mismo.

La capa que Apple realmente construyó para este trabajo

La propia respuesta de Apple a "Quiero filtrar el tráfico de mi Mac por aplicación" no es pf, sino el marco de Network Extension, específicamente sus proveedores de filtrado de contenido. La documentación para desarrolladores de Apple describe el modelo directamente: "Un filtro de contenido de red en el dispositivo examina el contenido de la red del usuario a medida que pasa a través de la pila de red y determina si debe bloquear ese contenido o permitir que pase a su destino final", y un proveedor de datos de filtro, un NEFilterDataProvider, "recibe el contenido de la red del usuario y examina ese contenido para determinar si debe bloquearlo o permitirlo". Los flujos se representan como objetos NEFilterFlow (con NEFilterBrowserFlow y NEFilterSocketFlow como casos concretos), que es la pieza que faltaba que nunca tuvo: un objeto de flujo que una aplicación de filtrado puede inspeccionar y vincular al proceso que lo abrió, antes de decidir aprobarlo o bloquearlo.

Esta es también la razón por la cual el Firewall de aplicaciones incorporado (el interruptor en Configuración del sistema) es un animal diferente de pf, no una interfaz para él. La propia guía de Apple lo describe sólo en términos entrantes: "puede proteger su Mac de contactos no deseados iniciados por otras computadoras" y funciona permitiéndole "seleccionar aplicaciones y servicios, y especificar si pueden tener acceso a través del firewall". Por aplicación, sí, pero solo para las conexiones entrantes y solo a través del mecanismo específico que Apple creó para ese trabajo. Responde a una pregunta diferente a "¿qué envía mi aplicación?".

Tres formas de filtrar el tráfico en una Mac y lo que realmente sabe cada una
AcercarseVe IP/puertoSabe qué aplicaciónManeja direcciones IP renombradas/rotativasPuede avisar al usuarioDirección
pf (pfctl)SíNoNo: resuelto una vez en el momento de la cargaNoO bien, por regla
Firewall de aplicaciones (Configuración del sistema)No (alternar a nivel de aplicación)SíN / ANoSolo entrante
Filtro de contenido de extensión de redSíSí, a través del objeto de flujoSí, evaluado por flujo en vivoSí, mediante la aplicación integrada.salientes y entrantes

Nada de esto hace que pf sea inútil. Si ejecuta una Mac como un enrutador liviano, necesita rechazar un rango conocido como incorrecto en el nivel del kernel, independientemente del proceso que lo solicite, o desea comprender qué hacen internamente las funciones VPN y de uso compartido de Internet de Apple, pf es la única y adecuada herramienta para ese trabajo, y pfctl -s rules / -s info son la forma correcta de verlo. Lo que nunca iba a hacer es responder la pregunta que la mayoría de la gente realmente tiene: cuál de mis aplicaciones está hablando con quién, en este momento, y si me pueden preguntar antes de que llegue una nueva.

El papel de FireAI y de HisnLabs

pf and the built-in Application Firewall are both worth using — FireAI does not replace either; it fills the specific gap neither one can, by tying outbound decisions to the app’s code signature and asking before an unknown one gets a first connection.

FireAI es el propio producto de HisnLabs: un cortafuegos con IA integrada para Mac. Muestra, en lenguaje claro, cada conexión que hacen tus aplicaciones y te deja decidir qué sale de tu Mac; su IA funciona en el propio equipo, así que tu tráfico nunca se envía a HisnLabs ni a nadie más. El equipo de investigación en seguridad de HisnLabs es quien mantiene esas decisiones fiables: cataloga qué dominios son simple telemetría frente a un servicio real, sigue el país y la red detrás de una conexión, y entrena el modelo local (la función Autopilot) con tráfico real, sin que nada salga de tu Mac.

Puedes leer las decisiones técnicas detrás de esto, o probar FireAI durante 17 días, en FireAI, de HisnLabs.

Fuentes