L’ESP in uscita senza risposta non significa che la VPN sia morta
L’ESP protegge una direzione per associazione e non riscontra nulla. Allineate la conversazione interna e la SA in ingresso prima di definire il server insensibile.
Avete catturato il traffico sull’host IPsec, visto partire pacchetti ESP, non visto tornare nulla e concluso che il lato remoto è guasto. La cattura non sostiene questa conclusione. L’ESP protegge una direzione di una conversazione e non riscontra nulla a livello IP, quindi l’assenza di ESP di ritorno può significare che l’applicazione non aveva nulla da dire con la stessa facilità con cui può significare che il tunnel è morto. Leggete lo scambio interno e lo stato del lato ricevente prima di accusare una delle due estremità.
Il mito: ogni pacchetto protetto merita una risposta
L’ESP non è un protocollo richiesta-risposta. Cifra e autentica ciò che la politica seleziona, e il ricevente convalida, decifra e consegna quel pacchetto interno senza generare un pacchetto proprio. Una richiesta UDP che la destinazione ignora, o un echo ICMP che la politica in ingresso scarta, producono silenzio in entrambe le direzioni come risultato corretto. Trattare quel silenzio come guasto di trasporto vi manda a cercare un guasto di rete che non è mai esistito.
Ciò che una cattura unidirezionale dimostra davvero è che lo stack del mittente ha cifrato qualcosa in quel punto di osservazione. Nulla sull’arrivo, e nulla sull’intenzione di rispondere. La domanda utile non è «perché non c’è risposta» ma «che cosa avrebbe dovuto produrre la conversazione interna».
Due SA, due SPI, una conversazione
Le associazioni di sicurezza IPsec sono unidirezionali, quindi un normale scambio protetto ha un’associazione in ingresso e una in uscita con identificatori separati e stato indipendente. Cercare il traffico di ritorno tramite lo SPI del pacchetto in uscita è quindi un errore di categoria, perché ogni risposta viaggia sotto la SA in uscita propria del peer con il suo SPI. Appaiate invece il gruppo tramite selettori di traffico e indirizzi del peer.
Il rinnovo delle chiavi complica il quadro per qualche secondo alla volta, poiché lo stato vecchio e quello sostitutivo possono sovrapporsi. Se il sintomo è iniziato attorno a un rinnovo delle chiavi, raccogliete identificatori di associazione e marche temporali insieme, non solo il nome della connessione.
Che cosa deve fare il ricevente prima che qualcosa risponda
| Stage | What to look at | Wrong conclusion if skipped |
|---|---|---|
| Sender encrypts | outbound SA packet counter | "the tunnel is up" |
| Peer receives | inbound SA counter and replay window | "the peer is down" |
| Inner delivery | target host or service logs | "routing is broken" |
| Application replies | the app's own trace | "the reply was dropped" |
| Protected return | the peer's outbound SA | "ESP only works one way" |
Ogni riga fallisce in modo indipendente e ogni guasto ha un proprietario diverso, per questo una sola cattura non può distinguerli. Il contatore in ingresso è l’unica prova diretta dell’arrivo, perché un pacchetto che fallisce l’autenticazione o il controllo di replay viene scartato senza alcuna risposta. Un peer il cui contatore in ingresso non si è mosso non vi sta quindi inviando alcuna informazione sulla sua politica.
La consegna è un passo separato dalla decifratura. Lo stato può essere valido e il pacchetto comunque scartato in seguito da una politica in ingresso o da una rotta che non include la destinazione interna, quindi verificate se l’host di destinazione ha visto testo in chiaro invece di supporre che un contatore pulito significhi che il pacchetto è andato dove volevate.
L’ESP nativo non è UDP
L’ESP nativo è il protocollo IP 50, che non è né TCP né UDP e non ha alcuna porta. Una regola del firewall che consente IKE su UDP 500 non dice quindi nulla sul percorso dati, e un filtro scritto attorno alle porte può lasciare che un tunnel negozi e poi scartare tutto ciò che viene trasportato al suo interno. Provate il percorso dati da solo, nella modalità che avete realmente osservato.
Dietro un NAT la forma cambia: il carico protetto viaggia dentro UDP, di solito sulla porta 4500, come definisce la RFC 3948. Registrate la modalità attiva prima di scrivere qualsiasi regola, perché un dispositivo sul percorso può trattare l’ESP nativo e l’ESP incapsulato in UDP in modo del tutto diverso, e alcuni middlebox consentono uno e scartano l’altro.
Leggete contatori che appartengono a questo incidente
Su un host strongSwan, swanctl --list-sas riporta contatori di pacchetti e byte per associazione in entrambe le direzioni, il che basta a separare «mai arrivato» da «arrivato e non risposto». Su Linux, /proc/net/xfrm_stat conta guasti aggregati come stato mancante, politica mancante ed errori di protocollo. Quei totali si accumulano dall’avvio e appartengono a un solo spazio dei nomi di rete, quindi un numero grande non è un’attribuzione.
Prendete due letture attorno alla finestra dell’incidente nello spazio dei nomi corretto e confrontate le differenze, altrimenti appiccicate gli errori della settimana scorsa al ticket di questo pomeriggio. Scrivete lo spazio dei nomi ed entrambe le marche temporali nel ticket, così il prossimo lettore può riprodurre il confronto invece di fidarsi di un totale.
Nominate la fase, non il sospetto
Una conclusione utile dice dove si è fermato il pacchetto: mai ricevuto, ricevuto e scartato, consegnato ma senza risposta, oppure risposto e perso al ritorno. Ciascuno di questi punti indica un proprietario diverso e un comando successivo diverso. «Nessuna risposta dal server VPN» schiaccia quattro guasti distinti in una frase che la cattura non ha mai giustificato.
Mantenete le catture strette e tenete lo stato grezzo del kernel fuori dai ticket, perché può trasportare materiale di chiavi che non ha nulla da fare fuori dall’host. Le differenze dei contatori e le marche temporali sono le parti che vale la pena consegnare alla persona successiva.