# A Firewall pf do macOS: O Que Consegue Fazer, e Por Que Não Pode Ser a Sua Firewall por Aplicação > Um olhar prático sobre o pf, o filtro de pacotes BSD dentro do macOS: inspecionar e carregar regras com o pfctl, e as razões concretas — nomes de anfitrião, identidade de processo, pedidos — pelas quais nunca foi feito para ser uma firewall por aplicação. HisnLabs Security & Research Team · Published 2026-09-17 Canonical: https://hisnlabs.com/pt/blog/macos-pf-firewall-limits 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: *Terminal — estado e contadores do pf* ```console $ 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 ``` Depois 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: *Terminal — regras atualmente carregadas* ```console $ sudo pfctl -s rules # example output, trimmed scrub-anchor "com.apple/*" all fragment reassemble anchor "com.apple/*" all block drop in log quick from to any ``` Aquela 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: *Terminal — a listar todas as âncoras carregadas recursivamente* ```console $ sudo pfctl -a '*' -s rules # example output, trimmed to the anchors that exist on a stock Mac ``` ### Escrever 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`: */etc/pf.anchors/test-block* ```text block drop out quick on en0 proto tcp to 203.0.113.10 port 443 ``` Para 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: *Terminal — a carregar e confirmar a regra* ```console $ 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 ``` > **Warning:** Isto é um exercício de laboratório, não uma recomendação para editar à mão o `/etc/pf.conf` num Mac do dia a dia. Um erro de sintaxe num conjunto de regras ativo pode cortar a sua própria sessão SSH ou bloquear tráfego de que precisava e — como a secção seguinte explica — as suas regras escritas à mão não sobrevivem da forma que poderia esperar. ## Por 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 | *Três formas de filtrar tráfego num Mac, e o que cada uma realmente sabe* 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 FireAI Pilot) 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](https://hisnlabs.com/fireai/pt/download). ## Sources - [pfctl(8) man page (Xcode man pages mirror)](https://keith.github.io/xcode-man-pages/pfctl.8.html) - [OpenBSD pf.conf(5) man page](https://man.openbsd.org/pf.conf) - [Apple Developer: Content filter providers (NetworkExtension)](https://developer.apple.com/documentation/networkextension/content-filter-providers) - [Apple Support: Block connections to your Mac with a firewall](https://support.apple.com/guide/mac-help/block-connections-to-your-mac-with-a-firewall-mh34041/mac)