Home Acceso remoto a Raspberry Pi por SSH desde internet
Post
Cancel

Acceso remoto a Raspberry Pi por SSH desde internet

Vamos a configurar el acceso por SSH a una Raspberry Pi desde fuera de nuestra red local haciendo uso de DuckDNS.

Detalles

En una entrada previa vimos cómo instalar Raspberry Pi OS en una Raspberry Pi y configurar el acceso a la misma por SSH para acceder a esta desde la red local a través de nuestro ordenador de trabajo sin necesidad de conectar el dispositivo a un monitor, teclado y ratón. Si no sabes de que hablamos, aquí está el enlace.

Aquí vamos a ver cómo exponer este mismo dispositivo de forma que sea accesible desde el exterior, esto es, que podamos acceder por SSH a la Raspberry desde fuera de nuestra red local; desde internet. Para ello vamos a hacer uso de DuckDNS, un servidor DNS gratuito ‘hosteado’ en Amazon AWS.

ATENCIÓN - Si tu operadora funciona a través de CGNAT siento decirte amigo que esto NO te va a funcionar. ¿Cómo saber si estoy usando CGNAT?

Lista de componentes

  • Nuestra Raspberry Pi (u otro sistema que ejecute Linux) ya configurado.
  • Nuestro ordenador de trabajo con conexión a internet.
  • Unos 20 minutos de tiempo libre.

Registrar cuenta en DuckDNS

Navegamos hasta DuckDNS y tenemos varias opciones para registrar una cuenta aunque todas implican disponer de una cuenta en algún servicio. Recomiendo crear una cuenta en alguno de estos servicios sólo para este propósito, que pueden ser: Twitter, Github o Google. Reddit y Persona aparecen listados pero ya no son una opción. Simplemente hacemos click en alguno de estos servicios e iniciamos sesión; automáticamente hemos registrado una cuenta de DuckDNS.

Imagen de DuckDNS

Vamos al campo ‘Domains‘ y creamos un nuevo dominio, esto es, creamos un nombre distintivo para el sistema que vamos a exponer. Al añadirlo (‘add domain‘) veremos que bajo el campo ‘current ip‘ aparece nuestra IP pública (podemos verificarlo en What Is My Public IP).

Lista de dominios en DuckDNS

Aunque este paso no es estrictamente necesario, nos sirve cómo comprobación, cambiamos el campo ‘current ip‘ por la dirección de un servidor de DNS público cómo, por ejemplo, las de Google. En tal caso, escribimos 8.8.8.8 y hacemos click en ‘update ip‘. Podemos usar otro servidor DNS público, no es necesario que sea Google. El campo de ‘ipv6‘ ni lo tocamos.

Nos apuntamos en algún lado nuestro dominio que acabamos de crear así cómo el token generado por Duck DNS que ¡NUNCA debemos compartir con nadie!

Explicaciones

¿Cuál es el sentido de todo esto? ¿No podemos usar la IP pública y ya? Por dar una explicación lo más corta posible: la IP pública que tenemos asignada es, con carácter general, dinámica; es decir, cambia cada cierto tiempo. Podemos pedir a nuestro ISP (proveedor de internet) que nos asigne una IP fija (y siendo así no necesitaríamos DuckDNS) peeeeero esto suele costar dinero en la mayoría de compañías telefónicas (mucho dinero).

¿La solución? Un servidor de nombres de dominio, un DNS. Esto en esencia es un sistema que asignará a nuestra IP un nombre reconocible (cómo testingforraspberrypi.duckdns.org), de forma que ‘traduce’ direcciones IP en nombres fáciles de tratar para las personas.

¿Pero si la IP pública cambia, cómo soluciona esto el problema? Para ello vamos a usar un script en la Raspberry Pi que le va a indicar a nuestra cuenta de DuckDNS cuál es la IP constantemente de forma que nunca perdamos acceso ante un cambio de IP pública.

Configuración Raspberry

Vamos al dispositivo y desde la consola (terminal) vamos a crear un directorio nuevo dentro del cual crearemos un fichero .sh (un script para bash).

1
2
3
4
5
6
7
8
# Crear directorio llamado duck (por ejemplo)
pi@raspberrypi:~ $ mkdir duck

# Entramos en dicho directorio
pi@raspberrypi:~ $ cd duck

# Dentro del mismo, creamos y abrimos (con nano) un fichero .sh
pi@raspberrypi:~/duck $ nano duck.sh

Dentro de este fichero vamos a introducir un comando dado por la documentación de DuckDNS que contiene nuestro dominio así cómo nuestro token y nos permite enviar nuestra IP a DuckDNS para que se actualice.

1
echo url="https://www.duckdns.org/update?domains=<nombredeldominio>&token=<token>&ip=" | curl -k -o ~/duck/duck.log -K -

Dónde sustituimos por el dominio que creamos antes (sin los símbolos «< >«) y por el token que guardamos previamente (de nuevo, sin los símbolos «< >«). La ruta ~/duck/ dependerá del nombre que le hayamos dado al directorio y el fichero al que estamos haciendo referencia (duck.log) será creado automáticamente. Esta línea nos permite pasarle a DuckDNS el nombre del dominio junto a su token (entendámoslo cómo una contraseña) y la IP actual.

Guardamos los cambios con ‘Ctrl + X‘ (propio del editor nano) y le proporcionamos permisos suficientes al usuario (‘pi’ en este caso) sobre el fichero haciendo:

