I log recenti dei container spesso terminano con una lamentela Read-only file system su /proc/sys/net/ipv4/route/flush, e quella riga si prende la colpa di un tunnel che può essere perfettamente sano. La scrittura che sta dietro punta a una voce del kernel che non fa più nulla di utile ora che la cache delle rotte IPv4 è sparita. Dentro un container /proc/sys viene montato in sola lettura, quindi il reindirizzamento viene rifiutato prima che arrivi un valore e la shell stampa quel rifiuto. Un tunnel funzionante può stampare questo avviso finché la vecchia riga resta nello script, e --privileged non rende mai significativa la scrittura.

Cosa cercava di svuotare lo script

Gli script di connessione più vecchi terminavano con una pulizia della cache: scrivere un valore in un file di controllo del kernel e chiedere allo stack IPv4 di scartare la sua cache di routing, così una nuova rotta del tunnel veniva scelta senza attendere la scadenza delle voci obsolete. Il file era indirizzato sotto /proc/sys/net/ipv4/, il che rendeva l'operazione un reindirizzamento della shell e non un comando di routing. Il kernel 3.6 ha rimosso quella cache, e con essa la ragione d'essere del flush. Nulla nel percorso dati attuale dipende da quella scrittura.

La voce stessa è sopravvissuta come file legacy di sola scrittura, quindi uno script che vi scrive ancora raggiunge un percorso reale e un controllo dei permessi reale. Su un host la scrittura restituisce successo e non cambia nulla. In un container lo stesso reindirizzamento incontra un /proc/sys in sola lettura e fallisce con EROFS, che la shell stampa come messaggio di file system in sola lettura. Su kernel dove il percorso è davvero assente la formulazione diventa No such file or directory, e la conclusione non cambia.

I due errori dicono cose diverse, e la differenza vale la pena tenerla chiara. Read-only file system significa che il kernel ha raggiunto una voce e ha rifiutato la scrittura; No such file or directory significa che la voce è sparita. Nessuno dei due messaggi riferisce sul dispositivo del tunnel, sulle rotte o sulla risoluzione dei nomi, quindi nessuno può giustificare più privilegi.

È l'ordine che fa sembrare il messaggio causale. Uno script di connessione installa rotte, cambia lo stato dell'interfaccia e riscrive la risoluzione dei nomi prima di arrivare alla pulizia finale, quindi l'ultima riga stampata è quella che la gente cita anche quando ogni passaggio importante ha restituito successo. Un tunnel che si stabilisce e trasporta traffico mentre stampa questo avviso corrisponde esattamente al meccanismo sopra.

Controllate il mount e la rotta prima di aggiungere privilegi

Tre letture separano un avviso cosmetico da un guasto reale: se lo script installato porta ancora la riga, come viene montato /proc/sys e dove va davvero il traffico dell'applicazione. Eseguitele nello stesso namespace del container o sull'host dove è apparso l'avviso, perché un controllo su una macchina non correlata risponde a un'altra domanda.

grep -n 'ipv4/route/flush' /usr/share/vpnc-scripts/vpnc-script
findmnt -no OPTIONS /proc/sys
ip -4 route get 10.20.5.10

La risposta di grep è più debole di quanto sembri, perché una corrispondenza prova che la riga è presente, non che venga eseguita senza protezione; uno script mantenuto può portare la scrittura dentro una guardia che la salta. findmnt -no OPTIONS /proc/sys risolve il mount direttamente, e ro in quell'output significa che ogni scrittura sotto quel punto viene rifiutata, qualunque cosa faccia lo script. La ricerca della rotta mostra poi se la destinazione che serve all'applicazione si risolve tramite l'interfaccia del tunnel o tramite il gateway predefinito del container. Una ricerca che sceglie il gateway predefinito significa che il tunnel è salito e nulla vi è instradato, il che è un problema di routing e non di privilegi.

Da dove arriva davvero la correzione

La correzione mantenuta vive nello script e non nei flag del container. L'vpnc-script upstream ha cambiato il modo in cui gestisce questa operazione, quindi confrontate la copia dentro l'immagine con l'upstream attuale e aggiornate tramite il pacchetto o la build dell'immagine che la fornisce. Un file modificato a mano dentro un container in esecuzione non è verificabile e non sopravviverà alla prossima build.

--privileged è documentato come concessione di tutte le capacità più un ampio accesso ai dispositivi, una grande concessione per un messaggio che non cambia nulla, quindi nominate la capacità mancante se ne manca davvero una. Dopo l'aggiornamento, ripetete la ricerca della rotta e lasciate che un'applicazione usi il tunnel, perché un log silenzioso e una connessione funzionante sono risultati separati.

Articoli correlati