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 pf deja de ser útil 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:
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/sLuego, 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:
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 anyEsa 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:
sudo pfctl -a '*' -s rules
# example output, trimmed to the anchors that exist on a stock MacEscribir 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:
block drop out quick on en0 proto tcp to 203.0.113.10 port 443Para 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:
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 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?".
| Acercarse | Ve IP/puerto | Sabe qué aplicación | Maneja direcciones IP renombradas/rotativas | Puede avisar al usuario | Dirección |
|---|---|---|---|---|---|
pf (pfctl) | Sí | No | No: resuelto una vez en el momento de la carga | No | O bien, por regla |
| Firewall de aplicaciones (Configuración del sistema) | No (alternar a nivel de aplicación) | Sí | N / A | No | Solo entrante |
| Filtro de contenido de extensión de red | Sí | Sí, a través del objeto de flujo | Sí, evaluado por flujo en vivo | Sí, 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é están haciendo las funciones VPN y de uso compartido de Internet de Apple bajo el capó, 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.
Dónde entran FireAI y 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 producto de HisnLabs: un firewall con IA que corre directamente en tu Mac. Te muestra, en lenguaje claro, cada conexión que hacen tus aplicaciones y te deja decidir qué sale de tu Mac; su IA funciona de manera local, así que tu tráfico nunca se envía a nosotros ni a nadie más. El equipo de investigación en seguridad de HisnLabs es el que mantiene esas decisiones confiables: cataloga qué dominios son simple telemetría y cuáles un servicio real, rastrea el país y la red detrás de cada conexión, y entrena el modelo local (la función Autopilot) con patrones de tráfico reales, sin que nada de eso salga de tu Mac.
Puedes leer las decisiones técnicas detrás de FireAI, o probarlo durante 17 días, en FireAI, de HisnLabs.
