Pubblicare una porta di client VPN dietro CGNAT: lista di controllo
Una sola regola NAT di destinazione dà connessioni semiaperte. Fissa l’indirizzo del tunnel, traduci in entrambi i sensi e conferma il percorso della risposta prima di provare.
Metti un servizio su un portatile dietro un NAT di livello operatore, indirizza quel portatile verso un VPS tramite una VPN e nessuno all’esterno può raggiungerlo. Aggiungi una regola NAT di destinazione sul VPS e ottieni qualcosa di peggio del silenzio: le connessioni si aprono e poi si bloccano. La risposta non manca, esce dalla route predefinita del client stesso, il che significa che il server non la vede mai. Esegui questi cinque controlli in ordine e fermati al primo che non regge.
Conferma che il server inoltrerà quanto meno
Spunta questa casella prima di scrivere una sola traduzione. Una regola DNAT per un pacchetto che il kernel rifiuta di inoltrare viene accettata dal parser delle regole e poi scartata dal percorso di inoltro, il che produce un timeout che sembra un problema di firewall.
sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
Impostarlo in un kernel in esecuzione non è lo stesso che impostarlo tra un riavvio e l’altro. Scrivi net.ipv4.ip_forward=1 in un file sotto /etc/sysctl.d/, esegui sysctl --system e poi rileggi il valore invece di fidarti che il file sia stato raccolto. Un container che gestisce il proprio spazio dei nomi di rete ha bisogno dello stesso valore dentro quello spazio, non solo sull’host.
Se la rilettura è ancora zero, fermati qui. Nulla più in basso funzionerà.
Fissa l’indirizzo del tunnel prima che qualche regola vi faccia riferimento
Il pool assegna indirizzi in ordine di connessione, quindi una regola scritta per il lease di oggi può puntare in silenzio a un altro client la settimana prossima. Lega l’indirizzo all’identità del certificato invece che all’ordine di arrivo.
client-config-dir /etc/openvpn/ccd
ifconfig-push 10.77.0.14 10.77.0.13
Quella coppia è l’estremità client e l’estremità peer di un tunnel punto a punto, con il server legato al nome comune del certificato. In una topologia a sottorete il secondo valore viene invece letto come netmask, quindi scrivi la forma che corrisponde alla topologia in uso. Poi ricollega il client e leggi l’indirizzo sul client stesso, perché la visione del server sul pool non è prova di ciò che il client ha configurato.
Se l’indirizzo cambia dopo una riconnessione, fermati. Una regola NAT che segue un obiettivo mobile fallirà a intermittenza e non ti insegnerà nulla.
Traduci in entrambi i sensi
La traduzione di destinazione invia il pacchetto in ingresso al client. La traduzione di origine è ciò che fa rispondere il client al server invece che al mittente originale, ed è la regola che la gente omette.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 29443 -j DNAT --to-destination 10.77.0.14:29443
iptables -t nat -A POSTROUTING -d 10.77.0.14 -p tcp --dport 29443 -j SNAT --to-source 10.77.0.13
Senza la seconda regola il client risponde tramite il suo uplink ISP, quindi il peer remoto vede un indirizzo di origine con cui non ha mai parlato, mentre il server non tiene alcuna voce di tracciamento per la risposta. L’osservatore esterno vede una stretta di mano che si completa a metà, ed è esattamente il sintomo che manda la gente a cercare un bug del firewall che non esiste.
Rileggi entrambe le regole con iptables -t nat -S e conferma che il nome dell’interfaccia sia quello che porta l’indirizzo pubblico. Su un host che già filtra con nftables, scrivi la traduzione in una catena NAT di nftables della famiglia di indirizzi corrispondente invece di mescolare strumenti.
Lascia passare la tabella dei filtri
Le tabelle NAT riscrivono le intestazioni; non concedono permessi. Con una policy DROP predefinita il flusso inoltrato ha bisogno della propria accettazione, più la direzione di ritorno che la maggior parte delle policy copre già con una regola established,related.
iptables -A FORWARD -i eth0 -o tun0 -p tcp --dport 29443 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Controlla la policy della catena FORWARD prima di aggiungere qualsiasi cosa, perché l’ordine di un DROP anticipato decide se la tua regola verrà mai consultata. Su un host la cui filtrazione vive in nftables, aggiungi la regola equivalente all’hook forward della tabella inet e conferma che la catena di base veda davvero il traffico inoltrato e non solo l’input locale. Se un contatore di pacchetti della nuova regola resta a zero mentre i contatori NAT salgono, il pacchetto viene scartato prima della tua regola. È il segnale per leggere l’ordine delle catene, non per aggiungere una seconda copia della stessa regola.
Provalo da una rete esterna
Prova da una rete non correlata. Una sonda da un’altra macchina sulla stessa LAN può passare attraverso il supporto NAT a forcina e non esercitare mai il percorso che usa un client remoto, quindi un risultato verde lì dimostra la cosa sbagliata.
tcpdump -ni any port 29443
conntrack -L | grep 29443
Esegui la cattura sul server e sul client allo stesso tempo. La cattura del server mostra se il pacchetto tradotto esce verso il tunnel; quella del client mostra se la richiesta arriva e dove è indirizzata la risposta. Una voce di traduzione in conntrack -L dimostra che la regola ha corrisposto, e la sua assenza dimostra che il pacchetto non ha mai raggiunto la catena NAT.
Gli scanner di porte sono prove deboli. Riportano la porta come chiusa finché l’applicazione non è legata e in ascolto, quindi usa una connessione reale al servizio reale. Quando alla fine funziona, tieni l’esposizione su quell’unica porta: inoltrare SSH o un pannello di amministrazione perché la prima regola sembrava scomoda è una decisione molto più grande che pubblicare un servizio.