Automatiza el túnel inverso SSH en Raspberry Pi

Automatiza el túnel inverso SSH en Raspberry Pi

Durante muchos días me he preguntado cómo automatizar el establecimiento de un túnel inverso.

Tengo muchas Raspberry remotas que usan NAT dentro de sus LAN y una Raspberry que uso como servidor, accesible desde Internet.

Implementé en mi sitio web un sistema para enviar comandos únicos remotos de Raspberries.

Cada Raspberry remoto comprueba cada minuto (crontab) la presencia de comandos disponibles y, si los hay, descarga el comando, crea un archivo ejecutable y lo ejecuta. Aquí está el código del archivo crontab:

#! /bin/bash

sudo wget -c --output-document=ipdiscover.php "www.myserver.com/checkforcommands.php";

comando=$(cat ipdiscover.php);

sudo rm "/esegui.sh";

echo "#! /bin/bash" >> /esegui.sh;
echo "" >> /esegui.sh;
echo -e $comando >> /esegui.sh;
echo "exit 0" >> /esegui.sh;

sudo chmod +x /esegui.sh;

sudo /esegui.sh;

sudo rm "ipdiscover.php";

sudo date >>/tmp/crontest.txt;

Este sistema funciona muy bien, pero no puedo usarlo para establecer el túnel inverso.

Si, en el servidor remoto, ejecuto este código:

sudo /usr/bin/ssh -gNnT -R 2222:localhost:22 pi@publicserverIP;

entonces todo funciona correctamente, pero si lo ejecuto desde el script crontab, no funciona.

Creé los certificados sin contraseña y los envié desde la Raspberry remota al servidor para no poder iniciar sesión.

Respuesta1

No es necesario ejecutar comandos crondesde sudo.

Cree un script como este a continuación y colóquelo en el directorio de inicio del usuario que establecerá una conexión SSH inversa a su servidor:

#!/bin/sh

### reverseSSHscript.sh ###

### (use public key authentication, so you don't need 
### to enter password for your server)
PrivateKeyToAccessCentralServer='/path/to/the/private/ssh/ServerKey.pem'

(
/usr/bin/nohup     \ 
 /usr/bin/ssh -gNnT \
  -i "${PrivateKeyToAccessCentralServer}" \
  -o ExitOnForwardFailure=yes     \
  -o ServerAliveInterval=60       \
  -o ServerAliveCountMax=1        \
  -o TCPKeepAlive=no              \
  -o UserKnownHostsFile=/dev/null \
  -o StrictHostKeyChecking=no     \
  -o CheckHostIP=no               \
  -R 2222:localhost:22 pi@publicserverIP
) &

Luego crea la tarea de cron para ejecutarla:

echo "@reboot User /path2the_script_shown_above/reverseSSHscript.sh" |
   sudo tee /etc/cron.d/reverseSSH2home

Entonces debería funcionar.
Por cierto, es posible que desee ejecutar este script bajo algunas restricciones Useren lugar de hacerlo rootsimplemente para estar seguro.

También debe implementar alguna lógica que reverseSSHscript.shverifique si la conexión ya está establecida, para evitar la creación de múltiples sesiones.

Ejecute también algunas comprobaciones adicionales desde cron periódicamente para comprobar si el puerto de conexión inversa todavía está activo en su servidor; algo como esto:

chkRemPort() {
    # Connect to intermediate host and check if remote forwarded port is alive
    echo $(/usr/bin/ssh -4 -f -q        \
        -o BatchMode=yes                \
        -o UserKnownHostsFile=/dev/null \
        -o StrictHostKeyChecking=no     \
        -o CheckHostIP=no               \
        -i /path/to/the/private/ssh/ServerKey.pem      \
        pi@publicserverIP               \
        /bin/nc -w 3 -zv localhost 2222 2>&1 | /bin/grep succeeded > /dev/null ;    \
        [ $? -eq 0 ] && { echo 'OK'; } || { echo 'FAILED'; }; exit; )
}

Si la verificación falla, intente establecer una nueva sesión inversa en su servidor.

PD:
Los puertos invertidos en cada Raspberry Pi deben ser diferentes para evitar conflictos entre los puertos de su servidor

información relacionada