Todo o Mac vem com duas coisas a que as pessoas chamam "a firewall". Uma é a Firewall de Aplicações nas Definições do Sistema, um interruptor por aplicação para ligações de entrada. A outra, mais discreta, é o pf, o filtro de pacotes BSD que o macOS herdou da linhagem FreeBSD/OpenBSD e que a própria Apple usa por baixo dos panos para a partilha de internet, a VPN e o NAT. Utilizadores avançados e administradores podem falar com ele diretamente através do pfctl, e muitos guias mostram um excerto de pf.conf e dão o assunto por encerrado. O que esses guias raramente explicam é onde o pf deixa de ser útil para aquilo que a maioria das pessoas realmente quer: observar e controlar o que as suas próprias aplicações enviam para fora. Isto é um laboratório, não uma palestra — vamos ligar o pf, escrever uma regra, ler o estado que mantém, e depois ver exatamente por que razão esse estado tem a forma errada para uma firewall por aplicação.
O que o pf realmente é
O pf é um filtro de pacotes ao nível do kernel: inspeciona pacotes à medida que atravessam interfaces de rede e decide, regra a regra, se os deixa passar ou os bloqueia. Não tem nenhum conceito de "aplicações" — trabalha puramente sobre cabeçalhos de pacotes: endereço de origem e destino, porta, protocolo, interface, direção. Isso não é uma limitação que alguém se tenha esquecido de corrigir; é a conceção. O pf foi construído para filtrar tráfego na camada de rede, a mesma camada em que operam os routers e as gateways, e é muito bom nesse trabalho.
Fala-se com ele através do pfctl, o utilitário de controlo. A sua página de manual é explícita quanto à divisão entre as duas coisas que faz: carrega conjuntos de regras a partir de um ficheiro de configuração, e reporta sobre o estado que o kernel está a manter. Duas opções importam mais para ativar e desativar o filtro, nas próprias palavras da página de manual: -e ("Ativar o filtro de pacotes.") e -d ("Desativar o filtro de pacotes."). Mais nada no pf está ligado ou desligado — o conjunto de regras inteiro move-se em bloco.
Ligá-lo e ler o seu estado
Um laboratório rápido, num Mac onde se sinta confortável a usar sudo. Primeiro, verifique se o filtro já está ativado e veja os seus 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/sDepois liste as regras que o kernel mantém atualmente. pfctl -s rules faz exatamente isto; a página de manual nota que, com -v, também imprime contagens de avaliação por regra, pacotes e bytes:
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 anyAquela linha com.apple/* não é decoração. A Apple carrega as suas próprias regras em âncoras nomeadas — o termo do pf para um subconjunto de regras autocontido, que pode ser trocado dentro e fora sem recarregar tudo o resto. A opção -a do pfctl visa uma âncora específica, e, segundo a página de manual, usá-la com um caráter universal ativa a impressão recursiva de âncoras aninhadas, o que é como se vê o que a própria Apple carregou ao lado de tudo o que se acrescente:
sudo pfctl -a '*' -s rules
# example output, trimmed to the anchors that exist on a stock MacEscrever e carregar uma regra de teste
Um ficheiro de âncora mínimo que bloqueia um endereço IP de saída, guardado como /etc/pf.anchors/test-block:
block drop out quick on en0 proto tcp to 203.0.113.10 port 443Para carregar um único ficheiro de âncora, o pfctl -f lê regras a partir de um ficheiro, segundo a sua página de manual, que descreve o ficheiro como contendo macros, tabelas, opções e regras de filtragem:
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 = 443Por que o pf não pode ser a sua firewall por aplicação
Nada do que se segue é um erro. É o que acontece quando se aponta um filtro de pacotes de camada de rede para um trabalho que exige saber qual o processo que enviou o pacote.
Não faz ideia de que aplicação enviou o pacote
As regras do pf correspondem a IP, porta, protocolo, interface e direção. Não há nenhum campo para "nome do processo", "identificador do pacote" ou "assinatura de código", porque o pf está na camada onde os pacotes existem, mas os processos não. Duas aplicações completamente diferentes a abrir ligações TCP para o mesmo IP e porta são indistinguíveis para o pf. Se quiser permitir que o Slack alcance um anfitrião enquanto bloqueia todas as outras aplicações de alcançar esse mesmo anfitrião, o pf sozinho não consegue exprimir essa regra.
Uma regra sobre um nome de anfitrião é uma regra sobre o IP que esse nome tinha no momento do carregamento
Os ficheiros pf.conf referem-se frequentemente a um nome de anfitrião por legibilidade — block from evil.example.com. O que realmente é carregado não é esse nome; é o endereço para o qual resolveu. A página de manual do pf.conf do OpenBSD diz isto com clareza: "A resolução de nomes de anfitrião e a tradução de interface para endereço são feitas no momento do carregamento do conjunto de regras." Não há nenhuma consulta DNS em tempo de execução à medida que o tráfego flui — a substituição acontece uma vez, quando se corre pfctl -f, e a regra continua a corresponder a esse único endereço até se recarregar. Isso está bem para um servidor com um IP estático. Desmorona-se no momento em que o nome por trás dele é uma CDN, um balanceador de carga na nuvem, ou qualquer serviço que rode ou balanceie a carga entre muitos endereços — o que descreve a maior parte da internet em 2026. Uma regra pensada para bloquear "este serviço" estreita-se silenciosamente para "qualquer que fosse o IP desse serviço que respondeu quando carreguei a regra", e o tráfego para todos os outros endereços que o mesmo nome de anfitrião resolve passa direto.
Sem pedidos, sem conversa — apenas um conjunto de regras estático
O pf não tem nenhum modelo de interação. Não consegue pausar uma ligação e perguntar "o Mail quer alcançar 51.x.x.x na porta 993 pela primeira vez — permitir?" Ou corresponde a uma regra que já se escreveu, ou cai para o comportamento por defeito. Cada decisão tem de ser antecipada e escrita antecipadamente, em termos de IP e porta, antes de o tráfego acontecer. Não há nenhum equivalente a um pedido de primeira ligação, porque pedir exige saber qual a aplicação a perguntar, e o pf não tem essa informação para começar.
A sua configuração escrita à mão não sobrevive a uma atualização
A Apple trata o /etc/pf.conf e as âncoras que carrega como configuração gerida pelo sistema, associada a componentes internos do macOS — a partilha de internet, a VPN, as próprias âncoras da Firewall de Aplicações dependem todas dele. As atualizações do macOS estão livres para reescrever ou substituir esse ficheiro. Se o editou à mão para acrescentar as suas próprias regras, não há nenhuma garantia de que sobrevivam à atualização seguinte; descobre-se da pior forma, depois do facto, que a sua regra deixou silenciosamente de se aplicar. Um ficheiro de configuração que uma pessoa mantém à mão e que o sistema operativo periodicamente substitui é um mau sítio para guardar a única coisa com que realmente se importava — "o meu Mac voltou a falar com aquele endereço".
Sem visualizador de registos, sem histórico, sem mapa
O pf pode registar pacotes correspondidos numa pseudo-interface, pflog0, se uma regra incluir a palavra-chave log — visível acima na regra da lista de bloqueio, na saída de -s rules anterior. Mas esse registo é um fluxo de captura de pacotes, legível com tcpdump -i pflog0, não um histórico pesquisável. Não há nenhum visualizador incorporado, nenhuma lista por aplicação do que foi bloqueado e quando, nenhum país ou organização associado a um endereço, nada que se mostraria a alguém para responder "o que é que este Mac tentou alcançar na semana passada." Obtêm-se pacotes em bruto, e cabe-lhe construir o resto sozinho.
A camada que a Apple realmente construiu para este trabalho
A própria resposta da Apple para "quero filtrar o tráfego do meu Mac por aplicação" não é o pf — é a estrutura Network Extension, especificamente os seus fornecedores de filtro de conteúdo. A documentação para programadores da Apple descreve o modelo diretamente: "Um filtro de conteúdo de rede no dispositivo examina o conteúdo de rede do utilizador à medida que passa pela pilha de rede e determina se deve bloquear esse conteúdo ou deixá-lo seguir para o seu destino final", e um fornecedor de dados de filtro — um NEFilterDataProvider — "recebe conteúdo de rede do utilizador e examina esse conteúdo para determinar se deve bloquear ou permitir." Os fluxos são representados como objetos NEFilterFlow (com NEFilterBrowserFlow e NEFilterSocketFlow como casos concretos), que é a peça em falta que o pf nunca teve: um objeto de fluxo que uma aplicação de filtragem pode inspecionar e associar de volta ao processo que o abriu, antes de decidir permitir ou bloquear.
É também por isso que a Firewall de Aplicações incorporada (o interruptor nas Definições do Sistema) é um animal diferente do pf, e não uma interface para ele. O próprio guia da Apple descreve-a apenas em termos de entrada: pode "proteger o seu Mac de contacto indesejado iniciado por outros computadores", e funciona deixando-o "selecionar aplicações e serviços, e especificar se podem ter acesso através da firewall." Por aplicação, sim — mas apenas para ligações a chegar, e apenas através do mecanismo específico que a Apple construiu para esse único trabalho. Responde a uma pergunta diferente de "o que é que a minha aplicação está a enviar para fora."
| Abordagem | Vê IP/porta | Sabe qual a aplicação | Lida com IPs renomeados/rotativos | Consegue pedir ao utilizador | Direção |
|---|---|---|---|---|---|
pf (pfctl) | Sim | Não | Não — resolvido uma vez no carregamento | Não | Qualquer uma, por regra |
| Firewall de Aplicações (Definições do Sistema) | Não (interruptor ao nível da aplicação) | Sim | N/A | Não | Apenas entrada |
| Filtro de conteúdo Network Extension | Sim | Sim, através do objeto de fluxo | Sim — avaliado por fluxo ao vivo | Sim, pela aplicação construída sobre ele | Saída e entrada |
Nada disto torna o pf inútil. Se correr um Mac como um router leve, precisar de rejeitar um intervalo conhecidamente mau ao nível do kernel independentemente de qual processo está a perguntar, ou quiser perceber o que as próprias funcionalidades de partilha de internet e VPN da Apple estão a fazer por baixo dos panos, o pf é a ferramenta certa e única para esse trabalho, e pfctl -s rules / -s info são a forma certa de o observar. O que nunca ia fazer é responder à pergunta que a maioria das pessoas realmente tem: qual das minhas aplicações está a falar com quem, agora mesmo, e posso ser consultado antes de uma nova ligação ser permitida.
O papel do FireAI e da 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.
O FireAI é o produto da HisnLabs: uma firewall com IA que corre diretamente no seu Mac. Mostra, em linguagem clara, cada ligação que as suas aplicações fazem e deixa-o decidir o que sai do seu Mac — a IA funciona localmente, pelo que o seu tráfego nunca é enviado para nós nem para mais ninguém. A equipa de investigação em segurança da HisnLabs é quem mantém essas decisões fiáveis: cataloga que domínios são simples telemetria e quais são um serviço real, acompanha o país e a rede por detrás de uma ligação e treina o modelo local (a funcionalidade Autopilot) com padrões de tráfego reais, sem que nada disso saia do seu Mac.
Pode ler as decisões técnicas por detrás dele, ou experimentar o FireAI durante 17 dias, em FireAI, da HisnLabs.
