Il blog sulla sicurezza di FireAI

Di FireAI Security & Research Team · Pubblicato

Il firewall di macOS: cosa può fare e perché non può essere il firewall della tua app

Il firewall di macOS: cosa può fare e perché non può essere il firewall della tua app

Ogni Mac viene fornito con due cose che le persone chiamano "il firewall". Uno è il firewall dell'applicazione nelle Impostazioni di sistema, un interruttore per app per le connessioni in entrata. L'altro, più silenzioso, è pf, il filtro dei pacchetti BSD che macOS ha ereditato dalla linea FreeBSD/OpenBSD e che Apple stessa utilizza dietro le quinte per la condivisione Internet, VPN e NAT. Gli utenti esperti e gli amministratori possono parlarci direttamente con pfctl e molte guide mostrano uno snippet pf.conf e basta. Ciò che queste guide raramente spiegano è dove pf smette di essere utile per ciò che la maggior parte delle persone desidera realmente: guardare e controllare ciò che inviano le proprie app. Questo è un laboratorio, non una lezione: attiveremo pf, scriveremo una regola, leggeremo lo stato che mantiene e poi esamineremo esattamente il motivo per cui quello stato ha la forma sbagliata per un firewall per app.

Cos'è in realtà

pf è un filtro di pacchetti a livello di kernel: ispeziona i pacchetti mentre attraversano le interfacce di rete e decide, regola per regola, se passarli o bloccarli. Non ha il concetto di "app": funziona esclusivamente sulle intestazioni dei pacchetti: indirizzo di origine e destinazione, porta, protocollo, interfaccia, direzione. Questa non è una limitazione che qualcuno ha dimenticato di risolvere; è il disegno. pf è stato creato per filtrare il traffico a livello di rete, lo stesso livello in cui operano router e gateway, ed è molto bravo in quel lavoro.

Ci parli con pfctl, l'utilità di controllo. La sua pagina man è esplicita riguardo alla divisione tra le due cose che fa: carica set di regole da un file di configurazione e riporta lo stato mantenuto dal kernel. Due flag sono più importanti per abilitare e disabilitare il filtro, secondo le parole della pagina man: -e (“Abilita il filtro dei pacchetti.”) e -d (“Disabilita il filtro dei pacchetti.”). Nient'altro in pf è attivato o disattivato: l'intero set di regole si muove insieme.

Accendendolo e leggendone lo stato

Un laboratorio veloce, su un Mac in cui ti senti a tuo agio nell'usare sudo. Innanzitutto, controlla se il filtro è già abilitato e guarda i suoi contatori:

Terminale: stato e contatori
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

Quindi elenca le regole attualmente detenute dal kernel. pfctl -s rules fa esattamente questo; la pagina man rileva che con -v stampa anche conteggi, pacchetti e byte di valutazione per regola:

Terminale: regole attualmente caricate
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

