Lasciare che un client OpenVPN faccia SSH verso un altro senza aprire il pool
Tieni client-to-client disattivato, lascia che il kernel inoltri un solo flusso e lascia chiuso il resto del pool. Due regole sul server più una sulla destinazione.
Un client deve raggiungere il servizio SSH di un altro client, e il resto del pool deve restare isolato come oggi. L’interruttore tentante è client-to-client, che attiva l’accesso tra pari per tutti in una volta e affida la decisione a OpenVPN invece che al kernel. Una risposta più stretta tiene spento quell’interruttore e lascia che l’instradamento e il firewall del server portino esattamente un flusso.
Il meccanismo conta più del testo della regola, perché i due approcci mettono il pacchetto in posti diversi. Sapere quale hai scelto spiega sia la regola che sembra non fare nulla sia il pari che si connette senza.
Dove client-to-client sposta il pacchetto
Con client-to-client attivo, il server inoltra internamente un pacchetto di pari invece di rispedirlo fuori dal dispositivo tunnel, così il pacchetto non raggiunge mai il percorso di inoltro del kernel. È comodo e significa anche che il tuo firewall non vede mai il flusso che dovrebbe sorvegliare. Lascia l’opzione spenta e il server instrada il pacchetto di nuovo fuori dalla stessa interfaccia, il che lo mette davanti a netfilter. Stessa interfaccia in ingresso, stessa in uscita, e la catena FORWARD ha il voto.
Lo scambio è esplicito: guadagni un punto di policy e ti assumi il lavoro di instradamento e inoltro che la scorciatoia faceva per te. Quel lavoro è piccolo per un solo flusso e cresce con ogni eccezione che aggiungi. Conta ora le eccezioni, perché è nel set di regole che vive davvero la policy tra pari.
Il percorso che un pacchetto di pari segue davvero
Supponi un servizio Linux Community OpenVPN 2.6, elaborazione TUN nello spazio utente invece di DCO, topologia a sottorete, tun0 e un pool di 10.44.0.0/24 con il client A su 10.44.0.21 e il client B su 10.44.0.37. Con la topologia a sottorete l’indirizzo e la maschera ricevuti da A coprono già il pool, quindi A invia il pacchetto al dispositivo tunnel senza bisogno di una rotta aggiuntiva spinta. Controlla la rotta effettiva su A invece di darla per scontata.
Sul server il pacchetto arriva indirizzato a B, che non è un indirizzo locale, quindi viene inoltrato. L’inoltro IPv4 deve essere attivo perché ciò accada, e la ricerca della rotta deve rispedire il pacchetto fuori da tun0. Il firewall vede quindi un flusso inoltrato con la stessa interfaccia su entrambi i lati, ed è il dettaglio che quasi tutti i set di regole trascurano. Qui non serve alcuna traduzione di sorgente, ed è mantenendo intatto l’indirizzo di A che B può applicare la propria regola basata sulla sorgente.
Due regole sul server, in questo ordine
Tre regole portano tutta l’autorizzazione: l’inoltro, l’eccezione della coppia e un rifiuto predefinito per la coppia tunnel. La regola di accettazione nomina la coppia e il servizio, così l’autorizzazione sopravvive a un pool che cresce. Mettila prima di qualsiasi rifiuto generalizzato del traffico tunnel-tunnel, perché vince la prima corrispondenza:
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o tun0 -s 10.44.0.21 -d 10.44.0.37 -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -j DROPQuei comandi sono illustrativi e appartengono al meccanismo che il tuo host usa per conservare le regole; un inserimento a runtime sparisce al boot successivo. È la regola con stato che permette alle risposte di B e alla stretta di mano TCP di tornare senza una seconda accettazione speculare.
Controlla i contatori dopo, non l’elenco delle regole, perché una regola che non corrisponde mai è identica a una che funziona. Se i contatori restano a zero, il pacchetto non sta seguendo il percorso che credi.
Cosa deve ancora consentire B
B esegue il servizio SSH, quindi B decide se qualcosa è in ascolto sull’indirizzo del tunnel e se il suo firewall locale accetta la sorgente. Un permesso di rete sul server non è un permesso per nessun account di B, e la verifica della chiave host e l’autenticazione utente valgono ancora come da qualsiasi altro posto.
Prova prima il caso positivo: una nuova connessione SSH da A all’indirizzo del tunnel di B, accettata con la chiave host attesa. Poi prova un altro pari o un’altra porta e conferma che viene rifiutata, perché un’autorizzazione che consente tutto in silenzio è indistinguibile da una che funziona finché non conta. Entrambe le metà di quel test sono necessarie, e la seconda è quella che la gente salta.
Annota gli indirizzi assegnati, le rotte effettive su entrambi i client e le regole esatte sul server e su B. Un ping riuscito verso il gateway o una porta aperta sul server non dimostra nulla di tutto ciò, dato che entrambe le cose possono essere vere mentre l’inoltro tra pari è ancora bloccato. Scrivi quei numeri mentre il tunnel è attivo, perché l’indirizzo che un client riceve dopo una riconnessione può essere un altro.