Perché un secondo tunnel VPN rompe il primo?
Un secondo client VPN installa due rotte semi-predefinite e il primo tunnel si spegne: leggi quale rotta vince, poi separa per profilo, tabella o spazio dei nomi.
Installare un secondo client VPN per raggiungere una rete cliente è il modo abituale in cui tutto questo inizia, e il primo tunnel si spegne mentre entrambi i client riportano successo. Ogni client ha installato una rotta predefinita, la seconda era più specifica, e il kernel ora la segue per tutto tranne la connessione esterna del primo tunnel stesso. Niente è andato in crash e nessun profilo è sbagliato. Una rotta ne ha sostituita un'altra, e la soluzione è decidere quale tunnel deve possedere la predefinita.
Il sintomo: il secondo client vince in silenzio
OpenVPN: la sua opzione redirect-gateway def1 non sovrascrive 0.0.0.0/0. Aggiunge 0.0.0.0/1 e 128.0.0.0/1: insieme coprono ogni indirizzo IPv4, e ogni prefisso batte una predefinita semplice per lunghezza. La predefinita originale resta nella tabella e smette di essere usata per il traffico ordinario, e una rotta host verso il server VPN impedisce al tunnel di catturare i propri pacchetti esterni. Entrambi i client lo fanno, e il secondo si limita a installare la sua coppia più tardi.
Per questo il primo tunnel sembra morto invece che disconnesso. La sua interfaccia è attiva, il suo canale di controllo è vivo, e nessun traffico applicativo lo raggiunge più. Il reclamo opposto ha lo stesso push mancante: un telefono che si connette ma non invia nulla di solito parla con un server che non ha mai annunciato redirect-gateway, quindi il dispositivo conserva la propria predefinita e raggiunge solo il pool.
Scatta un'istantanea delle rotte prima e dopo la connessione del secondo client. Le due semi-rotte che compaiono nella tabella sono tutto il cambiamento, e spiegano entrambi i reclami. Nient'altro nella tabella deve muoversi perché il sintomo appaia. Per questo rimuovere il secondo client ripristina subito il primo.
Leggi quale tunnel vince davvero
Non dedurre il vincitore dall'ordine di avvio dei client né dall'icona nella barra delle applicazioni. Chiedi al kernel quale rotta userebbe per una destinazione fuori da entrambe le reti private, e leggi l'interfaccia restituita.
ip route show
ip route get 198.51.100.24
route print -4
Find-NetRoute -RemoteIPAddress 198.51.100.24
Le prime due sono la risposta Linux e le ultime due l'equivalente Windows. Eseguile mentre entrambi i tunnel sono attivi, poi disconnettine uno ed eseguile di nuovo. La differenza tra i due output è il fatto che serve prima di scegliere una soluzione, e richiede meno tempo che leggere il log di uno qualsiasi dei client.
Annota il risultato, inclusi il nome dell'interfaccia e il prefisso che ha corrisposto. Un ticket che dice che il secondo VPN ha rotto il primo è una descrizione del sintomo, non un'affermazione di routing su cui qualcuno possa agire. La ricerca la trasforma in un fatto che il prossimo ingegnere può riprodurre con un solo comando.
Windows: impedire a un profilo di possedere la predefinita
Windows conserva profili salvati, e il client integrato permette a uno di dipendere da un altro così che il primo salga automaticamente quando il secondo si connette. Il profilo connesso più di recente tende a mantenere la predefinita, quindi il proprietario pratico è l'ultima connessione e non la prima. Assegna a ogni profilo le proprie rotte push e attiva lo split tunneling per quello che non deve possedere la predefinita.
Set-VpnConnection -Name "Contoso" -SplitTunneling $true
rasdial Contoso
Lo split tunneling cambia questo: solo i prefissi spinti dal server finiscono nella tabella, il che lascia la predefinita al primo tunnel. Il progetto fallisce comunque se entrambi i server spingono una rotta predefinita, perché allora vince l'ultima connessione e nessuna impostazione lato client lo cambia. Correggi il push lato server o accetta un solo proprietario.
I profili attivati dalle applicazioni sono un'altra funzione e vale la pena conoscerla: un profilo Windows può avviarsi quando parte un eseguibile denominato, con filtri di traffico che decidono cosa trasporta. È un'impostazione di profilo e non una regola del firewall, e risolve un problema diverso dal conflitto di rotta predefinita.
Linux: tenere il secondo tunnel fuori dalla tabella principale
Eseguire due istanze di openvpn --config su una macchina mette entrambi i client nella stessa tabella, e tre opzioni li separano con isolamento crescente. La più leggera è impedire del tutto al secondo client di modificare la tabella, con route-nopull e rotte esplicite, o uno script route-up che installi solo ciò che intendi. Allora il secondo tunnel porta esattamente i prefissi che nomini e nient'altro. Allora decidi tu quali prefissi vanno dove invece di scoprirlo dopo.
Il policy routing è l'opzione intermedia. Una regola seleziona una tabella separata per un indirizzo sorgente o un marchio firewall, e quella tabella porta le rotte del secondo tunnel. Il filtro del percorso inverso è la trappola qui, perché una risposta che arriva su un'interfaccia diversa da quella che la tabella sceglierebbe viene scartata, quindi controlla l'impostazione rp_filter prima di concludere che il tunnel è rotto.
ip rule add from 10.44.7.0/24 table 100
ip route add default dev tun1 table 100
sysctl net.ipv4.conf.all.rp_filter
Gli spazi dei nomi di rete sono l'opzione più pesante e la più pulita. Avvia il secondo client dentro ip netns, dagli una coppia veth ed entra in quello spazio dei nomi per usarlo. Le interferenze spariscono perché ogni spazio dei nomi possiede le proprie tabelle invece di condividerne una, il che vale la configurazione extra quando entrambi i tunnel devono restare attivi per settimane.
Per applicazione, e il concatenamento come problema a parte
A volte solo un programma dovrebbe usare il secondo tunnel. Su Linux il policy routing per utente, cgroup o porta ottiene quel risultato, e una singola destinazione può essere fissata a un'interfaccia senza toccare affatto la predefinita. Un'applicazione che fissa il proprio socket a un'interfaccia non consulta mai la tabella di routing, quindi un launcher può continuare a usare l'adattatore fisico finché un indirizzo non viene scelto nelle sue impostazioni.
Il concatenamento è un'operazione diversa dall'eseguire due tunnel fianco a fianco. Concatenare A sopra B significa che l'indirizzo del server interno deve essere raggiungibile dall'interno del tunnel esterno. Il client esterno inoltre non deve scambiare i pacchetti cifrati del client interno per una fuga. Un client dentro una macchina virtuale è la versione rozza ma affidabile; entrambi su un solo host richiedono il lavoro di routing sopra più un percorso esterno verso il server interno che non entra mai nel tunnel interno.
Annota il proprietario della predefinita, l'elenco dei prefissi che porta ogni tunnel e il percorso DNS. Questi tre fatti trasformano il prossimo incidente in una consultazione invece che in un'indagine.