Quella riga com.apple/* non è una decorazione. Apple carica le proprie regole in ancore con nome: il termine di pf per un set di regole secondarie autonomo che può essere scambiato dentro e fuori senza ricaricare tutto il resto. Il flag -a di pfctl prende di mira un'ancora specifica e, secondo la pagina man, il suo utilizzo con un carattere jolly consente la stampa ricorsiva di ancore nidificate, che è il modo in cui vedi ciò che Apple stessa ha caricato insieme a tutto ciò che aggiungi:

Terminale: elenca ricorsivamente ogni ancoraggio caricato
sudo pfctl -a '*' -s rules
# example output, trimmed to the anchors that exist on a stock Mac

Scrittura e caricamento di una regola di test

Un file di ancoraggio minimo che blocca un indirizzo IP in uscita, salvato come /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

Per caricare un singolo file di ancoraggio, pfctl -f legge le regole da un file, secondo la sua pagina man, che descrive il file come contenente macro, tabelle, opzioni e regole di filtro:

Terminale: caricamento e conferma della regola
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

Perché pf non può essere il firewall della tua app

Niente di quanto segue è un bug. È ciò che accade quando si punta un filtro di pacchetti a livello di rete su un lavoro che richiede di sapere quale processo ha inviato il pacchetto.

Non ha idea di quale app abbia inviato il pacchetto

Le regole pf corrispondono su IP, porta, protocollo, interfaccia e direzione. Non esiste un campo per "nome processo", "identificatore bundle" o "firma codice", perché pf si trova nello strato in cui esistono i pacchetti ma i processi no. Due app completamente diverse che aprono connessioni TCP allo stesso IP e porta sono indistinguibili da pf. Se vuoi consentire a Slack di raggiungere un host impedendo a tutte le altre app di raggiungere lo stesso host, pf da solo non può esprimere quella regola.

Una regola su un nome host è una regola su qualunque IP avesse il nome host al momento del caricamento

I file pf.conf spesso fanno riferimento a un nome host per motivi di leggibilità: block from evil.example.com. Ciò che effettivamente viene caricato non è quel nome; è qualunque sia l'indirizzo a cui si è risolto. La pagina man di OpenBSD pf.conf lo dice chiaramente: "La risoluzione del nome host e la traduzione dell'interfaccia per l'indirizzo vengono eseguite al momento del caricamento del set di regole." Non è prevista alcuna ricerca DNS in runtime durante il flusso del traffico: la sostituzione avviene una volta, quando esegui pfctl -f, e la regola continua a corrispondere a quell'indirizzo finché non lo ricarichi. Questo va bene per un server con un IP statico. Cade a pezzi nel momento in cui il nome dietro di esso è un CDN, un bilanciatore del carico cloud o qualsiasi servizio che ruota o bilancia il carico su molti indirizzi, il che descrive la maggior parte di Internet nel 2026. Una regola intesa a bloccare "questo servizio" si restringe silenziosamente a "qualunque degli IP di quel servizio abbia risposto quando ho caricato la regola" e il traffico verso ogni altro indirizzo con lo stesso nome host si risolve senza problemi.

Nessun suggerimento, nessuna conversazione: solo un insieme di regole statiche

pf non ha un modello di interazione. Non è possibile mettere in pausa una connessione e chiedere "Mail vuole raggiungere 51.x.x.x sulla porta 993 per la prima volta: consentirlo?" Corrisponde a una regola che hai già scritto oppure rientra nell'impostazione predefinita. Ogni decisione deve essere anticipata e scritta in anticipo, in termini di IP e porta, prima che si verifichi il traffico. Non esiste l'equivalente di una richiesta di prima connessione, perché la richiesta richiede di sapere quale app sta richiedendo e pf non dispone di tali informazioni per cominciare.

La configurazione scritta a mano non sopravvive a un aggiornamento

Apple tratta /etc/pf.conf e gli ancoraggi che carica come configurazione gestita dal sistema legata agli interni di macOS: la condivisione Internet, la VPN e gli ancoraggi dell'Application Firewall dipendono tutti da questo. Gli aggiornamenti di macOS sono gratuiti per riscrivere o sostituire quel file. Se lo hai modificato manualmente per aggiungere le tue regole, non c'è garanzia che sopravvivano al prossimo aggiornamento; scopri nel modo più duro, dopo il fatto, che la tua regola ha smesso silenziosamente di essere applicata. Un file di configurazione che una persona conserva manualmente e che il sistema operativo sovrascrive periodicamente è un brutto posto in cui conservare l'unica cosa a cui tieni davvero: "il mio Mac ha parlato di nuovo con quell'indirizzo?".

Nessun visualizzatore di registri, nessuna cronologia, nessuna mappa

pf può registrare i pacchetti corrispondenti su una pseudo-interfaccia, pflog0, se una regola include la parola chiave log — visibile sopra nella regola blocklist dal precedente output -s rules. Ma quel registro è un flusso di acquisizione di pacchetti, leggibile con tcpdump -i pflog0, non una cronologia ricercabile. Non esiste un visualizzatore integrato, nessun elenco per app di ciò che è stato bloccato e quando, nessun paese o organizzazione collegata a un indirizzo, niente che mostreresti a qualcuno per rispondere "cosa ha tentato di raggiungere questo Mac la scorsa settimana". Ottieni pacchetti grezzi e puoi costruire il resto da solo.

Il livello che Apple ha effettivamente creato per questo lavoro

La risposta di Apple a "Voglio filtrare il traffico del mio Mac per app" non è pf: è il framework Network Extension, in particolare i suoi fornitori di filtri dei contenuti. La documentazione per gli sviluppatori di Apple descrive direttamente il modello: "Un filtro del contenuto di rete sul dispositivo esamina il contenuto della rete dell'utente mentre passa attraverso lo stack di rete e determina se deve bloccare quel contenuto o consentirgli di passare alla sua destinazione finale," e un fornitore di dati di filtro - un NEFilterDataProvider — "riceve il contenuto della rete dell'utente ed esamina quel contenuto per determinare se bloccarlo o consentirlo." I flussi sono rappresentati come oggetti NEFilterFlow (con NEFilterBrowserFlow e NEFilterSocketFlow come casi concreti), che è il pezzo mancante che non ha mai avuto: un oggetto flusso che un'app di filtro può ispezionare e ricollegare al processo che lo ha aperto, prima di decidere se passare o bloccare.

Questo è anche il motivo per cui l'Application Firewall integrato (l'interruttore in Impostazioni di sistema) è un animale diverso da pf, non un front-end per esso. La guida di Apple lo descrive solo in termini in entrata: "può proteggere il tuo Mac da contatti indesiderati avviati da altri computer" e funziona consentendoti di "selezionare app e servizi e specificare se possono accedere attraverso il firewall". Per-app, sì, ma solo per le connessioni in entrata e solo attraverso il meccanismo specifico che Apple ha creato per quell'unico lavoro. Risponde a una domanda diversa da "cosa sta inviando la mia app".

Tre modi per filtrare il traffico su un Mac e cosa sa realmente ciascuno
ApproccioVede IP/portaSa quale appGestisce gli IP rinominati/ruotatiPuò richiedere all'utenteDirezione
pf (pfctl)SÌNONo: risolto una volta in fase di caricamentoNOO per regola
Firewall applicazione (Impostazioni di sistema)No (attivazione/disattivazione a livello di app)SÌN / ANOSolo in entrata
Filtro dei contenuti dell'estensione di reteSÌSì, tramite l'oggetto flussoSì, valutato in base al flusso in tempo realeSì, tramite l'app basata su di essoIn uscita e in entrata

Niente di tutto ciò rende pf inutile. Se utilizzi un Mac come router leggero, devi rifiutare un intervallo notoriamente errato a livello di kernel indipendentemente dal processo che lo richiede o vuoi capire cosa fanno le funzionalità VPN e di condivisione Internet di Apple sotto il cofano, pf è lo strumento giusto e unico per quel lavoro e pfctl -s rules / -s info sono il modo giusto di vederlo. Ciò che non avrebbe mai fatto è rispondere alla domanda che la maggior parte delle persone si pone: quale delle mie app sta parlando con chi, in questo momento, e posso chiedermelo prima che arrivi una nuova.

Il ruolo di FireAI e di 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 è il prodotto di HisnLabs: un firewall con IA che funziona direttamente sul Mac. Mostra in linguaggio chiaro ogni connessione che le tue app effettuano e ti lascia decidere cosa esce dal tuo Mac — la sua IA lavora in locale, quindi il tuo traffico non viene mai inviato a noi né a nessun altro. Il team di ricerca sulla sicurezza di HisnLabs è quello che mantiene affidabili queste decisioni: cataloga quali domini sono semplice telemetria e quali un servizio reale, traccia il Paese e la rete dietro una connessione e addestra il modello locale (la funzione Autopilot) su schemi di traffico reali, senza che nulla lasci il tuo Mac.

Puoi leggere le scelte tecniche che ci stanno dietro, oppure provare FireAI per 17 giorni, su FireAI, di HisnLabs.

Fonti