NAT decide quale indirizzo di origine vede davvero il tuo server VPN
L'indirizzo del tuo portatile non raggiunge mai il server VPN. NAT lo riscrive all'ultimo salto e l'IP del tunnel viene assegnato dopo. Come confrontare le due estremità.
Immagini il server VPN che legge l'indirizzo del tuo portatile dal pacchetto e lo scrive in un registro. Quello che legge è ciò che l'ultimo salto NAT ha messo nell'intestazione esterna, e su un telefono usato come hotspot è spesso un indirizzo condiviso con centinaia di altri abbonati. L'indirizzo della tua macchina 192.168.x.x non attraversa mai internet in quell'intestazione, e l'indirizzo del tunnel viene assegnato dal server dopo che la connessione è già attiva. Quindi, quando il registro del server e ip addr sul portatile non coincidono, nessuno dei due è sbagliato; descrivono livelli diversi di una stessa sessione.
Tre indirizzi, e solo uno è nel registro
La confusione nasce dal ridurre tre indirizzi a uno. Ognuno ha un proprietario diverso, vive in un'intestazione diversa e raggiunge il server per un percorso diverso.
| Address | Who assigns it | Where it sits | Visible to the VPN server |
|---|---|---|---|
Device address, e.g. 192.168.1.24 | Your router via DHCP | Outer header, before translation | No, rewritten in place |
| Translated address and port | Router, ISP CGNAT, or both | Outer header, after translation | Yes, this is the tuple it logs |
Tunnel address, e.g. 10.8.0.6 | The VPN server itself | Inner header, after decapsulation | Yes, but it chose it |
Solo la riga centrale è sconosciuta al momento della connessione. Il server la scrive nella sua tabella dei peer, nel file di stato o nel log dei flussi a seconda del demone: WireGuard la chiama endpoint, un file di stato di OpenVPN la etichetta come Real Address e strongSwan la riporta come host remoto dell'IKE_SA. Quel valore viene aggiornato ogni volta che arriva un pacchetto da un'altra fonte, quindi cambia senza che nessuno riavvii nulla.
La riga in basso è ciò che le persone leggono erroneamente come un'affermazione di identità. Segna uno slot nella configurazione del server, non una persona, perché il server l'ha scelto dal proprio pool. Due utenti possono ricevere lo stesso indirizzo di tunnel in giorni diversi, e uno può tenerne due da due dispositivi.
Perché la tupla registrata cambia mentre il tunnel resta attivo
La traduzione degli indirizzi è una tabella con un timer, non un'associazione permanente. Un router domestico conserva la mappatura UDP per un po' dopo l'ultimo pacchetto, un gateway dell'operatore ricicla le porte secondo il proprio calendario, e un telefono che passa da Wi-Fi a LTE torna con una fonte completamente diversa. I valori predefiniti di conntrack su Linux sono un buon riferimento qui: nf_conntrack_udp_timeout è di 30 secondi e la variante per lo streaming è di 120, quindi un tunnel silenzioso può perdere la mappatura molto prima che l'utente se ne accorga.
Il tunnel sopravvive perché il protocollo autentica il peer, non l'indirizzo. WireGuard è senza stato dopo l'handshake, quindi ogni pacchetto autenticato aggiorna l'endpoint memorizzato e il rilegamento si sana al pacchetto successivo; per questo esiste persistent-keepalive = 25, per mantenere calda la mappatura durante l'inattività. Il --float di OpenVPN fa lo stesso lavoro e consente a un client autenticato di riprendere da un nuovo indirizzo e una nuova porta. Nelle build 2.4 e 2.5 dove float è disattivato per impostazione predefinita, un rilegamento reimposta la sessione e il client si riconnette.
IPsec ci arriva con più parti mobili. IKEv2 rileva la traduzione confrontando gli hash di origine e destinazione nei payload di rilevamento NAT, passa all'incapsulamento UDP 4500 e segue i keepalive fino alla nuova tupla. Quando i keepalive sono bloccati, la SA resta attiva sulla carta mentre il traffico in una direzione si ferma in silenzio.
Cosa può attribuire il server e cosa no
Il mito che vale la pena uccidere è che la traduzione ti nasconda all'operatore. Cambia l'etichetta, non l'osservazione. Un gateway dietro il NAT dell'operatore vede lo spazio 100.64.0.0/10 o un indirizzo pubblico condiviso da molti abbonati, e può comunque legare il flusso a un soggetto di certificato, una chiave pubblica WireGuard, un indirizzo di tunnel assegnato, contatori di byte e una finestra temporale. Niente di tutto ciò ha bisogno del tuo indirizzo LAN.
I limiti vanno anche nell'altra direzione. Un indirizzo condiviso in un registro indica un gateway, non una famiglia; due sessioni dallo stesso indirizzo tradotto su porte diverse sono dispositivi diversi; lo stesso indirizzo in due giorni diversi può essere due abbonati non correlati se la porta è stata riciclata. Un server che registra solo le chiavi dei peer non può associarne una a un cliente senza il database degli account, e un server che registra solo indirizzi non può distinguere un portatile da un telefono dietro lo stesso router.
Confronta le due estremità invece di indovinare
Per chiarire cosa è successo, cattura la stessa connessione alle due estremità nello stesso momento e confronta la tupla, non l'indirizzo. Sul client, prima di qualsiasi traduzione:
ss -uapn 'dport = :51820'
ip -4 route get 203.0.113.10
wg show wg0 endpoints
Poi leggi la voce di traduzione sul router o sul gateway CGNAT, e ciò che arriva infine al server:
conntrack -L -p udp --dport 51820
tcpdump -ni eth0 udp port 51820
Tre schemi spiegano la maggior parte delle discrepanze. La porta di origine sul server differisce dalla porta locale mentre la destinazione coincide: traduzione di porte ordinaria. L'indirizzo di origine sul server appartiene a un blocco ISP che non è il tuo: almeno un livello NAT aggiuntivo. I pacchetti si fermano dopo un periodo di inattività e riprendono con una nuova porta: la mappatura è scaduta, non è un guasto di routing. Se i timestamp sono distanti più di un secondo o due, stai confrontando due tentativi diversi.
Dove la differenza rompe le cose
Le interruzioni che sembrano guasti del server di solito iniziano qui. Una regola di accesso fissata al tuo indirizzo di casa fallisce dopo che il lease dell'ISP cambia. Una regola fail2ban che corrisponde a un indirizzo tradotto blocca tutti gli abbonati dietro quel gateway insieme. Un peer site-to-site con un indirizzo remoto fisso smette di rinnovare le chiavi dopo che un collegamento mobile cambia. Il protocollo del tunnel andava bene; l'ipotesi sulla tupla esterna no.
La stessa confusione compare sul lato server. Se la scatola VPN stessa è dietro NAT servono un port forwarding e un percorso di inoltro funzionante; la guida all'inoltro di strongSwan copre quel caso per IPsec. Un server raggiungibile solo su un indirizzo privato non vede mai la tupla tradotta che i suoi client presentano, e questo è un problema diverso dai client che vengono tradotti.
Esegui questi quattro controlli in ordine e fermati al primo che fallisce:
- Cattura alle due estremità contemporaneamente; conferma che porta di origine, porta di destinazione e timestamp corrispondano.
- Leggi l'elenco dei peer del server per l'indirizzo che tiene ora, non quello che ti aspettavi.
- Controlla la tabella conntrack o NAT per la voce e la sua durata residua.
- Conferma che l'indirizzo dell'interfaccia del tunnel sul client corrisponda a quello assegnato dal server, non all'indirizzo LAN.
Se le due catture concordano sulla tupla e il tunnel fallisce ancora, la traduzione non è il tuo problema; passa all'handshake e alla tabella di routing dentro il tunnel.