I kill switch falliscono in una direzione che le persone non si aspettano: sono costruiti per bloccare il traffico mentre il tunnel è giù, e i pacchetti che costruiscono il tunnel sono essi stessi traffico. È tutto qui il difetto. Un insieme di regole che scarta tutto ciò che non esce dal tunnel scarta anche l’handshake che dovrebbe sollevarlo, quindi il client riprova in un ciclo e l’errore viene attribuito alla fase che viene controllata per prima. Prima di ampliare un firewall, stabilite quale delle tre fasi viene negata: la risoluzione del nome, il pacchetto esterno verso il peer o la risposta che torna indietro.

Come dipendono l’uno dall’altro il tunnel e il suo stesso trasporto

Leggete un client VPN come due stati di rete che condividono un solo percorso di socket. Prima che il tunnel esista, il client apre un socket sull’adattatore fisico e invia frame cifrati all’indirizzo e alla porta del peer. Solo quando quello scambio riesce crea il dispositivo di tunnel e installa le rotte. Un kill switch è una politica sul secondo stato, scritta così ampiamente che vale per entrambi.

Le regole basate sull’interfaccia sono la forma abituale: accettate ciò che esce attraverso tun0 o wg0, scartate il resto del percorso in uscita. Quella formulazione non può esentare la connessione del client stesso al server, quindi un’implementazione corretta aggiunge quell’eccezione in modo esplicito, e lo fate anche voi quando scrivete regole a mano. Le regole per applicazione su Windows e macOS evitano parte di questo facendo corrispondere un processo invece di un’interfaccia, ma il processo deve comunque uscire prima che il tunnel esista.

Tre fasi, nell’ordine in cui accadono

La prima fase è la risoluzione. Quando il profilo memorizza un nome host invece di un indirizzo letterale, il client ha bisogno di una risposta DNS prima di poter inviare qualcosa. Un profilo che punta il DNS al resolver del tunnel crea uno stallo: il resolver è raggiungibile solo attraverso il tunnel che la ricerca dovrebbe abilitare. Risolvere fuori dal tunnel, o fissare l’endpoint a un indirizzo, elimina l’ambiguità.

La seconda fase è il pacchetto esterno, che deve sopravvivere prima all’instradamento e poi al firewall, in quest’ordine. wireguard-tools si occupa della metà di instradamento per WireGuard marcando i propri pacchetti e aggiungendo una regola di policy perché saltino la rotta predefinita appena installata; la pagina di manuale di wg-quick descrive quella regola e la tabella che usa. Ricostruite quell’instradamento a mano, o lasciate che un secondo strumento riscriva le regole, e i pacchetti marcati possono essere rimandati nel tunnel che dovrebbero stabilire.

La terza fase è il percorso di ritorno. Un handshake senza risposta non è prova di uno scarto in uscita; è altrettanto compatibile con una regola in ingresso del server o con un dispositivo NAT che ha dimenticato la mappatura. Separatele prima di toccare il client.

What you seeStageWhere to look
The client log repeats a resolve step and no packets appear on the wire1, name lookupResolver path while the tunnel is down
The send counter on the physical adapter stays flat2, routingPeer route and policy rules
The send counter rises and a firewall drop counter rises2, firewallRule order, mark, and interface match
Packets leave and nothing comes back3, return pathServer input rules, NAT, listening port

I client registrano il sintomo che rilevano, non la fase che ha fallito, quindi la tabella è di solito più rapida del log.

I contatori decidono più in fretta dei log

Su Linux, nft list ruleset o iptables -vnL OUTPUT stampa un contatore di pacchetti per regola. Connettetevi una volta, lasciate che fallisca, poi rileggete i contatori. Una regola il cui contatore si è mosso è una regola che l’handshake ha colpito; se non si è mosso nulla da nessuna parte, il pacchetto non ha mai raggiunto il firewall. Ho visto un insieme di regole scartare il proprio handshake, e solo i contatori lo hanno detto.

Per distinguere «mai raggiunto il firewall» da «mai uscito dall’host», osservate l’interfaccia stessa. ip -s link show dev wlan0 riporta i pacchetti inviati, e tcpdump -ni wlan0 udp port 51820 mostra i frame. Se resta piatto mentre il client riprova, il guasto è sopra netfilter: una rotta del peer mancante, una regola di policy che punta a un dispositivo che non esiste ancora, o un errore di socket che il client inghiotte.

Provate le eccezioni con indirizzi di documentazione come 203.0.113.10, così che una svista non possa sondare l’host di qualcun altro.

Un’eccezione dell’endpoint obsoleta si legge come un’interruzione del server

La versione più fuorviante compare dopo che l’indirizzo del peer cambia: un servizio di indirizzi dinamici lo ha spostato, l’host è stato ricostruito, o l’indirizzo di uscita della vostra rete è diverso. L’eccezione nomina ancora il vecchio indirizzo, quindi i pacchetti verso quello nuovo finiscono sulla regola di scarto. La stessa configurazione funzionava ieri, ed è per questo che le persone iniziano diagnosticando il server.

Un nome host dentro una regola di firewall non vi salva. In nftables il nome viene risolto al caricamento dell’insieme di regole, quindi fissa l’indirizzo che esisteva in quel momento e diventa obsoleto come uno letterale. La soluzione duratura è aggiornare l’eccezione quando l’endpoint cambia e mantenerla stretta: un indirizzo di peer, una porta di trasporto. Un intervallo abbastanza ampio per sopravvivere a un cambio di indirizzo lo è anche per lasciar uscire traffico non correlato.

Quando il kill switch gira sull’host del server

La stessa dipendenza esiste all’altro capo, e lì è più facile trascurarla. Se la macchina che funge da server VPN esegue anche un client desktop con kill switch, o un profilo firewall copiato da un portatile, le sue regole di scarto valgono per il servizio che termina i tunnel. Le risposte all’handshake di un client vengono scartate, quindi ogni client non riesce a connettersi mentre il server sembra sano e la sua interfaccia di tunnel resta inutilizzata.

Quell’host ha bisogno di tre accettazioni strette prima dello scarto: la porta di ascolto sull’interfaccia fisica, l’interfaccia di tunnel per il traffico decifrato e l’inoltro dal tunnel verso ciò che i client devono raggiungere. Leggete l’insieme installato con nft list ruleset, iptables -S, o pfctl -sr prima di cambiare qualsiasi cosa, e ricordate che un insieme di regole salvato sopravvive al riavvio, quindi un errore lì sopravvive al processo che lo ha fatto.

Ordine di ripristino che tiene la macchina chiusa

Lavorate dall’interno verso l’esterno dal profilo. Leggete l’indirizzo e la porta del peer che usa il client, confermate che il nome host si risolva senza il tunnel, poi aggiungete un’eccezione per quell’indirizzo e quella porta solo sull’adattatore fisico. Riconnettetevi e osservate il contatore di invio; un handshake completato è il segnale che la seconda fase è riparata.

Lasciate il resto della politica di scarto al suo posto durante i test. Un controllo innocuo è tentare una connessione a un indirizzo di documentazione non correlato e confermare che scade ancora, il che mostra che il kill switch funziona invece di essere disattivato. Stringete l’eccezione quando il tunnel è stabile, e non lasciate un’autorizzazione permanente a tutto per il binario del client solo perché è comodo.

Se il tunnel sale e l’applicazione continua a fallire, le fasi rimanenti non sono questa: DNS diviso, MTU e instradamento per applicazione producono ciascuno un tunnel connesso con traffico rotto, e ciascuno ha un primo controllo diverso.

Articoli correlati