Il client ottiene un indirizzo, il server risponde ai ping e, ciò nonostante, ogni pagina va in timeout. La maggior parte delle persone inizia a modificare il profilo del client a questo punto, il che di solito è fatica sprecata: una volta che il tunnel è attivo, il server deve comportarsi come un router. Tre condizioni devono valere contemporaneamente prima che un pacchetto esca e torni una risposta, e il sintomo è identico qualunque manchi.

Perché un tunnel funzionante non ha ancora una via d’uscita

Il kernel deve inoltrare i pacchetti tra le interfacce, cosa disattivata per impostazione predefinita sulla maggior parte delle distribuzioni Linux. Il traffico deve essere tradotto verso un indirizzo a cui il mondo esterno possa rispondere, a meno che ogni router a monte conosca già la rotta di ritorno alla sottorete del tunnel. Il percorso di inoltro del firewall deve consentire il traffico in entrambe le direzioni, comprese le risposte.

Ognuna di queste può essere corretta separatamente, ed è qui la trappola. Attivare l’inoltro senza una regola di traduzione lascia i pacchetti uscire con una sorgente privata e senza via di ritorno. Aggiungere la traduzione senza una regola di inoltro lascia il kernel scartare il pacchetto un passo più tardi.

Quindi provate i tre livelli invece del client, e cambiatene uno alla volta perché il risultato significhi qualcosa.

L’inoltro è un interruttore del kernel da rendere persistente

Controllate il valore attuale prima di modificarlo, poi impostarlo e confermate che la modifica ha avuto effetto.

sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
sysctl net.ipv4.ip_forward

Il primo comando riporta il valore attuale, il secondo lo imposta a runtime e il terzo dimostra che la scrittura ha funzionato. Il valore a runtime scompare al riavvio successivo, ed è per questo che una sessione funzionante può rompersi dopo una manutenzione senza alcuna modifica di configurazione.

Rendetelo permanente in un file sotto /etc/sysctl.d/, poi applicate quel file invece di riavviare per scoprirlo. Su FreeBSD l’equivalente è net.inet.ip.forwarding, con gateway_enable=YES in rc.conf per la persistenza. Un dispositivo che segnala l’inoltro disattivato spiega un’intera classe di segnalazioni «i pacchetti arrivano e non torna nulla». Controllate l’impostazione anche dopo ogni aggiornamento, perché un kernel ricostruito o un’immagine del dispositivo sostituita possono azzerarla senza dirlo a nessuno.

Scegliete masquerade o un indirizzo di traduzione fisso

Con un indirizzo esterno dinamico, masquerading è la forma corretta più semplice. Nominate la sottorete del tunnel come sorgente e l’interfaccia esterna come uscita.

iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o eth0 -j MASQUERADE

Con un indirizzo pubblico statico, la traduzione della sorgente verso quell’indirizzo esatto è più prevedibile e più facile da verificare.

iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -j SNAT --to-source 198.51.100.10

La seconda forma porta una trappola di manutenzione: un indirizzo codificato a mano che poi cambia mantiene il tunnel funzionante mentre l’accesso a internet si ferma in silenzio. Usate masquerade oppure aggiornate la regola ogni volta che il provider vi sposta. Anche l’interfaccia conta, perché un router che condivide il proprio tunnel a monte deve tradurre attraverso quel tunnel e non attraverso la WAN fisica.

La tabella dei filtri è la terza porta

Inoltro e traduzione possono essere entrambi corretti mentre il pacchetto muore ancora nella tabella dei filtri. ufw è un colpevole frequente: la sua politica di inoltro arriva come DROP, e il resto della configurazione può sembrare perfettamente corretto mentre quell’unica impostazione uccide il traffico. Alzarla è una decisione di sicurezza deliberata e non una casella di controllo.

iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

La prima regola consente il traffico nuovo dal tunnel verso l’esterno, e la seconda solo le risposte di ritorno. Restringete entrambe alla sottorete del tunnel e alla destinazione voluta, perché un’accettazione indiscriminata sull’interfaccia del tunnel trasforma la VPN in un punto di uscita aperto per chiunque possa autenticarsi.

Un tunnel in bridge richiede un’altra risposta. L’indirizzo appartiene al bridge, non alla porta fisica, quindi asservire l’interfaccia rimuove l’indirizzo che aveva prima e l’host sembra irraggiungibile finché il bridge stesso non ne riceve uno, cosa che dhclient br0 può fornire. Quel guasto sembra un problema VPN ed è un problema di livello due. Controllate l’indirizzo del bridge stesso prima di toccare il firewall, perché una modifica del filtro non può riparare un host che non ha più un indirizzo da cui inviare.

Dove guardare quando una pagina non si carica mai

Fate ping all’indirizzo del tunnel del server per provare che il tunnel esiste. Poi eseguite un traceroute dal client verso un indirizzo pubblico e leggete dove si ferma: sul server il pacchetto arriva ma non viene inoltrato né tradotto; oltre il server il problema è a monte e fuori dalle vostre mani.

ping -c 3 10.9.0.1
traceroute -n 198.51.100.10

Il primo comando prova che il tunnel trasporta traffico fino al server stesso, e il secondo mostra quanto lontano arriva un pacchetto verso l’esterno. Una traccia che termina all’indirizzo del tunnel indica inoltro o traduzione sul server, mentre una traccia che si ferma un salto dopo indica il provider o la rotta di ritorno del router a monte.

Sul server, osservate l’interfaccia esterna mentre un client carica una pagina. Traffico che esce con un indirizzo sorgente privato significa che manca la traduzione, e nessuna risposta significa che il percorso di inoltro o la rotta di ritorno a monte lo sta scartando.

Se i client remoti devono raggiungere anche host sulla LAN del server, ricordate che la LAN ha bisogno di una rotta di ritorno alla sottorete del tunnel. È routing e non traduzione, ed è il passo che più spesso si dimentica quando la via per internet finalmente funziona.

Articoli correlati