La risposta della VPN site-to-site non passa nel tunnel
Una risposta che salta il tunnel è una decisione di routing del lato remoto. Controllate la tabella degli host, i selettori e rp_filter, poi scegliete route o NAT.
Ho passato una mattina su un tunnel che saliva pulito e spostava traffico esattamente in una direzione: la filiale raggiungeva il file server in sede, e ogni connessione aperta dalla sede verso la filiale moriva al primo SYN. Le SA erano attive, i contatori del tunnel salivano, e l’handshake non è mai stato il problema. La risposta veniva instradata in un punto che il tunnel non copre, e quella scelta appartiene al lato remoto. Una VPN site-to-site trasporta solo i pacchetti che un host consegna al gateway, e ogni host fa quella scelta separatamente, in ogni direzione, dalla propria tabella di routing.
Le due direzioni sono instradate separatamente
IP non conserva memoria della direzione di una conversazione. Ogni host che invia un pacchetto esegue la propria ricerca del prefisso più lungo, sceglie un solo prossimo hop e dimentica la decisione. La richiesta e la risposta sono due pacchetti senza legame che appartengono per caso alla stessa connessione, e il tunnel è un hop che l’una o l’altra può usare o no. Nulla nello scambio IKE insegna al server remoto come raggiungere la vostra sottorete; la negoziazione concorda solo quali prefissi possono essere cifrati.
Quell’accordo è la seconda porta. Su strongSwan i selettori di traffico sono leftsubnet e rightsubnet, e un pacchetto la cui sorgente o destinazione cade fuori dalla coppia negoziata non viene cifrato, qualunque cosa dica la tabella di routing. Un prefisso instradato nel tunnel ma assente dai selettori è un guasto silenzioso a senso unico: la rotta sembra corretta, il pacchetto esce comunque in chiaro o viene scartato, e solo il log di charon protesta.
L’host remoto non sa nulla del vostro tunnel
Dentro la LAN remota la risposta è un pacchetto ordinario indirizzato al vostro client. L’host di destinazione non vede alcuna intestazione IPsec e non ha motivo di preferire il gateway VPN; cerca il vostro prefisso, non trova nulla di più specifico della sua rotta predefinita e la segue. Se la rotta predefinita punta a un firewall centrale, il firewall ha o non ha una rotta di ritorno nel tunnel. Quando non ce l’ha, ottenete uno scarto silenzioso, un ICMP unreachable o una risposta che esce dall’interfaccia verso internet e muore.
Una seconda interfaccia basta a rompere questo anche quando una rotta esiste. Un NAS con un link di gestione su un’altra VLAN, un server con un uplink di backup, una regola di policy che manda un intervallo di sorgenti in una seconda tabella: una qualsiasi di queste cose può catturare la risposta. Su Linux, ip rule show e ip route show table all mostrano regole e tabelle che l’elenco predefinito nasconde.
Leggete la decisione sulla macchina che invia la risposta
Interrogate il kernel prima di cambiare qualcosa, e dategli l’indirizzo di sorgente, perché le regole dipendenti dalla sorgente cambiano la risposta.
ip route get 10.10.5.10 from 10.20.30.15
ip rule show
ip route show table all
ss -tn state established "( sport = :445 )"
L’output indica l’interfaccia uscente e il prossimo hop. Se l’interfaccia non è quella rivolta al gateway VPN, avete trovato il difetto, e il lavoro che resta è scegliere dove deve stare la rotta. Un ping dal gateway qui dimostra poco: risponde con un indirizzo che l’host remoto sa collocare, non con l’indirizzo del vostro portatile.
Su Windows gli equivalenti sono Find-NetRoute -RemoteIPAddress 10.10.5.10 per la decisione e Get-NetRoute per la tabella. Una rotta aggiunta con New-NetRoute che porta una metrica più alta di quella predefinita perde in silenzio, quindi leggete la colonna della metrica, non la voce. Poi confermate con i pacchetti: tcpdump -ni any "host 10.10.5.10 and tcp port 445" sull’interfaccia LAN remota mostra la richiesta, e lo stesso filtro dal lato del tunnel mostra se è tornata una risposta. Richiesta visibile senza risposta significa che la risposta è stata instradata altrove o scartata; una risposta sull’interfaccia sbagliata vi dà il colpevole prima che tocchiate una rotta.
Quando il gateway del server non è l’endpoint della VPN
Molti siti mettono un firewall tra i server e il concentratore. Quel firewall inoltra la risposta, quindi ha bisogno di una rotta per il prefisso del vostro client che punti al gateway VPN, e di una policy di inoltro in entrambe le direzioni. I dispositivi con stato peggiorano le cose: la richiesta ha attraversato il firewall da un host LAN che ha permesso, la risposta ora arriva da un’altra direzione e la voce di tracciamento delle connessioni non corrisponde più, così il pacchetto viene scartato come non valido invece che negato. Ecco perché il log delle policy sembra vuoto mentre il traffico sparisce.
Il gateway ha un proprio secondo filtro. Il filtraggio del percorso inverso di Linux scarta i pacchetti la cui sorgente non è raggiungibile attraverso l’interfaccia da cui sono arrivati, ed è esattamente la forma di un percorso di ritorno asimmetrico legittimo. la guida all’inoltro di strongSwan chiede net.ipv4.ip_forward e un net.ipv4.conf.all.rp_filter allentato proprio per questo motivo. Un valore severo di 1 su uno dei due gateway rompe in silenzio una rotta corretta, e nstat -az mostra gli scarti se sapete dove guardare.
| Symptom | Where the reply is most likely lost |
|---|---|
| Gateway ping works, LAN host silent | Source address the far host cannot place in its table |
| SYN arrives, no SYN-ACK, tunnel counters flat | No route to the client prefix on the far host or its gateway |
| Reply counted on the internet-facing interface | Default route or policy rule on the far host |
| Firewall reports invalid state | Asymmetric path through a stateful device |
| Worked until a link failed over | New path is asymmetric, or rp_filter now rejects it |
Instradate o traducete, poi verificate in entrambe le direzioni
Le due riparazioni non sono equivalenti. Aggiungere una rotta mantiene intatto l’indirizzo del client, quindi le regole basate sulla sorgente, i log di audit e le applicazioni che registrano il chiamante continuano a funzionare; il prezzo è che ogni hop che prende la decisione ha bisogno della rotta, cioè più punti in cui sbagliare. Mascheramento sul gateway remoto riduce il percorso di ritorno a un solo hop, perché la risposta ora è indirizzata al gateway stesso, e nasconde quale client ha fatto cosa.
iptables -t nat -A POSTROUTING -o eth1 -s 10.20.30.0/24 -j MASQUERADE
Sceglietelo deliberatamente: appena i client appaiono come l’indirizzo del gateway, le ACL basate sulla sorgente smettono di distinguerli, e conntrack deve tenere la mappatura perché la risposta venga riscritta verso il tunnel. Se i selettori escludono ancora il prefisso del client, NAT non cambia nulla, perché la richiesta non è mai entrata nel tunnel.
Prima di dichiararlo risolto, confermate quattro cose in ordine: la rotta sull’host che invia la risposta, la rotta su ogni hop che la inoltra, i selettori che coprono entrambi i prefissi e una cattura che mostri la risposta entrare nel tunnel con la sorgente che vi aspettate. Poi ripetete il test dall’altro sito. Una direzione che passa è un progetto semiaperto, e la seconda direzione di solito fallisce per un motivo diverso da quello appena riparato.