Archivo por días: 10 febrero, 2021

Acceso remoto con IP dinámica

Poder acceder a tus datos en cualquier momento, aunque no estés es casa, es una maravilla: abrir un FTP y poder copiar cualquier cosa desde tu ordenador siempre es muy práctico. Por desgracia, en la práctica suele haber dos problemas:

  • Si tu ordenador está apagado y no hay nadie en casa, no puedes acceder
  • Si tienes IP dinámica es probable que no sepas cual tienes en un momento determinado

Hay gente que nunca apaga su PC, pero ese no es mi caso: prefiero tenerlo apagado cuando no lo utilizo. Por otro lado, aunque mi proveedor de internet es bastante razonable en cuanto a las IPs dinámicas (intenta darte siempre la misma), alguna que otra vez cambia. Por eso quería encontrar una solución que me permitiese acceder de manera cómoda a mi equipo siempre que quiera. Y la encontré en Telegram.

Básicamente se me ocurrió crear un pequeño bot de Telegram que corre en una Raspberry Pi que utilizo como servidor multimedia en casa y que, por tanto, siempre está encendida. Este bot acepta dos comandos:

  • ¿Cual es la IP externa? Para ello el bot, que corre en local, utiliza uPnP para preguntar al router cual es la dirección IP actual, y responde con un mensaje indicándola.
  • Encender ordenador principal, cosa que hace mediante WakeOnLan.

Con estas dos opciones ya tengo acceso constante a mi ordenador desde el exterior sin necesidad de tenerlo encendido todo el rato ni de jugar a la ruleta para ver si conservo la misma IP que la última vez que me conecté. Este es el código:

#!/usr/bin/env python3

import telegram
from telegram.ext import Updater, CommandHandler
import miniupnpc
from wakeonlan import send_magic_packet

# la MAC del equipo a encender
mad_addr = 'XX:XX:XX:XX:XX:XX'

# El token de nuestro bot
updater = Updater("XXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY")

# Solo nos autorizamos a nosotros, para evitar que se nos cuelen hasta la cocina
def check_id(update):
    """ Incluir comprobación de identidad. Si es correcta, devolver TRUE;
        si no, devolver FALSE """
    if update.message.from_user.id != "XXXXXXXXXXX":
        return False
    return True


# Devuelve un mensaje de Telegram con la IP actual
def get_ip(bot, update):

    if check_id(update):
        u = miniupnpc.UPnP()
        u.discoverdelay = 200
        u.discover()
        u.selectigd()
        update.message.reply_text("IP externa: {:s}".format(u.externalipaddress()))
    else:
        update.message.reply_text("Acceso denegado")


# Utiliza WakeOnLan para encender el equipo
def encender(bot, update):
    if check_id(update):
        send_magic_packet(mac_addr)
        update.message.reply_text("Encendiendo")
    else:
        update.message.reply_text("Acceso denegado")


# Configuramos nuestro bot con los comandos nuevos
updater.dispatcher.add_handler(CommandHandler('ip', get_ip))
updater.dispatcher.add_handler(CommandHandler('encender', encender))

# y lo lanzamos
updater.start_polling()
updater.idle()

Utiliza los módulos python-telegram-bot, wakeonlan y miniupnpc. Como vemos, se definen dos comandos, ip y encender. Eso sí, hay que configurar algunas cosas:

  • En primer lugar, necesitamos obtener un token de Telegram para nuestro bot.
  • En segundo lugar, hay que poner la dirección MAC del equipo que queremos encender.
  • En tercer lugar, hay que configurar qué usuario tiene derecho a ejecutar los comandos, en la función check_id(). Esto es necesario para evitar que cualquiera se pueda abrir una conversación con nuestro bot y «tocarnos las narices».

Por motivos obvios he eliminado los valores de mi token, dirección MAC, y los parámetros que compruebo para certificar la validez del usuario. Cada uno debe poner los suyos propios.

Una vez hecho esto queda la segunda parte: garantizar que se lance siempre que se arranque la placa. En teoría parecería que no sería necesario si siempre va a estar encendida, pero ya sabemos que, a veces, se va la luz, o hay que reiniciarla para instalar actualizaciones… por eso hay que añadir un fichero para convertirlo en un servicio systemd, de manera que se arranque siempre automáticamente. Este es el fichero que utilizo yo:

[Unit]
Description = Lanzar telegrambot
After = network.target
[Service]
Restart = always
RestartSec = 1
ExecStart = /usr/bin/encenderbot.py
[Install]
WantedBy = multi-user.target

El cual, obviamente, asume que he copiado el código anterior en /usr/bin/encenderbot.py. Este fichero se llamará encenderbot.service y se copiará en /etc/systemd/system. Una vez copiados los ficheros basta con ejecutar:

systemctl start encenderbot.service

para lanzarlo, y

systemctl enable encenderbot.service

para que se lance automáticamente en cada arranque.

Por último, queda un detalle importante por resolver, y es que GMD3, por defecto, tiene activado el ahorro de energía, lo que significa que si encendemos el ordenador pero no nos identificamos, al cabo de unos minutos (en torno a 20) el ordenador entrará en suspensión. Esto es un problema, pues nos obligaría a enviar de vez en cuando la señal de WakeOnLan, además de cortar cualquier conexión que tengamos si dura más de 20 minutos. Para resolverlo tenemos que desactivar dicha suspensión. Sin embargo, no basta con quitarla en nuestro panel de configuración, porque eso sólo influye en nuestra sesión. Tenemos que hacerlo para GDM3, que se ejecuta como un usuario diferente, y para ello utilizaremos estos comandos:

xhost +
sudo -u gdm dbus-launch gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'
sudo -u gdm dbus-launch gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing'
xhost -

El primer comando desactiva la seguridad en X11 y es necesario si estamos en Wayland, fundamentalmente. El segundo configura GDM3 para que no entre en suspensión cuando el equipo está conectado a la corriente, y el tercero para lo mismo pero cuando está alimentado con baterías. El cuarto reactiva la seguridad en X11. Un detalle importante es que, en Debian, el usuario no es gdm, sino Debian-gdm, por lo que si utilizamos ese sistema operativo o uno derivado, lo más probable es que haga falta que los comandos empiecen con sudo -u Debian-gdm dbus-launch…

Y con esto ya tenemos una manera de conocer en todo momento nuestra IP externa y de encender nuestro ordenador de manera remota. Ahora sólo nos queda ir a nuestro Telegram, buscar a nuestro bot con el nombre que le dimos al crearlo, e iniciar un chat con él para poder enviarle los comandos.