Il «File exists» di OpenVPN su una rotta non è un problema di file
Il messaggio proviene dalla tabella delle rotte del kernel, non dal file system. Leggi la voce che possiede già il prefisso prima di modificare la politica della LAN.
Inizia da dove appare il messaggio. Un client si connette, il tunnel sale, poi il registro segnala che il comando di aggiunta rotta di Linux è fallito con File exists. Nulla in quella frase si riferisce a un certificato, a una chiave o a un file di configurazione, anche se le parole lo suggeriscono. Il kernel sta descrivendo la sua tabella delle rotte, e il prefisso che hai chiesto di installare ha già una voce.
Segui la sequenza del client stesso: cosa ha richiesto, cosa conteneva già la tabella, chi ha messo quella voce lì, e solo dopo cosa cambiare. Ogni passo elimina un possibile proprietario.
Cosa stava effettivamente chiedendo il client
Prima dell'errore, il client registra la rotta che intende aggiungere, di solito come destinazione, maschera di rete, gateway e talvolta come metrica o tabella. Quella riga è la richiesta. L'errore che segue è la risposta del kernel, e i due vanno letti fianco a fianco.
journalctl -u openvpn-client@office -b --no-pager | grep -nE 'route|File exists'
openvpn --config /etc/openvpn/client/office.ovpn --verb 4 --log /tmp/ovpn.log
Un codice di uscita diverso da zero dell'helper delle rotte è meno informativo del testo sottostante, perché risposte diverse del kernel producono un codice diverso da zero. Conserva il messaggio esatto; la distinzione tra una voce esistente e un gateway irraggiungibile decide quale delle sezioni successive si applica.
Leggi la rotta esistente, non solo l'indirizzo
Cercare nella tabella lo stesso quadruplo puntato non basta. Un oggetto rotta è identificato dalla famiglia di indirizzi, dalla tabella, dal prefisso di destinazione, dalla metrica, dal protocollo e dal dispositivo di uscita, e le voci che condividono un prefisso possono coesistere legittimamente quando questi attributi differiscono. A collidere è l'oggetto intero, non il testo.
ip -4 route show table all | grep -F '10.40.'
ip -4 route show match 10.40.0.0/16
ip -4 route get 10.40.0.5
L'ultimo comando risponde a una domanda diversa dalle prime due: non cosa esiste, ma quale voce il kernel sceglierebbe per quella destinazione in questo momento. Entrambe le viste sono utili, e divergono abbastanza spesso da meritare un confronto prima di concludere qualcosa. La discrepanza tra loro è il caso interessante, non un errore di arrotondamento.
Annota il prefisso, la tabella, la metrica e il dispositivo accanto alla richiesta fallita. Se la voce esistente ha gli stessi attributi e lo stesso salto successivo, hai un'istruzione duplicata e non un problema di routing.
Quattro proprietari che un prefisso può avere
Le rotte connesse provengono da un indirizzo assegnato e vengono ricreate dal sistema ogni volta che quell'indirizzo esiste. Un client DHCP o un gestore di connessioni installa rotte come parte del proprio ciclo di vita. Un altro client VPN potrebbe già portare lo stesso prefisso. E un hook o uno script locale può aggiungerne una che nient'altro conosce.
Ogni proprietario richiede una correzione diversa. Una rotta connessa non è tua da cancellare; rimuoverla può interrompere l'accesso locale prima che il tunnel sia utilizzabile, e il kernel la rimetterà. Una rotta di proprietà di un gestore va modificata tramite quel gestore, non con un ip route del manuale che la prossima riconnessione annulla.
Un'interfaccia conservata rende più facile la stessa confusione. Quando il dispositivo del tunnel sopravvive a una riconnessione, le rotte installate da codice di configurazione personalizzato possono essere ancora presenti alla seconda esecuzione, così uno script che presume uno stato pulito fallisce la seconda volta e funziona la prima. O cancelli deliberatamente la voce obsoleta o rendi idempotente il codice di configurazione.
block-local risponde a un'altra domanda
Quando un profilo manda tutto il traffico attraverso il tunnel, il client deve decidere cosa succede alla rete locale. Il flag block-local cambia questa decisione instradando la LAN locale attraverso il tunnel mantenendo l'eccezione documentata per il gateway della LAN; è una scelta di politica del traffico con conseguenze visibili sulla raggiungibilità.
Non spiega perché l'aggiunta di una rotta abbia restituito un errore di voce esistente, e adottarlo come riparazione universale nasconde il conflitto reale dietro un cambio di politica. Se le tue risorse locali diventano irraggiungibili dopo una modifica del profilo, questo flag è una delle prime cose da controllare; se l'aggiunta di una rotta fallisce, non è la risposta.
Trattalo come una decisione su quali destinazioni restano locali, presa deliberatamente e messa per iscritto. Non è un interruttore da provare quando il registro sembra allarmante.
Chiudi il cerchio: rimuovi il duplicato alla sua origine
Una volta che sai quale proprietario detiene la voce, rimuovi l'istruzione duplicata dove è definita. Può essere una riga route nel profilo, un push dal server o un hook che non deve più essere eseguito.
ip -4 route show match 10.40.0.0/16
ip -4 route get 10.40.0.5
journalctl -u openvpn-client@office -b --no-pager | tail -n 15
Poi riconnettiti e conferma tre cose: il tunnel sale, la destinazione prevista si risolve nel percorso desiderato, e l'errore sparisce senza che ne appaia uno nuovo al suo posto. Un registro pulito con un percorso scelto male non è una correzione.
Se il prefisso indica la LAN locale da un lato e una rete remota dall'altro, il problema è una sovrapposizione di indirizzi e non un duplicato, e nessuna cancellazione renderà entrambi i significati veri insieme. Quel caso richiede un piano diverso per una delle due reti. Decidi quale lato verrà rinumerato prima di toccarne uno.