Il client OpenVPN si blocca quando il suo server gira sullo stesso host
Due istanze di OpenVPN su un solo host si contendono la stessa porta locale e la stessa tabella di routing. Fissa la porta, separa i dispositivi e controlla quale tabella vince.
Avevo una macchina da laboratorio che accettava un tunnel da un sito remoto e componeva anche verso una rete del fornitore. Il profilo in uscita funzionava da settimane. Dopo l'aggiunta del server in entrata, quello in uscita si è connesso e poi ha smesso di far passare traffico nel giro di secondi, oppure ha rifiutato di avviarsi con un errore di indirizzo già in uso. I file di configurazione non erano cambiati; l'host aveva semplicemente acquisito un secondo processo OpenVPN con la propria opinione su porte e route.
Il guasto non è casuale e non è un problema di autenticazione. Due demoni su una macchina competono per lo stesso socket locale e per la stessa tabella di routing, e chi si avvia o si riconnette per ultimo tende a vincere. Sapere quale di queste due collisioni hai decide dove guardare per primo.
Leggi il sintomo al contrario
Inizia da quando il tunnel muore. Un errore di bind all'avvio punta al lato in ascolto: qualcosa possiede già quella porta, e OpenVPN rifiuta di avviarsi invece di condividerla. Un tunnel che sale e poi tace punta al routing, perché una route installata dall'altra istanza può trascinare i pacchetti della connessione esterna fuori dal loro percorso.
Entrambi i casi producono la stessa lamentela dell'utente, ed è per questo che i cicli di tentativi e gli script di watchdog non riparano nulla. Riconnettono il client nello stesso conflitto. La prima domanda utile è se il processo è ancora in esecuzione quando il traffico si ferma.
Un socket e un dispositivo per istanza
Un server in ascolto lega la propria porta; anche un client in uscita ha bisogno di una porta locale per il suo traffico incapsulato. Quando entrambi vivono sullo stesso host, il comportamento predefinito del client può entrare in collisione con la porta del server. La porta locale del client può essere fissata, e il binding può essere saltato dove il peer non richiede una porta di origine fissa:
lport 1195
nobind
dev tun1Quei numeri sono esempi, non un requisito. Ciò che conta è che il client smetta di contendersi la porta del server e che ogni istanza ottenga un dispositivo tunnel separato. Due demoni che condividono tun0 sovrascrivono lo stato del dispositivo l'uno dell'altro anche quando le loro porte differiscono, quindi un dispositivo per tunnel non è facoltativo.
nobind appartiene al lato client. Un server deve comunque legare e ascoltare, quindi non copiare la riga nella configurazione del server e non disattivare il binding su un client il cui peer filtra su una porta di origine fissa.
Scegli un solo proprietario per la route predefinita
Solo una connessione può installare una route predefinita. Se entrambi i profili reindirizzano tutto il traffico, la seconda connessione sostituisce silenziosamente la prima, e la prima sembra rompersi. O mantieni il tunnel in uscita separato e spingi solo i prefissi del fornitore, oppure gli dai una tabella di routing separata.
ip rule add from 10.9.0.2 table 120
ip route add default dev tun1 table 120
ip route get 10.9.0.2Gli indirizzi e il numero di tabella sopra sono segnaposto. Subito dopo aver aggiunto la regola, conferma che l'indirizzo del server VPN stesso si risolva ancora tramite la tabella normale; una tabella che cattura il trasporto esterno rompe il tunnel che doveva proteggere, e il ciclo di riconnessione che segue sembra un provider inaffidabile.
Per una configurazione che deve sopravvivere a riconnessioni e riavvii, un namespace di rete è il confine più solido. Il secondo client gira nel proprio namespace con le proprie interfacce e route, e vengono esposti solo i servizi che devono attraversare. L'host mantiene una route predefinita, e una riconnessione del namespace non può riscriverla.
Verifica con la tabella, non con la riga di stato
Un client che segnala di essere connesso dimostra solo il proprio canale di controllo. Cattura lo stato di routing prima e dopo ogni connessione, poi chiedi al kernel quale dispositivo userebbe una destinazione reale:
ip route show
ip route get 10.40.0.20
ss -lunp | grep 1194Se il dispositivo selezionato per l'indirizzo del fornitore cambia quando parte il secondo tunnel, hai la collisione di route. Se entrambi i processi compaiono sulla stessa porta locale, hai la collisione di socket. Correggere la prima senza la seconda sposta solo il guasto alla riconnessione successiva.
Scrivi porte, dispositivi, tabelle e proprietario della route nel runbook dell'host. Altrimenti la prossima persona che aggiunge un terzo tunnel riscoprirà la stessa collisione, e l'unica prova visibile sarà una connessione che funziona finché il demone di qualcun altro non si riavvia.