All’avvio, un’unità socket che collega un indirizzo VPN fisso può fallire prima che il tunnel lo abbia assegnato, e il servizio dietro non parte mai. Due interruttori sembrano correzioni e risolvono metà diverse di quel problema. FreeBind consente a systemd di creare l’ascoltatore mentre l’indirizzo è ancora assente. After= ordina solo i processi, quindi cambia quando le cose partono senza far arrivare l’indirizzo prima.

Due problemi diversi, due interruttori diversi

Il primo problema è un errore di collegamento: il kernel rifiuta l’ascolto su un indirizzo che l’host non possiede, quindi l’unità socket fallisce subito e il servizio non viene mai attivato. Il secondo problema è un errore di disponibilità: l’indirizzo alla fine esiste, ma qualcosa tenta di usarlo prima che il tunnel trasporti traffico. FreeBind affronta il primo e non fa nulla per il secondo. Le direttive di ordine non affrontano direttamente nessuno dei due, perché decidono solo cosa parte e in quale sequenza. Nominare l’errore che si ha davvero è tutta la decisione.

Verificate quale dei due avete dal journal, non dalla descrizione del servizio. Un errore di collegamento nomina un indirizzo e segnala che non può essere assegnato. Un errore di disponibilità compare di solito più tardi, come timeout o connessione rifiutata vista dall’altro lato, con un’unità socket perfettamente sana nei log.

FreeBind: l’ascoltatore esiste prima dell’indirizzo

FreeBind dice al kernel di consentire un collegamento a un indirizzo non locale, così systemd può creare il socket in ascolto all’avvio e passarlo all’applicazione ogni volta che l’applicazione parte. È il senso dell’attivazione tramite socket, e la ragione per cui il socket può sopravvivere al servizio dietro di esso.

[Socket]
ListenStream=
ListenStream=10.8.0.1:8443
FreeBind=yes

L’assegnazione vuota cancella le voci di ascolto ereditate dall’unità del fornitore prima che venga aggiunta la nuova, il che impedisce a un ascoltatore wildcard residuo di rispondere su ogni interfaccia. Sostituite l’indirizzo e la porta con i vostri e verificate l’unità effettiva, non solo il file drop-in. Usate un drop-in con il nome dell’unità invece di modificare un file del pacchetto sul posto, perché il prossimo aggiornamento del pacchetto sovrascriverà la modifica e non lascerà traccia dell’intenzione. Poi applicatelo con la procedura di ricarica e riavvio che l’unità socket si aspetta.

La documentazione dei socket di systemd descrive il comportamento IPv4 e IPv6 dietro questa opzione, e il dettaglio importante è che si applica al collegamento e non all’instradamento. Nulla in essa assegna un indirizzo o avvia una VPN. FreeBind è un permesso concesso all’ascoltatore, non un sostituto dell’interfaccia.

After= e Wants=: l’ordine non è disponibilità

Ordine e requisito sono assi separati, e confonderli produce unità che partono nell’ordine giusto e falliscono comunque. After=vpn-client.service significa solo che, se entrambi i processi vengono avviati, questo attende che l’altro sia avviato. Non tira dentro la VPN e non attende che la VPN finisca di connettersi.

Le direttive di requisito come Wants= e Requires= gestiscono l’attivazione e differiscono in ciò che accade quando la dipendenza fallisce: una continua, l’altra si ferma. Nessuna delle due sa che cosa significhi un tunnel connesso. Un processo VPN può essere attivo senza indirizzo assegnato, oppure con indirizzo assegnato e senza rotta verso il peer, ed entrambi gli stati soddisfano la dipendenza. Se l’applicazione ha bisogno che l’indirizzo esista, modellate quella condizione esplicitamente invece di trattare l’avvio del processo come prova di disponibilità.

Controllate ciò che l’unità dichiara davvero con systemctl cat e systemctl show -p After -p Wants -p Requires. Drop-in da tre directory diverse possono aggiungere direttive che non avete mai scritto, e l’unità effettiva è l’unica cosa che systemd legge.

Ciò che network-online.target non fa

Un’unità ordinata dopo network-online.target attende che il gestore di rete dichiari la rete utilizzabile, il che è un punto di sincronizzazione all’avvio e non una condizione continua. Non dice nulla sul fatto che un tunnel specifico sia attivo, e non si attiverà di nuovo quando una VPN si riconnette a metà pomeriggio. Trattarlo come un monitor di riconnessione è la lettura errata più comune di quell’obiettivo.

Il progetto systemd documenta direttamente questa distinzione, e la conseguenza pratica è che tutto ciò che necessita di un indirizzo di tunnel deve possedere la dipendenza da sé. Un’unità che attende network-online e poi collega un indirizzo di tunnel è corretta solo quando il tunnel sale per primo per caso, il che è una coincidenza e non un progetto.

Verificate il ciclo di vita che avete scelto davvero

Verificate un avvio pulito, una richiesta dopo la comparsa dell’indirizzo e il comportamento dopo che la VPN cade e ritorna. Questi tre casi separano un ascoltatore funzionante da un servizio funzionante.

systemd-analyze verify myapp.socket
systemctl cat myapp.socket
ss -ltn "sport = :8443"

Il primo comando intercetta gli errori del file di unità prima di un riavvio, il secondo mostra l’unità unita e il terzo dimostra se l’ascoltatore esiste e su quale indirizzo. Un ascoltatore su un indirizzo wildcard dove vi aspettavate un indirizzo di tunnel è esattamente il residuo che il ListenStream vuoto doveva rimuovere. Ripetete il terzo comando dopo una riconnessione della VPN per vedere se l’indirizzo si è spostato.

Scegliete il ciclo di vita deliberatamente: o un ascoltatore collegato liberamente che attende il ritorno di un indirizzo stabile, o un servizio che si ferma con il tunnel e riparte al ripristino. Sono progetti diversi e falliscono in modi diversi. Poi mantenete la politica di accesso legata alle fonti e ai percorsi che intendevate, perché collegare un indirizzo di destinazione non richiede che i pacchetti accettati siano arrivati attraverso un’interfaccia fidata.

Articoli correlati