Der smart-home-control Server ist aus Sicherheitsgründen nur sehr eingeschränkt von außen zu erreichen. Trotzdem sollen bestimmte Funktionlitäten, wie zum Beispiel Push-Benachrichtigungen oder Alexa Anbindung möglich sein. Außerdem muss intern auch HTTPS verfügbar sein (idealerweise nicht selbst-signiert, weil das auf allen Geräten eingerichtet werden müsste). Die Seite hier beschreibt, wie das funktioniert und eingerichtet wird.
0. Allgemeine Funktionsweise
Die beteiligten Server sind:
- Der smart-home-control Raspi, der nur aus dem Smart-Home LAN vollständig erreichbar ist. Aus dem MWN kann man sich (via Portfreigabe auf der FritzBox) per SSH verbinden. Von ganz außen geht keine Verbindung.
- Der teachtum40 Server, der aus bestimmten MWN Adressen SSH Verbindungen erlaubt, von ganz außen aber nur HTTP(S).
Verbindungen von außen nimmt also der teachtum40 Server per HTTPS entgegen. Jeder Client, der sich darüber per Socket.io verbindet, muss ganz am Anfang ein Token schicken (sio.emit("login", "<token>")
), damit er Zugriff auf die smart-home-control API bekommt. Je nach Token lässt sich konfigurieren, welche spezifischen Zugriffe erlaubt sind.
Das Token bekommt der Client entweder aus dem internen Netz (dazu ruft er https://smart-home-internal.teachtum40.../token
ab (tbd)), oder er hat es woanders her. Zum Beispiel könnte man es in URLs / scannbare QR-Codes einbetten.
1. Zertifikat-Forwarding
Damit der Smart-Home-Server Let's Encrypt Zertifikate erhalten kann, obwohl er nicht von außerhalb des MWN ereichbar ist, werden die Zertifikate vom teachtum40 Server generiert, und mithilfe eines Post-Hooks per SCP an den smart-home-server übertragen.
Einrichtung der SCP-Übertragung
Damit wirklich nur die Übertragung des Zertifikats möglich ist, wird für den teachtum40 Server ein eigenes SSH Keypair generiert (auf dem teachtum40 Server):
ssh-keygen -t ed25519 -b 4096 -C "certificate-forwarder@digillab" -f id_ed25519_cert_forwarder
Das neue Keypair wird als id_ed25519_cert_forwarder(.pub)
gespeichert.
Auf dem Smart Home Server kann man jetzt einen Zielordner erstellen, an den der teachtum40 Server hinkopieren kann:
sudo mkdir /srv/from-teachtum40
sudo chown pi:pi /srv/from-teachtum40
Dann fügt man den Public Key von Forwarder (id_ed25519_cert_forwarder.pub
) auf dem Pi hinzu:
echo 'from="138.246.225.122,2001:4ca0:800::8af6:e17a",restrict,command="scp -r -v -t /srv/from-teachtum40/" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICCHnczUZaDTfj/2muKX4A32fsGsq8LH3DzC7Du4UfFz certificate-forwarder@digillab' >> ~/.ssh/authorized_keys
(Public Key und IP Adressen ggf. ändern)
Durch Angabe der IPs kann der Key nur für Verbindung von der gegebenen IP Adresse verwendet werden.
Mit dieser Konfiguration kann der teachtum40 Server jetzt Dateien in das oben erstellte Verzeichnis kopieren:
scp -i /pfad/zu/id_ed25519_cert_forwarder -o StrictHostKeyChecking=no lokale-datei-zum-kopieren.txt pi@10.162.111.146:
(IP Adresse ggf. ändern)
Falls ein Fehler kommt, dass die Berechtigungen für den private Key zu locker sind, kann man das einschränken mit:
chmod u=rw,g=,o= id_ed25519_cert_forwarder*
Certbot Post-Hook
Zum Schluss richtet man noch den Post-Hook ein. Dazu gibt man das neue Zertifikat den root user, unter dem der renewal läuft (in /etc/cron.d/certbot
):
sudo cp id_ed25519_cert_forwarder* /root/
Und erstellt eine Datei /etc/letsencrypt/renewal-hooks/deploy/forward_certificate.sh
mit dem Inhalt:
#!/bin/bash
scp -q -r -i /root/id_ed25519_cert_forwarder -o StrictHostKeyChecking=no /etc/letsencrypt/live/<die-domain>.de pi@10.162.111.146: > /dev/null 2>&1
(Domain und IP ggf. ändern)
Bei der Ersteinrichtung des Zertifikats muss man das Skript einmal von Hand laufen lassen:
sudo /etc/letsencrypt/renewal-hooks/deploy/forward_certificate.sh
2. Port-Forwarding (für den Socket.io Server)
Auf die gleiche Art wie das Zertifikat-Forwarding, lässt sich ein Port-Forwarding einrichten, bei dem sichergestellt wird, dass das nur für den teachtum40 Server möglich ist. Deswegen hier etwas abgekürzt:
Auf teachtum40:
ssh-keygen -t ed25519 -b 4096 -C "port-forwarder@digillab" -f id_ed25519_port_forwarder
sudo cp id_ed25519_port_forwarder* /root/
# Public Key lesen und kopieren:
cat id_ed25519_port_forwarder.pub
Auf dem smart-home-control:
echo 'from="138.246.225.122,2001:4ca0:800::8af6:e17a",restrict,port-forwarding,permitopen="localhost:3030",command="sleep infinity" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINgFE3nxYE/GEtwltRsa81/DuWDbeUXM7Y9Q+S0vFjaT port-forwarder@digillab' >> ~/.ssh/authorized_keys
Zum Schluss den Service dazu auf teachtum40 einrichten:
sudo vim /etc/systemd/system/smart-home-forwarder.service
und befüllen mit:
[Unit]
Description=Port forwarding SSH script
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/usr/bin/ssh -v -i /root/id_ed25519_port_forwarder -o StrictHostKeyChecking=no -L 3031:localhost:3030 pi@10.162.111.146 dummy-cmd
[Install]
WantedBy=multi-user.target
Und dann:
sudo systemctl enable smart-home-forwarder
sudo systemctl start smart-home-forwarder