1
pi@raspberrypi:~/duck $ chmod 700 duck.sh

Ahora que ya hemos proporcionado permisos vamos a crear un crontab. Un crontab no es más que un fichero que permite especificar comandos que queremos que se ejecuten tras ciertas condiciones (normalmente de tiempo). Nos sirve por ejemplo para ejecutar un programa tras cada reinicio pero en este caso vamos a hacer que ejecute el script que hemos definido antes una vez cada hora todos los días (esta frecuencia podemos cambiarla).

Para hacerlo escribimos:

1
2
# Creamos un crontab (elegimos un editor para abrirlo)
pi@raspberrypi:~/duck $ crontab -e

, y dentro del fichero abierto con el editor (nano por ejemplo) bajamos hasta el final (después de las líneas comentadas) y añadimos:

1
2
3
4
5
6
7
8
# Ejecutar duck.sh cada hora todos los días; podeis ver sobre el formato usado en crontab.guru. Los asteríscos representan 'cualquier valor'. 
*/* 1 * * * ~/duck/duck.sh

# Si queremos cambiar la frecuencia, por ejemplo a 30 minutos:
*/30 * * * * ~/duck/duck.sh

# Usualmente, la documentación especifica 5 minutos:
*/5 * * * * ~/duck/duck.sh

Nuevamente, guardamos con ‘Ctrl + X’ y ya podemos probar a ejecutar por primera vez el script. Para ello solo tenemos que hacer:

1
2
# Ejecutar script .sh
pi@raspberrypi:~/duck $ ./duck.sh

Esta ejecución debería devolvernos la siguiente respuesta (puede tardar unos segundos):

1
2
3
4
5
# Respuesta al comando ejecutado
%   Total     % Received % Xferd  Average Speed  Time   Time   Time  Current
                                  Dload  Upload  Total  Spent  Left  Speed
100     2     0     2    0     0      2      0 --:--:-- --:--:-- --:--:-- 2 
pi@raspberrypi:~/duck $

Tras esta ejecución se habrá creado el fichero ‘duck.log‘ al que hicimos referencia más arriba; podemos verlo escribiendo dir ó ls en la consola y veremos que está ahí. Si queremos consultar su contenido, escribimos cat duck.log y veremos que el contenido del fichero pone ‘OK‘. Si esto es así, lo hemos hecho todo bien.

En este momento cobra sentido uno de los cambios que hicimos antes que fue cambiar la IP pública en DuckDNS por la de algún servidor DNS público. Si todo ha ido bien, podemos volver a la web de DuckDNS y deberemos ver que el campo ‘current ip‘ ha vuelto a cambiar por nuestra IP pública. Vamos por el buen camino.

Hecho esto, reiniciamos el dispositivo escribiendo sudo reboot y podemos pasar al siguiente y último paso. El crontab que creamos antes seguirá ejecutando el comando aunque se reinicie.

Redirección de puertos (port-forwarding)

Esta es quizás la parte más difícil simplemente porque cada router es un mundo y no hay pasos específicos que sirvan para todos. En ESTA página hay una gran cantidad de modelos listados con guías para cada uno pero por lo general deberemos buscar en el panel de administración de nuestro router una opción llamada ‘Redirección de puertos‘, ‘Puertos‘, ‘Port forwarding‘, ‘Redireccionamiento‘ o similares.

Por cierto, ¿hemos dicho ya que nuestro dispositivo debe tener una IP fija DENTRO de la red local? Esto no cuesta nada y normalmente la mayoría de routers ‘caseros’ una vez asociada una IP local a un dispositivo no suelen cambiarla, peeeeero nunca viene mal si podemos asegurarnos de que le estamos dando una IP fija al dispositivo desde el panel de administración.

¿Por qué? Básicamente porque queremos dar acceso por SSH a nuestra Raspberry Pi, no a cualquier dispositivo de la casa conectado a internet, ¿verdad? ¿¡VERDAD!?

Una vez que nos hemos asegurado de esto, vamos a especificar una regla para exponer el puerto 22 (que es el puerto usado por SSH) del dispositivo (si no lo hemos modificado). Especificamos el puerto (que en algunos casos debe expresarse cómo rango), similar para el puerto interno que el externo, especificamos la IP local del dispositivo y nos aseguramos de seleccionar TCP (Protocolo de Control de Transmisión), NO UDP (Protocolo de Datagramas de Usuario) ni TCP+UDP. Guardamos los cambios y salimos del panel de administración del router.

Panel del router

Funcionamiento

De la misma forma que trabajamos con nuestro dispositivo por SSH accediendo con ssh [email protected] aquí haremos lo mismo pero cambiando el destino, es decir, en lugar de especificar la IP privada 192.168.X.X, escribiremos el dominio que hemos creado:

ssh [email protected]

Aceptamos el aviso que devuelve la terminal de Windows (si estamos usando Windows) y listo, si todo ha ido bien deberíamos estar viendo la terminal del dispositivo. ¡OJO!, esta prueba debemos hacerla desde una red externa para asegurarnos de que está funcionando; no tendría mucho sentido hacerlo desde la misma red en la que está conectada la Raspberry Pi.

This post is licensed under CC BY 4.0 by the author.

Comenzando con Home Assistant de cero en 2021

Instalación y configuración de acceso SSH a Home Assistant