Connessione ssh verso un host remoto dietro nat grazie ad un tunnel comandato a distanza

Dopo avere visto come accedere tramite tunnel ssh ad un host remoto dietro nat (Connessione ssh verso un host dietro nat), vediamo come attivare/disattivare tale tunnel grazie ad un semplice file di testo posto sul web server del host che fungerà da host pubblico.

Elementi in gioco:

  • host-dietro-nat: host su cui vogliamo accedere, sarà lui a creare il tunnel
  • server-pubblico: server pubblico a cui abbiamo accesso e che conterrà il file di testo con il comando per aprire o chiudere il tunnel; per accedere a server-pubblico dovremo bussare alla porta 1234

Cosa vogliamo ottenere:
Vogliamo che host-dietro-nat controlli periodicamente un file sul server web server-pubblico e in base a questo apra/chiuda un tunnel ssh sempre verso server-pubblico. Una volta aperto il tunnel ssh dal server pubblico potremo accedere ad host-dietro-nat con un semplice ssh -p 2222 localhost impartito su server-pubblico.

File con comando:
Il file contenente il comando per aprire/chidere la connessione ssh deve risiedere sulla web root di server-pubblico ed è nominato o.txt. Deve contenere uno dei seguenti caratteri seguito dal ritorno a capo (n)

  • r: reset – killa ssh bussanti, ssh tunnel e riapre il tunnel
  • o: open – apre il tunnel
  • c: close – chiude il tunnel (killa ssh bussanti e ssh tunnel)

Vediamo gli script che dovranno essere eseguiti da host-dietro-nat:

open-tunnel-ssh.sh

#!/bin/sh
COMANDO=`wget -q -O - http://server-pubblico/o.txt`
 
echo "COMANDO=$COMANDO"
 
if [ "$COMANDO" == "r" ] || [ "$COMANDO" == "c" ]; then
  echo "reset"
  kill_ssh_bussanti
  kill_ssh_tunneling
fi
 
if [ "$COMANDO" == "r" ] || [ "$COMANDO" == "o" ]; then
  PORTAAPERTA=`ps |grep "[s]sh -f -N -R 2222" | wc -l`
 
  if [ "$PORTAAPERTA" == "0" ]; then
    echo "sto bussando"
    ssh -p 1234 server-pubblico &
    sleep 10
    echo "apro il tunnel"
    ssh -f -N -R 2222:localhost:22 user@server-pubblico
    kill_ssh_bussanti
  fi
fi

kill_ssh_tunneling

#!/bin/sh
echo "killo ssh tunneling"
for KPID in `ps |grep "[s]sh -f -N -R 2222" | tr -s ' ' | cut -d ' ' -f 2 `; do
  kill -9 $KPID
done

kill_ssh_bussanti

#!/bin/sh
echo "killo ssh bussanti"
for KPID in `ps | grep "[s]sh -p 1234" | tr -s ' ' | cut -d ' ' -f 2 `; do
  kill -9 $KPID
done

Vediamo i passi che eseguire lo script open-tunnel-ssh.sh:

  • recupera il comando da eseguire inserendolo nella variabile COMANDO (wget -q -O – http://server-pubblico/o.txt)
  • chiude eventuali richieste di port knocking ed eventuali tunnel aperti quando il comando è reset o close grazie agli script kill_ssh_bussanti e kill_ssh_tunneling
  • se il comando impartito è reset oppure open prosegue bussando a server-pubblico (sh -p 1234 server-pubblico &) e aprendo il tunnel ssh verso server-pubblico (ssh -f -N -R 2222:localhost:22 user@server-pubblico)

Si da per scontato che il tutto funziona utilizzando la chiave pubblica ssh di host-dietro-nat in modo che ssh non richieda la password di autenticazione.

Una volta inserito nel crontab di host-dietro-nat lo script open-tunnel-ssh.sh potremo aprire o chiudere il tunnel grazie al contenuto del file o.txt residente su server-pubblico.

6 pensieri su “Connessione ssh verso un host remoto dietro nat grazie ad un tunnel comandato a distanza

  1. Ciao! Un solo chiarimento.. Perchè busso alla porta 1234 se voglio aprire la 2222 ? Perdonami ma sono un po’ ignotante in materia…

  2. @Tapiocapioca
    Perché nel mio caso dovevo accedere ad una macchina con firewall configurato con protezione port koncking sulla porta 1234.

    Dove non ci sia un portknocking a monte (la maggior parte dei casi) possono essere escluse le parti di codice che la riguardano.

    In open-tunnel-ssh.sh possiamo togliere le linee

    echo “sto bussando”
    ssh -p 1234 server-pubblico &
    sleep 10

    e possiamo togliere anche tutte le righe che lanciano

    kill_ssh_bussanti

    Spero di essere stato chiaro,
    ciao.

  3. Chiarissimo!
    Però dato che sei disponibile ne approfitto ben volentieri!

    Ho modificato il tuo script come segue:

    —————————————————-

    #DESCRIPTION=Tunnel SSH
    COMANDO=`wget -q -O – http://www.xxx.com/o.txt`
    echo “COMANDO=$COMANDO”
    if [ “$COMANDO” == “r” ] || [ “$COMANDO” == “c” ]; then
    echo “reset”
    kill_ssh_tunneling
    fi
    if [ “$COMANDO” == “r” ] || [ “$COMANDO” == “o” ]; then
    PORTAAPERTA=`ps |grep “[s]sh -f -N -R 11000” | wc -l`
    if [ “$PORTAAPERTA” == “0” ]; then
    echo “apro il tunnel”
    ssh -i /etc/dropbear/web.key -g -R 11000:localhost:80 root@xxx.mine.nu
    fi
    fi

    ——————————————————

    Se provo ad eseguirlo ottengo un errore! Per la precisione:

    /usr/script/tunnelssh.sh: line 14: syntax error: unexpected “fi” (expecting “then”)

    Per quanto mi riguarda dovrebbe essere tutto ok.. Ma evidentemente…
    😀

    Grazie se avrai voglia di aiutarmi!

  4. @Tapiocapioca
    Il tuo script riportato pari pari sulla mia ubuntu non mi presenta nessun errore ma viene eseguito fino in fondo.

    Ho notato che se nello script non hai specifico quale interprete usare inserendo sulla prima linea
    #!/bin/bash

    Prova e metterlo magari è un problema del genere.

    Una domanda, su che sistema deve funzionare questo script ?

  5. Mmmm… Non faccio fatica a credere che sulla tua ubuntu funzioni! E’ venuto il dubbio anche a me nel momento in cui ti ho scritto il messaggio.

    Uso un sistema particolare, un dreambox dm800. E’ un decoder satellitare. Magari lo conosci, mi sembri più che avvezzo alla sperimentazione con le periferiche più variegate!

    Probabilmente gli manca qualcosa per eseguire correttamente lo script 🙁
    Purtroppo usa pacchetti igkp che non conosco per niente..

    Se sei curioso ti posso far vedere un po’ remotamente!

  6. @Tapiocapioca
    No non lo conosco ma ho avuto a che fare con altri sistemi embedded tipo router basati con dd-wrt e open-wrt.

    Ti contatto privatamente così se vuoi mi dai le credenziali per accedere da remoto e do un’occhiata.

    Ciao.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *