Il tuo servizio funziona sulla macchina, il tunnel è attivo eppure il browser sulla tua scrivania aspetta ancora una risposta. Niente è rotto nel senso comune: l’applicazione ascolta dentro uno spazio dei nomi di rete, e quello stack è invisibile alla LAN. Il suo loopback appartiene allo spazio dei nomi, quindi un client su un’altra macchina non ha alcun indirizzo che raggiunga la porta. Un salto deliberato, o una coppia veth, risolve il problema senza spostare il resto dell’host.

Perché nulla risponde all’indirizzo della LAN

Uno spazio dei nomi è uno stack di rete completo: interfacce, rotte, regole del firewall e un loopback privato. Un processo avviato tramite ip netns exec vede quello stack e nient’altro, quindi l’indirizzo a cui si lega viene risolto solo dentro lo spazio dei nomi. Il 127.0.0.1 dell’host è un loopback completamente diverso.

Per questo curl fallisce sull’host mentre lo stesso comando dentro lo spazio dei nomi riesce. L’applicazione è sana; l’indirizzo semplicemente non esiste nello stack dell’host.

Pubblicare una sola porta con un salto socat

socat collega i due stack nello spazio utente, il che basta quando deve attraversare un’unica porta TCP. Il lato host ascolta sulla LAN e, per ogni connessione accettata, avvia un secondo socat dentro lo spazio dei nomi che si collega al loopback dell’applicazione. Il processo interno raggiunge l’applicazione esattamente come farebbe un client locale. Nulla cambia nell’instradamento dello spazio dei nomi, quindi l’applicazione continua a usare il tunnel come unica uscita.

socat TCP-LISTEN:9100,reuseaddr,fork EXEC:'ip netns exec vpn socat STDIO tcp-connect:127.0.0.1:9100',nofork

Il processo esterno ha bisogno di root o della capacità di entrare nello spazio dei nomi. Se la VPN cade, l’applicazione perde il suo percorso e la porta pubblicata fallisce chiusa, che è il comportamento che vuoi da una gabbia.

Usare una coppia veth quando attraversa più di una porta

Una coppia veth è la risposta giusta quando devono attraversare più porte o protocolli, o quando altri host devono avviare connessioni. Un’estremità resta nell’host, l’altra passa nello spazio dei nomi, e una /30 piccola dà a entrambi i lati un indirizzo stabile. Poi una rotta dell’host invia l’indirizzo dello spazio dei nomi attraverso la coppia.

ip link add veth0 type veth peer name veth1
ip link set veth1 netns vpn
ip addr add 10.77.0.1/30 dev veth0
ip link set veth0 up
ip netns exec vpn ip addr add 10.77.0.2/30 dev veth1
ip netns exec vpn ip link set veth1 up

Non aggiungere una rotta predefinita attraverso l’host se non vuoi rompere la gabbia. Il tunnel deve restare l’uscita, quindi attraverso la coppia è raggiungibile solo l’indirizzo del servizio pubblicato. Dai allo spazio dei nomi anche il suo file di risoluzione, perché ip netns exec legge /etc/netns/vpn/resolv.conf e senza di esso la risoluzione dei nomi nella gabbia è vuota.

Prova da un’altra macchina, non dall’host

Esegui il test da una seconda macchina, perché l’host può raggiungere un listener locale per percorsi che non dicono nulla sulla LAN. Controlla prima a cosa si è realmente legata l’applicazione dentro lo spazio dei nomi, poi collegati dall’esterno all’indirizzo pubblicato. Legarsi a tutti gli indirizzi lì non allarga la gabbia, perché il carattere jolly appartiene ancora allo spazio dei nomi e la LAN non può vederlo.

ip netns exec vpn ss -lntp

Se la connessione dall’host funziona e quella dalla LAN no, il pezzo mancante è il salto o la rotta, non l’indirizzo di legame. Avvia OpenVPN dentro lo spazio dei nomi invece di spostarvi un dispositivo tun attivo, dato che spostare l’interfaccia la disattiva e può cancellare rotte che poi non potrai riparare dall’esterno. Tieni i comandi di ripristino sulla console, non dentro la gabbia.

Articoli correlati