Connessione ssh verso un host dietro nat

Supponiamo di aver un host A con un indirizzo pubblico e un host B su una lan dietro Nat, a questo punto vogliamo raggiungere dall’host A l’host B tramite ssh ma non possiamo mettere mano al gateway che Natta B.
Una possibile soluzione è fare aprire a B un tunnel ssh su A tramite il quale poi ci collegheremo

open_tunnel_ssh.sh

#!/bin/bash
PORTAAPERTA=`ps u -N -C grep |grep "ssh -N -R 3333" | tr -s ' ' | cut -d ' ' -f 11 | wc -l`
if [ "$PORTAAPERTA" == "0" ]; then
     ssh -N -R 3333:localhost:22 user@host_A.com -f
fi

questo script può essere inserito nel crontab di B in modo che venga eseguito ogni cinque minuti. Se il tunnel è già aperto la connessione ssh non verrà rieseguita altrimenti verra aperta la porta 3333 sull’host A che punterà alla porta 22 (ssh) dell’host B

A questo punto dall’host A possiamo impartire il comando

ssh -p 3333 localhost

e avremo accesso a l’host B

nell’eventualità che il tunnel cada questo verrà ripristinato dopo cinque minuti grazie al crontab.

Per fare funzionare il tutto è fondamentale che la connessione ssh da B verso A funzioni senza dovere impartire la password ma grazie alla chiave pubblica di B precedentemente generata

ssh-keygen -t dsa

e salvata in

~/.ssh/authorized_keys

di A

11 pensieri su “Connessione ssh verso un host dietro nat

  1. Ciao,
    ssh per fare un tunnel è molto comoda, certo…
    però ogni volta mi viene il mal di testa con la sintassi del comando… sicuro che dove hai scritto host_B non ci vada host_A ?
    Altra cosa, non ti chiede la password però ti chiede la passphrase, quindi devi generare una chiave senza la passphrase…
    bye martuf1

  2. Hai ragione ho sbagliato, l’ho appena corretto:

    il tunnel da B verso A si crea con:
    ssh -N -R 3333:localhost:22 user@host_A.com -f

    e ci si collega da A a B con:
    ssh -p 3333 localhost

  3. ciao, scusa la domanda da neofita, ma siccome la soluzione mi piace parecchio vorrei riuscire a metterla in pratica. Come si fa a creare lo script di cui posti la sintassi?
    Davide

  4. Ciao Davide,
    esattamente cosa è che vuoi sapere ?
    Basta che ricopi lo script sostituendo host_A e host_B con i tuoi valori.
    Puoi usare un qualsiasi editor sotto linux (vi, gedit, kate) e poi rendi eseguibile il file con chmod.

    Sono a disposizione per qualsiasi chiarimento.

    Ciao.

  5. Ciao,

    Prima di tutto grazie per la disponibilità

    ho provato in tutti i modi a mettere in crontab un file chiamato manutenzione.sh, salvato in /[HOME]/manutenzione.sh.

    Editando il crontab dell’utente (crontab -e) ho fatto i seguenti tentativi senza risultato:
    */1 * * * * sh /home/orso/manutenzione.sh
    */1 * * * * /home/orso/manutenzione.sh
    */1 * * * * sh /home/orso/./manutenzione.sh

    Il file manutenzione.sh ha i permessi di esecuzione (chmod +x …..).

    Non riesco a capire dove sbaglio…..

    Grazie ancora
    Davide

  6. Prima di inserire il comando nel crontab hai provato a lanciarlo manualmente e hai controllato se il risultato è quello desiderato ?

    la prima colonna ntdel crontab (*/1) ha poco senso perché gia con * viene eseguito il comando ogni minuto, quindi io sostituirei */1 con *

    Eventualmente prova a riavviare il servizio crontab, una volta sono diventato matto per un problema simile, poi è bastato riavvieare crontab.

    a seconda della distrivuzione:

    sudo /etc/init.d/cron restart

    oppure

    service crond restart

    ciao, fammi sapere.

  7. Per essere più precisi dovrebbe essere così

    * * * * * /home/orso/manutenzione.sh

  8. Ciao, scusa se è passato qualche giorno ma sono rimasto incasinato con il lavoro.

    Ho scoperto che crontab fa a pugni con una leggera modifica che ho apportato al tuo script per poterlo applicare ad un parco macchine piuttosto nutrito.

    Il mio script è:

    #!/bin/bash
    HOSTNAME_VAR=$HOSTNAME
    PORTA=5${HOSTNAME_VAR##*-}

    PORTAAPERTA=`ps u -N -C grep |grep “ssh -N -R $PORTA” | tr -s ‘ ‘ | cut -d ‘ ‘ -f 11 | wc -l`

    if [ “$PORTAAPERTA” == “0” ]; then
    ssh -N -R $PORTA:localhost:22 user@server -f
    fi

    In pratica, le macchine del mio parco hanno un hostname strutturato così:

    host-xxx

    dove xxx è un numero progressivo.
    Con questa tecnica ottengo delle connessioni sul mio server dalla porta 5001 in avanti, in base al nome host della macchina.

    Il problema che la parte “dinamica” dello script non va in crontab: infatti per ottenere il risultato l’ho messo in esecuzione automatica (ma ovviamente viene eseguito 1 volta sola all’avvio).

    Non so se hai dei suggerimenti.

    Grazie ancora
    Davide

  9. Ciao Davide,
    ho ripreso il tuo script e l’ho eseguito sul mio pc con Ubuntu 8.10, a me funziona sia lanciandolo a mano che inserendolo nel crontab.

    Ti chiedo una cosa, l’utente impostato nel crontab per eseguire lo script è lo stesso di quando viene lanciato a mano ?
    Se così non fosse e l’utente del crontab fosse prima volta che esegue l’ssh sulla macchina remota, lo script si bloccherebbe richiedendo conferma per lo scambio delle chiavi.

    Se il problema è questo imposta nel crontab l’utente con cui lanci attualmente lo script in esecuzione automatica.

    Naturalmente fammi sapere.
    Ciao, a presto.

  10. Ciao,

    come sempre i miei tempi di risposta sono bibblici, ma, anche se dopo un po’ di tempo, ritengo doveroso farti i miei ringraziamenti.

    Ho visto adesso il tuo suggerimento ed effettivamente era un problema di utente. Adesso è tutto ok.

    Grazie ancora.

    Davide.

    PS: sapresti mica darmi un suggerimento dove trovare delle indicazioni per realizzare un semplice contatore per contare gli accessi delle macchine client al server?
    Ciao

  11. Ciao Davide sono contento che hai risolto il problema.

    Per il contatore di accessi io proverei utilizzando il comando last oppure se i client accedono tutti con un unico utente personalizzerei .bashrc in modo da incrementare un contatore su file ad ogni sua esecuzione (che avviene ad ogni login da parte dell’utente).

    Ciao.

Lascia un commento

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