Due progetti, una sola applicazione HTTPS, e il pacchetto segue un percorso diverso in ciascuno. Un port forwarding cambia dove viene consegnato il pacchetto e lascia il resto com’è. Una VPN trasporta prima quel pacchetto dentro un altro pacchetto, così il listener dell’applicazione vede una sorgente diversa e un carico utile massimo più piccolo. La cifratura di cui si discute è presente in entrambi i casi, perché l’applicazione resta HTTPS; ciò che cambia è chi può aprire una connessione e cosa può osservare la rete in mezzo. Questa distinzione risolve la maggior parte delle domande pratiche.

La regola DNAT riscrive la destinazione e si ferma lì

Su un gateway Linux, pubblicare un servizio significa una regola nella catena PREROUTING della tabella nat, o l’equivalente in nftables. La regola corrisponde all’indirizzo e alla porta pubblici, poi riscrive la destinazione verso l’indirizzo privato dell’applicazione. Indirizzo sorgente, porta sorgente e carico utile restano intatti, e conntrack registra la mappatura così le risposte vengono riscritte in uscita. Il comportamento è il modello tradizionale di traduzione degli indirizzi descritto in RFC 3022.

sudo iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 443 \
  -j DNAT --to-destination 10.20.30.40:443
sudo iptables -t nat -L PREROUTING -n -v
sudo conntrack -L -p tcp --dport 443

Il listener dell’applicazione non viene mai a sapere che la connessione è arrivata tramite una traduzione. Vede l’indirizzo sorgente reale del client, utile per i registri di accesso e i limiti di velocità, e risponde all’indirizzo privato perché conntrack inverte la mappatura. Nulla su quel percorso decifra o ricifra: TLS continua a funzionare tra il client e il certificato dell’applicazione stessa.

La regola fissa anche le modalità di errore che incontrerete più avanti. Se il gateway inoltra ma l’host dell’applicazione non ha nessuna rotta di ritorno verso il client, le risposte partono con la sorgente sbagliata e la stretta di mano si blocca. Se una seconda regola corrisponde per prima, l’ordine decide il risultato, e iptables -t nat -L -n -v mostra i contatori che provano quale regola ha preso il pacchetto.

Il tunnel incapsula il pacchetto prima che il listener lo veda

Una VPN non pubblica affatto l’applicazione. Il client costruisce un pacchetto esterno indirizzato all’indirizzo pubblico del gateway, cifra il pacchetto interno al suo interno, e il gateway decifra e instrada il pacchetto interno verso la destinazione privata. Con WireGuard il trasporto esterno è UDP, di solito su una porta alta; con OpenVPN su TCP 443 il pacchetto esterno sembra TLS a qualunque cosa sorvegli il percorso.

Dentro il tunnel il pacchetto interno conserva indirizzi privati: l’indirizzo di tunnel del client, diciamo 10.8.0.6, e l’applicazione su 10.20.30.40. Il listener vede quindi una sorgente dal pool del tunnel, e ogni client condivide quel gateway come prossimo salto. I registri di accesso dietro una VPN mostrano spesso il gateway invece dell’utente proprio per questo motivo, a meno che il gateway conservi la sorgente originale.

L’incapsulamento costa spazio nell’intestazione, ed è l’unica differenza a livello di meccanismo con una conseguenza misurabile. Un’intestazione IP esterna più UDP più l’intestazione propria di WireGuard erodono l’MTU del percorso, quindi i pacchetti grandi vanno frammentati o lo stack TCP interno deve limitare il proprio MSS. Un trasferimento che funziona sul percorso inoltrato può bloccarsi sul tunnel quando un apparato intermedio scarta l’ICMP che avrebbe segnalato l’MTU più piccolo.

ip route get 10.20.30.40
ping -M do -s 1400 10.20.30.40
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

L’esposizione si decide all’ingresso, non con la cifratura

Entrambi i progetti terminano sullo stesso listener TLS, quindi entrambi ereditano lo stesso certificato, le stesse versioni di protocollo e lo stesso accesso applicativo. Cambia chi può avviare una stretta di mano. Con un inoltro pubblico, qualsiasi host che raggiunga 203.0.113.10:443 ottiene una stretta di mano TCP e un ClientHello TLS prima ancora che l’autorizzazione dell’applicazione venga consultata. Con l’accesso solo tramite tunnel, il listener è raggiungibile solo dagli indirizzi che il gateway instrada nel tunnel, e il SYN di un estraneo muore sulla politica del gateway.

Questa differenza riguarda la raggiungibilità, non la riservatezza. Un servizio HTTPS inoltrato non è testo in chiaro, e una VPN non elimina la necessità di autenticazione dell’applicazione: l’ammissione al tunnel risponde se un dispositivo può inviare pacchetti in questa rete, mentre l’applicazione dei file risponde se un utente può leggere un documento. Confondere le due cose è il modo in cui i team finiscono con una VPN che concede tutta la LAN e un’applicazione con un’unica password condivisa.

Ispezionate il listener e la politica separatamente, perché ciascuno dei due può essere più ampio di quanto supponiate:

sudo ss -ltnp 'sport = :443'
sudo nft list ruleset
openssl s_client -connect 203.0.113.10:443 -servername files.example.com </dev/null

Se ss mostra che il listener è legato a 0.0.0.0, l’applicazione è raggiungibile da dove l’instradamento e la politica del firewall lo consentono, e l’inoltro è solo una delle vie d’ingresso. Legarlo all’indirizzo privato, o limitare l’intervallo di sorgenti nel firewall, è una decisione separata dalla scelta di una VPN, ed è la decisione che riduce davvero l’esposizione.

Misurate il percorso, non l’etichetta

Quando qualcuno sostiene che l’inoltro è più veloce, il confronto onesto mantiene tutto il resto costante: stesso client, stessa rete di accesso, stesso file, stessa configurazione TLS, stesso host dell’applicazione. Eseguite il trasferimento due volte per percorso e annotate tempo totale, numero di errori e reattività, non l’output di un test di velocità non correlato.

curl -sS -o /dev/null -w '%{time_connect} %{time_appconnect} %{time_total}\n' \
  https://files.example.com/report.pdf
mtr -rwc 20 203.0.113.10
mtr -rwc 20 10.20.30.40

Quei numeri separano la creazione della connessione dal tempo di trasferimento, il che conta perché i due percorsi di solito differiscono per latenza di andata e ritorno e MTU, non per costo della cifratura. Il lavoro TLS avviene agli estremi in entrambi i progetti, e un tunnel aggiunge incapsulamento, un percorso diverso e forse un gateway più carico. Se il percorso del tunnel è più lungo o il suo gateway è sotto carico, la differenza appartiene al percorso e non alla parola cifratura.

Scegliete la politica d’ingresso di cui il servizio ha davvero bisogno, poi decidete se una differenza misurata giustifica cambiarla. Un inoltro pubblico si adatta a un servizio pensato per internet aperto, con restrizioni di sorgente, TLS aggiornato e monitoraggio davanti. L’accesso solo tramite tunnel si adatta a uno strumento interno i cui utenti sono già registrati, purché l’instradamento del gateway e i permessi dell’applicazione siano entrambi più stretti dell’intera LAN.

Prima di dichiarare finito il progetto, confermate quattro cose: a quale indirizzo è legato il listener, quale regola o rotta ammette il pacchetto, se il percorso di ritorno funziona dall’indirizzo reale del client e se i carichi grandi sopravvivono all’MTU. Ognuna di queste ha un comando qui sopra, e nessuna è risolta dalla parola sicuro o da un grafico di larghezza di banda.

Articoli correlati