Our logo :(

Hackerspace Monterrey

Túnel ssh para RaspberryPi

El objetivo.

Acceder a una RaspberryPi[1] que está detrás de una IP dinámica (lo más común para proveedores de Internet en hogares) sin necesidad de configurar algún servicio de NATing[2] en el modem y/o router.

Un caso de uso sería monitorear nuestros equipos remotamente, revisando que su funcionamiento sea el correcto.

Cómo funciona esto es que creamos un túnel inverso (eng. reverse SSH tunel) utilizando SSH[3], esto crea una conexión encriptada desde la Raspberry Pi al servidor, la configuramos de tal manera que esta conexión inicie automáticamente cada que se enciende la máquina, así podemos asegurarnos que la conexión se reestablesca si se llegase a interrumpir.

Asunciones

  • Se tiene acceso a un servidor con IP pública y SSH
  • Se tiene una PC (Workstation/Desktop/Mac/Laptop).
  • Se tiene una Raspberry Pi.
  • Se tiene una salida a Internet.
  • Se tiene una red local (LAN).
  • La PC y Raspberry están conectadas a la LAN.

Configuración para usuarios

## Preparar usuario para túnel la Raspberry

  • Habilitar SSH en raspberry.

    rpi$ sudo raspy-config

[imagen raspy-config menu] [imagen raspy-config opcion]

  • Crear usuario para el tunel en Raspberry.

    rpi$ sudo adduser tunnel

[imagen alta-usuario]

  • Cambiar de usuario a tunnel.

    rpi$ su tunnel

  • Crear un par de llaves SSH para el usuario Tunnel.

    rpi$ ssh-keygen

  • Obtener la dirección IP asignada a la Raspberry.

    rpi$ ip addr show

Esto desplegara una lista de tus interfaces, busca la dirección IP como un juego de cuatro números junto la etiqueta ‘inet’.

e.g.

3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc mq state UP group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.2/24 brd 192.168.0.255 scope global wlan1
    valid_lft forever preferred_lft forever
    inet6 fe80::c66e:1fff:fe16:49e3/64 scope link
    valid_lft forever preferred_lft forever

En este caso la dirección sería 192.168.0.2

Preparar usuario para túnel en servidor

  • Crear usuario para túnel en servidor

    servidor$ sudo adduser tunnel

[imagen alta-usuario]

  • Crear carpeta .ssh

servidor$ su tunnel servidor$ cd ~ servidor$ mkdir .ssh servidor$ cd .ssh

Copiar llave pública al servidor

El par de llaves criptográficas que acabamos de crear nos servirán para poder conectarnos al servidor desde la Raspberry sin necesidad de tener que ingresar la contraseña del usuario cada vez que tenemos que conectarnos al él.

  • Copiamos la llave pública, id_rsa.pub, de la Raspberry al servidor, utilizando nuestra PC como intermediario. Reemplaza con la dirección.

    PC$ scp tunnel@<raspberry-ip>:.ssh/id_rsa.pub raspberry_public_key

  • Una vez hecho esto, copiamos la llave al servidor:

    PC$ scp raspberry_public_key tunnel@<servidor>:

  • Ingresamos al servidor para colocar la llave pública de la Raspberry en la lista de llaves autorizadas para realizar identificar.

PC$ ssh <servidor> servidor$ su tunnel servidor$ cat raspberry_public_key >> ~/.ssh/authorized_keys

Con esto debemos tener nuestra llave pública que se creo en la Raspberry Pi dentro de la cuenta del usuario tunnel dentro del servidor. Para validar que la llave se haya copiado correctamente, desplegamos que el contenido del archivo ~/.ssh/authorized_keys y verificamos que sea el mismo que generamos para el usuario tunnel en la Raspberry Pi.

`servidor$ cat ~.ssh/authorized_keys`

Crear túnel

Probar el comando para el túnel.

  • Ingresamos a raspberrypi con el tunnel desde pc/laptop.

    PC$ ssh tunnel@<ip-raspberry>

  • Probamos correr manualmente el comando que crea el túnel

rpi$ ssh -NTC -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no \ -i ~/.ssh/id_rsa -R 12345:localhost:22 tunnel@<servidor>

Si el comando fue bien la terminal se quedara en “stand-by”, esperando conexiones. Se puede agregar la opción -v al comando para ver lo que ocurre con las conexiones, esto nos ayuda en caso de que ocurra un error.

Para probar que realmente tenemos acceso, entramos al servidor y cambiamos de usuario a “tunnel”, con ese usuario activo ejecutamos:

servidor$ ssh localhost -p 12345

Si todo sale bien nuestro prompt cambia hacia el prompt de nuestra Raspberry Pi:

rpi$

Crear servicio de túnel.

Una vez validado el comando de túnel, lo que falta es hacer que se ejecute cada que la Raspberry Pi se encienda. Para ello usamos systemd[4] para crear un servicio que realice esta tarea.

  • Creamos el archivo del servicio

    rpi$ sudo nano /etc/systemd/system/tunnel-service

  • Añadimos la siguiente configuración a este archivo

``` [Unit] Description=SSH Tunnel Service ConditionPathExists=|/usr/bin After=network.target

[Service] User=tunnel ExecStart=/usr/bin/ssh -NTC -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -i %h/.ssh/id_rsa -R 12345:localhost:22 tunnel@

RestartSec=3 Restart=always

[Install] WantedBy=multi-user.target ```

Guardamos el archivo antes de salir (presionando Ctrl-o en Nano).

  • Iniciamos el servicio.

    rpi$ sudo systemctl restart tunnel-service

Si el resultado es positivo veremos el siguiente mensaje en pantalla.

[imagen log de systemctl restart]

  • Habilitamos al servicio para que se ejecute desde boot.

    rpi$ sudo systemctl enable tunnel-service

Probar túnel.

Habiendo hecho esto, accedemos con cualquier usuario al servidor y cambiamos al usuario tunnel. Reiniciamos la Raspberry Pi, una vez reiniciada accedemos al túnel desde el servidor:

servidor$ su tunnel servidor$ ssh localhost -p 12345

Con ello debemos aparecer en la terminal de nuestra Raspberry Pi.

Recomendaciones.

  • Cambia el nombre de la Raspberry Pi a uno que sea mas especifico a nuestra aplicación (podemos tener muchas raspies regadas por ahi).

  • Asignar una dirección IP estática a la Raspberry, si por alguna razón estamos en el sitio y tenemos que acceder a la misma nos ahorramos el paso de buscar la dirección asignada por la red.

  • Usar un usuario diferente para cada túnel en el server para una mejor administración.

  • Se puede validar si el túnel esta vivo del lado del servidor si buscamos por conexiones ssh en modo LISTEN servidor$ netstat -l | grep ssh



Dirección
Isaac Garza 735-A
Monterrey, N.L.
C.P. 64000
(81) 19-36-9480
Mapa

Horario
Martes
19:00 a 23:00

Sábado
14:00 a 00:00

Junta semanal
Martes 19:00