WireGuard: due mezze rotte contro 0.0.0.0/0 in wg-quick
Due intervalli /1 coprono gli stessi indirizzi di /0, ma wg-quick li instrada diversamente. Controllate regole di policy, marcature e percorso dell’endpoint prima di modificare.
Due prefissi /1 coprono esattamente gli stessi indirizzi IPv4 di un singolo /0, e questa uguaglianza vale solo all’interno dell’elenco dei prefissi consentiti del peer. Smette di valere nel momento in cui lo strumento di configurazione decide come instradare, perché Linux wg-quick tratta un prefisso predefinito come caso speciale e non come aritmetica. Il ramo speciale installa una tabella dedicata, due regole di policy, una marcatura di socket e impostazioni di percorso inverso che una coppia di mezze rotte non riceve mai. Quando quindi un proxy o un browser smette di funzionare dopo la modifica, i prefissi sono la parte meno interessante del cambiamento.
L’elenco dei prefissi non è tutta la configurazione
AllowedIPs svolge due compiti insieme, e solo uno riguarda la copertura. Per WireGuard stesso l’elenco è routing a chiave crittografica: decide quali destinazioni vengono cifrate verso un peer e quali indirizzi di origine quel peer può usare. Per wg-quick lo stesso elenco funge anche da specifica delle rotte, e la rotta che produce dipende da quale ramo l’elenco incontra. Una copertura identica su due forme di elenco diverse non dice quindi nulla su uno stato dell’host identico.
La configurazione predefinita vi toglie questa decisione dalle mani, perché Table è automatico per impostazione predefinita e lo strumento sceglie dove finiscono le rotte. Un altro gestore di rete, un wrapper di distribuzione o un valore Table personalizzato cambiano di nuovo il risultato, ed è per questo che un consiglio scritto per un host può sembrare sbagliato sul successivo.
Che cosa aggiunge il ramo predefinito oltre a una rotta
Una voce /0 manda wg-quick nel suo percorso di rotta predefinita: una tabella di routing separata riceve la rotta predefinita, una regola di policy vi manda il traffico non marcato, una seconda regola mantiene autorevoli le rotte più specifiche della tabella principale, e l’interfaccia riceve una marcatura firewall sul proprio socket. Quella marcatura è il guardiano del loop. I datagrammi cifrati che portano il traffico del tunnel escono con la marcatura impostata, così la regola che indirizza tutto il resto nel tunnel non inghiotte i pacchetti di trasporto del tunnel stesso.
Una coppia di voci /1 prende invece il percorso di rotta ordinario. Due rotte finiscono nella tabella configurata, e nulla della macchineria circostante compare, non perché sia superflua ma perché quel percorso di codice non è mai stato imboccato.
Dove i due assetti divergono
La divergenza si mostra prima come ricorsione. Con le mezze rotte nella tabella principale, l’indirizzo di trasporto del peer stesso cade dentro un prefisso del tunnel, quindi il pacchetto che dovrebbe portare il tunnel corrisponde a una rotta che punta dentro il tunnel. Qualcosa deve esentarlo: una rotta host per l’endpoint corrente, una marcatura applicata a mano o una regola specifica dell’interfaccia. Una rotta host funziona finché l’indirizzo dell’endpoint non cambia, cosa che accade con endpoint basati su DNS, client in roaming e configurazioni con più peer.
In secondo luogo, tutto ciò che ragiona sulle marcature cambia comportamento. Un proxy trasparente che reindirizza le connessioni localmente crea nuovi socket le cui marcature e origini differiscono dal flusso client originale, e le regole di policy generate dal ramo predefinito erano parte di ciò che ha separato quei flussi. Leggere la connessione in uscita del proxy stesso è un esercizio diverso dal verificare se la destinazione originale è raggiungibile.
Leggete le regole e le marcature prima di modificare
Catturate lo stato attuale mentre il tunnel è sano, poi di nuovo dopo la modifica, e confrontate i due dump invece di ragionare dal file di configurazione. Includete le regole di policy, ogni tabella, la marcatura dell’interfaccia e gli endpoint registrati.
ip rule show
ip -4 route show table all | grep -E 'default|wg1'
wg show wg1 fwmark
wg show wg1 endpoints
Se la prima riga dell’output ha perso la regola del traffico non marcato e la tabella dedicata è vuota, il ramo predefinito non è in esecuzione e nessuna aritmetica dei prefissi ripristinerà i suoi effetti. Una marcatura zero su un’interfaccia che prima ne portava una è lo stesso segnale, visibile in un solo valore.
Provate la perdita del tunnel prima di distribuire
Se la disposizione a mezze rotte è la scelta deliberata, deve fornire esplicitamente i pezzi mancanti: un percorso dell’endpoint che sopravvive ai cambi di indirizzo, il comportamento previsto quando il tunnel cade e il trattamento equivalente per IPv6. Scriveteli come requisiti invece di scoprirli durante un’interruzione. Poi provate il guasto, perché un tunnel completo che ricade silenziosamente sul collegamento fisico è peggio di uno che smette di funzionare.
sudo ip -4 route add 198.51.100.20/32 via 192.0.2.1 dev eth0
ip -4 route get 198.51.100.20
sudo wg-quick down wg1
La ricerca della rotta dovrebbe risolvere l’endpoint dall’interfaccia fisica senza attraversare il tunnel, e portare l’interfaccia giù dovrebbe lasciare l’host nello stato promesso dal progetto. Un proxy che funziona dopo la sostituzione dimostra che lo stato dell’host generato contava; non dimostra che la prevenzione dei loop e il comportamento a interfaccia abbassata siano sopravvissuti alla modifica.