Interruttore di sicurezza pf di macOS per OpenVPN: regole che si chiudono
Un insieme di regole pf blocca il traffico diretto mentre il tunnel è abbassato. Mantieni il percorso del client verso il suo server, poi dimostra il blocco con il tunnel spento.
Su macOS, un interruttore di sicurezza vale quanto la politica del filtro pacchetti che gli sta dietro, e pf è il pezzo che applica quella politica. La politica deve fare due cose opposte insieme: lasciare che il client raggiunga il suo server perché un tunnel possa esistere, e fermare tutto il resto dal uscire direttamente. La maggior parte delle regole pubblicate riesce nella seconda e dimentica la prima, così la macchina perde connettività invece di guadagnare protezione. La versione che funziona nomina l’endpoint, il resolver e il tunnel, e nient’altro.
Cosa può decidere un filtro pacchetti, e cosa no
pf guarda interfacce, indirizzi, numeri di protocollo e porte, e si ferma lì. Non sa mai quale processo ha aperto un socket, quindi un permesso scritto per un programma diventa un permesso per ogni programma che può raggiungere la stessa porta. È così che un’eccezione UDP generosa riporta un interruttore di sicurezza a una rete normale. Il blocco consapevole dell’applicazione appartiene al client o a un’estensione di sistema, non a questo file.
Il filtro non crea nemmeno rotte. Quando il client cade, la rotta predefinita può ancora puntare a un tunnel morto, e pf trasforma tutto ciò in pacchetti bloccati invece di un ritorno silenzioso al Wi-Fi. Il blocco è il risultato voluto, non un guasto da aggirare.
L’ordine decide l’esito più spesso del testo della regola. Senza quick, pf continua a valutare dopo una corrispondenza e vince l’ultima regola corrispondente, quindi un passaggio ampio in fondo annulla le eccezioni accurate sopra di esso. Marcare i passaggi con quick rende definitiva la prima corrispondenza, che è ciò che un autore di politiche di solito intende.
Leggi prima i fatti su interfaccia ed endpoint
Le interfacce wireless non sono numerate allo stesso modo su ogni Mac, e il dispositivo del tunnel riceve un numero che può cambiare tra un avvio e l’altro. Una regola che nomina un dispositivo inesistente fallisce in fase di analisi, il che è rumoroso e facile da cogliere, mentre una regola che nomina il dispositivo esistente sbagliato viene analizzata pulitamente e consente traffico che volevi fermare.
Raccogli i fatti mentre il client è connesso, perché il dispositivo del tunnel esiste solo allora. Ti servono l’interfaccia che tiene la rotta predefinita, il dispositivo creato dal client, e l’indirizzo e la porta del server a cui si collega. È proprio quest’ultimo valore che la maggior parte delle regole omette, e ometterlo è il motivo per cui un insieme copiato blocca il proprio tunnel.
route -n get default
ifconfig -l
scutil --nc list
Il primo comando nomina l’interfaccia che vince ora, il secondo elenca ogni dispositivo che il kernel conosce, e il terzo mostra le configurazioni VPN che il sistema può avviare. Annota quelle risposte, poi leggi l’indirizzo e la porta del server dalla configurazione del client stesso.
Scrivi l’insieme di regole intorno al percorso del tunnel
Il file qui sotto nega per impostazione predefinita e riammette cinque cose: loopback, il dispositivo del tunnel, il percorso del client verso il suo server, il resolver usato prima che esista il tunnel, e i due scambi che mantengono utilizzabile un collegamento wireless. I nomi delle interfacce e l’indirizzo del server vengono dalla tua macchina, quindi sostituisci i valori che hai confermato. Anche il numero del tunnel non corrisponderà al tuo.
set skip on lo0
block all
pass out quick on utun0
# maintain this line when the server address changes
pass out quick on en1 inet proto udp to 203.0.113.10 port 1194
# only the resolver the client uses before the tunnel exists
pass out quick on en1 inet proto udp to 192.0.2.53 port 53
pass out quick on en1 inet proto udp from any port 68 to any port 67
pass out quick on en1 inet proto udp to 224.0.0.251 port 5353
La riga DHCP esiste perché un Mac chiede un indirizzo prima di averne uno, quindi la richiesta esce dalla porta 68 verso la porta 67 senza un indirizzo di origine utilizzabile. La riga multicast permette al sistema di giudicare se vale la pena usare il collegamento wireless, e rimuoverla produce una macchina che segnala nessuna connessione su una rete funzionante. La riga dell’endpoint è ciò che permette a OpenVPN di raggiungere il suo server; senza di essa, block all scarta la stretta di mano esterna e il tunnel non sale mai. La riga del resolver è più stretta di un permesso DNS generale, perché nomina un indirizzo e una porta invece di ogni query che fa la macchina.
Quelle eccezioni per endpoint e resolver sono le due che devono esistere; tutto il resto resta bloccato. Se il client chiama un indirizzo letterale, togli la riga del resolver e mantieni quella dell’endpoint. Se l’indirizzo del server cambia, aggiorna quella riga prima della connessione successiva, oppure riempi una tabella pf dall’hook del client stesso e fai corrispondere invece la tabella.
Abbassa il tunnel, poi riavvia
Analizza prima di caricare, perché un errore di sintassi costa poco in una prova a secco e molto in una sessione remota. Poi carica il file, abilita il filtro se era spento, e rileggi ciò che è realmente in vigore. La rilettura non è cerimonia: un’altra ancora può aggiungere regole che non hai scritto, quindi confronta l’insieme stampato con il tuo file.
sudo pfctl -n -v -f /etc/pf.conf
sudo pfctl -f /etc/pf.conf
sudo pfctl -e
sudo pfctl -s rules
sudo pfctl -s Anchors
sudo pfctl -a <anchor> -s rules
sudo pfctl -s info
Con le regole caricate, abbassa il tunnel e prova a caricare una pagina. Il traffico ordinario dovrebbe fermarsi, e dovrebbe restare fermo dopo che la macchina dorme e si sveglia, perché è in quella transizione che lo stato obsoleto rientra. Riconnettiti e conferma che il traffico riprende senza toccare l’insieme di regole. Se un browser funziona ancora con il tunnel abbassato, una regola è più ampia di quanto pensassi, e la rilettura di solito la nomina.
Il riavvio è la parte che la gente salta. macOS legge /etc/pf.conf all’avvio, ma leggere il file non è lo stesso che abilitare il filtro, quindi un insieme di regole che ora funziona può restare inattivo dopo un riavvio. Esegui poi sudo pfctl -s info e conferma che la riga di stato riporti il filtro come abilitato.
Mantieni onesti l’uscita e il percorso di riavvio
Un insieme di regole che blocca tutto può anche chiuderti fuori da una macchina che amministri da remoto. Modifica da una sessione locale quando puoi, tieni il file precedente accanto al nuovo, e conosci il ripristino prima di averne bisogno. I comandi sotto disattivano il filtro e ricaricano la copia che hai tenuto, ed è la sequenza da eseguire da una console, non dal tunnel che hai appena tagliato. Un ripristino in cinque secondi batte una regola intelligente ogni volta.
sudo pfctl -d
sudo pfctl -f /etc/pf.conf.previous
sudo pfctl -s rules
La persistenza richiede un demone di avvio che esegua pfctl -e e carichi il tuo file all’avvio. Trattalo come qualsiasi altro compito privilegiato: percorsi assoluti, un registro che puoi leggere dopo, e una prova su una macchina che puoi raggiungere fisicamente. Un demone che fallisce in silenzio lascia la macchina non protetta e dall’aspetto normale.
Documenta le lacune, a cominciare da un secondo client VPN che crea il proprio dispositivo di tunnel. Le tue regole nominano una sola interfaccia di tunnel, quindi la seconda resta bloccata o viene catturata da una regola ampia aggiunta in seguito. Le interfacce di tethering e hotspot compaiono solo a volte e meritano la stessa nota. Nessuna di quelle lacune è un motivo per saltare la politica; sono le condizioni in cui vale ancora.