Aggiungi una regola per il traffico VPN nella catena FORWARD, esegui la richiesta dalla stessa macchina Linux e il contatore resta a zero. La regola è probabilmente corretta. Il pacchetto non ha mai preso quella strada, perché una richiesta generata sulla macchina stessa non viene inoltrata da essa. Seguire la vita del pacchetto dal socket al cavo spiega perché, e dove dovrebbe stare invece la regola.

Scopri dove è nato il pacchetto

L’ordine degli hook di Netfilter separa tre casi, e solo uno di essi coinvolge FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

Un’applicazione locale parte nel percorso OUTPUT, perché il kernel ha già stabilito che il pacchetto nasce qui e non è mai candidato all’inoltro. Creare un tunnel non cambia questa classificazione; il tunnel è un dispositivo da cui il pacchetto può uscire, non una fase che trasforma l’uscita locale in transito.

Due pacchetti, una storia

Una volta attivo il tunnel, il pacchetto interno dell’applicazione e il pacchetto esterno cifrato sono oggetti diversi. Il pacchetto interno porta la destinazione e il carico scelti dall’app. Il pacchetto esterno porta il testo cifrato all’indirizzo e alla porta del peer, ed è quello che attraversa davvero l’interfaccia fisica.

La tua politica riguarda uno dei due, e scegliere quello sbagliato è una causa comune di regole che sembrano non fare nulla. Una regola che corrisponde all’indirizzo esterno del peer vede ogni pacchetto del tunnel allo stesso modo, qualunque cosa faccia l’applicazione all’interno. Una regola che corrisponde a una destinazione interna vede il traffico che ti interessa, e si attiverà solo se quel pacchetto raggiunge l’hook su cui hai installato la regola.

Gli spazi dei nomi spostano il confine

Un container rende tutto più difficile senza cambiare il principio. La richiesta dell’applicazione è uscita locale dentro lo spazio dei nomi di rete del container. L’host riceve quel traffico su un’interfaccia Ethernet virtuale e può inoltrarlo, quindi una regola FORWARD sull’host può avere senso anche se il processo che ha generato la richiesta non ha mai toccato la catena OUTPUT dell’host.

Prima di scegliere un hook, stabilisci dove vivono davvero l’insieme di regole e il tunnel. Un tunnel dentro il container, un tunnel sull’host con il container instradato attraverso di esso e un tunnel in uno spazio dei nomi separato sono tre topologie diverse con tre diverse posizioni delle regole. Leggi le regole dentro lo spazio dei nomi che possiede il dispositivo, non solo in quello predefinito.

Chiediti se ti serve davvero un mark

Se l’obiettivo è inviare un prefisso di destinazione attraverso il tunnel, una rotta per quel prefisso può bastare. Controlla prima le rotte effettive, incluso tutto ciò che il server ha spinto: una rotta predefinita reindirizzata manda molto più traffico attraverso la VPN della politica ristretta che avevi in mente, e nessuna quantità di mark farà coincidere il risultato con l’intenzione.

La classificazione serve quando la decisione dipende da qualcosa che una rotta non può esprimere, come la sorgente, l’utente o il processo. Per il traffico ricevuto, il mark in PREROUTING funziona. Per il traffico locale, il mark deve avvenire in una fase di uscita che possa innescare una nuova ricerca di rotta dopo che il mark è impostato. Con nftables è una catena di tipo route sull’hook di uscita; una normale catena di filtro in uscita imposterà il valore e lascerà la rotta invariata.

Con iptables, l’equivalente vive nella disposizione mangle OUTPUT, e vale lo stesso requisito: la decisione di instradamento deve essere rivista dopo che il mark esiste. Poi una regola di policy deve consumare il mark e puntare a una tabella che contenga una rotta utilizzabile. Impostare un mark conntrack è una terza operazione, separata; memorizza un valore sul flusso e non mette da sola quel valore sul pacchetto corrente perché l’instradamento lo legga.

Verifica la ricerca e il contatore insieme

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

L’indirizzo e il mark sono illustrativi, e le due interrogazioni di rotta rispondono a domande diverse. La seconda chiede cosa farebbe il kernel se un pacchetto portasse quel mark; non dimostra che il tuo insieme di regole ne assegni uno. Trattala come un test di ipotesi, non come prova che la politica funzioni.

Poi esegui una richiesta innocua e osserva due cose insieme: il contatore sull’hook scelto e l’uscita che il pacchetto ha realmente preso. Se il contatore si muove e il pacchetto esce altrove, il mark o la tabella sono sbagliati. Se nessuno dei due si muove, il pacchetto non raggiunge affatto quell’hook, e la domanda successiva è lo spazio dei nomi o il percorso.

Infine, limita il test a ciò che il meccanismo può esprimere. Una rotta per un indirizzo non diventa una politica permanente per un servizio i cui indirizzi ruotano. Decidi prima l’ambito dei pacchetti, poi verifica se il progetto di instradamento e mark può mantenere quell’ambito dopo una riconnessione.

Articoli correlati