Sicherer Zugang zu einem Smart Home ohne öffentliche IP (Teil 1)

Einführung


Es ist schwierig, einen umfangreichen Titel zu wählen, der die Bedeutung widerspiegelt, daher werde ich sofort die Aufgabe beschreiben, die ich mir selbst gestellt habe.

Es gibt ein "Smart Home". In meinem Fall ist dies ein lüfterloser Heimserver mit ioBroker, obwohl dies nicht wichtig ist. Zusätzlich zu den Haushaltsgegenständen möchte ich Sensoren von außen daran anschließen (z. B. an einem ESP32 aus einem entfernten Gewächshaus). Ich habe mich dazu entschlossen, dies über mqtt zu tun. Zugriff auf die Schnittstelle über das Internet.

Das Übliche. Aber es gibt Nuancen:

  • Der Anbieter hat keine Möglichkeit, mir eine öffentliche IP-Adresse zu geben. Und es gibt keine anderen Anbieter.
  • Ich bin nicht gerne an bestimmte Cloud-Dienste gebunden. Ein externer Dienst kann ebenfalls geschlossen werden (da gbridge kürzlich eine Benachrichtigung gesendet hat). Und nur im Fehlerfall ist nicht klar, was zu tun ist. Ich bevorzuge meine eigene, die übertragen werden kann und mit wenig Blut wiederholt wird, wenn etwas passiert.
  • Sicherheit ist wichtig. Keine Paranoia, sondern ioBroker ins Internet stellen, vor allem angesichts der Tatsache, dass mehrere Dienste ausgestellt sind (Flot ...). Nicht wirklich.

Weiter möchte ich nicht sofort das Ergebnis zeigen, sondern den Prozess. Wie es ging, wie Wunschliste transformiert wurde, Entscheidungen geändert. Es ist möglich, dass einige Punkte korrekter / effizienter gelöst werden können (ich bin kein Systemadministrator, kein Entwickler). Oder vielleicht geht jemand nicht so weit und nutzt eine Zwischenlösung, die ich zum Beispiel für mich nicht sicher oder bequem fand. Eigentlich ist das, was in diesem Teil beschrieben wird, eine ziemlich funktionierende Option, aber für mich ist es "mittelschwer".

Öffentliche Adresse für mqtt


Zu Hause leuchtet die öffentliche IP auf dem Router nicht (ich spreche nicht von fest, dies kann durch Dyndns und Analoga gelöst werden), nämlich der Anbieter gibt 10.x.x.x ohne Optionen. Sie müssen also einen kleinen VPS mieten und einen Probros daraus machen.

Am einfachsten ist es, durch ssh zu tunneln. Auf dem Heimserver (ich werde es iob.xxx.xx nennen) führe ich Folgendes aus:

ssh -N -T -R pub.xxx.xx:1883:127.0.0.1:1883 a@iob.xxx.xx 

Wenn Sie eine Verbindung zu Port 1883 des externen Servers pub.xxx.xx herstellen, befinden Sie sich in Wirklichkeit auf Ihrem Heim-iob: 1883, während der mqtt-Container (Moskito) ausgeführt wird.

Natürlich ist es notwendig, dass dies automatisch startet, die Verbindung wird nach einem Fehler wiederhergestellt. Deshalb habe ich autossh verwendet und es als Service entworfen.

/etc/systemd/system/ssh_mqtt.service:

[Unit]
Description=SSH Tunnel mqtt
After=network.target

[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR pub.xxx.xx:1883:127.0.0.1:1883 -i /home/a/.ssh/id_rsa a@pub.xxx.xx

[Install]
WantedBy=multi-user.target

Alle Arten von systemctl aktivieren / neu starten usw. Ich werde nicht beschreiben.

Leider wurde ich trotz Autossh von ständigen Einfrierungen heimgesucht. Daher entschied ich, dass keine Entitäten erstellt werden müssen, und entschied mich für das übliche ssh:

/etc/systemd/system/ssh_mqtt.service:

[Unit]
Description=SSH Tunnel mqtt
After=network.target

[Service]
Restart=always
RestartSec=20
User=anri
ExecStart=/bin/ssh -N -T -R pub.xxx.xx:1883:127.0.0.1:1883 -i /home/a/.ssh/id_rsa a@pub.xxx.xx

[Install]
WantedBy=multi-user.target

In der Folge stellte sich übrigens heraus, dass dieser Anbieter so schräg ist. Nun, oder der günstigste Preis für 45 Rubel / Monat funktioniert so schief für ihn. Die Sitzung hängt regelmäßig, auch wenn sie einfach über ssh (MobaXterm) verbunden ist. Am Ende bestellte ich mir einen VPS von einem anderen (55 Rubel / Monat) und die Probleme mit dem Einfrieren verschwanden.

Übrigens habe ich mir selbst ausgesucht, wo ich VPS nicht nur auf der Grundlage des Preises, sondern auch unter Berücksichtigung von Ping (10-20 ms) einsetzen soll.

Im Allgemeinen ist diese Option ganz normal, insbesondere wenn man bedenkt, dass ich später eine Internetverbindung ausschließlich zu Port 8883 über TLS hergestellt habe. Jene. Das Passwort für Moskito wurde verschlüsselt übertragen.

Anschließend werden Kundenzertifikate obligatorisch. Jene. Auf TLS-Ebene müssen Sie zunächst ein Client-Zertifikat vorlegen und sich dann mit dem in mosquito angegebenen Kennwortnamen anmelden. Jene. Es ist nicht so einfach, zur Phase der Passwortsuche zu gelangen.
Dementsprechend habe ich zuerst das Serverzertifikat von LetsEncrypt verwendet und dann aufgrund der Notwendigkeit von Clientzertifikaten auf Selbstsignierung umgestellt.

Da ich dabei auch an der Software für ESP32 gearbeitet habe, habe ich festgestellt (oder dachte nur, ich erinnere mich nicht mehr), dass bei Problemen mit der VPN-Verbindung der Akku viel schneller verbraucht wird. Während des normalen Betriebs läuft der Zyklus ab: Aufwachen, die Sensoren mit Strom versorgen, eine Verbindung zum WLAN herstellen, eine Verbindung mit dem mqtt-Server herstellen, die Sensorwerte lesen, sobald sie bereit sind, auf mqtt übertragen, die Sensoren ausschalten, 10 Minuten in den Tiefschlaf gehen.

Normalerweise dauert ein solcher Zyklus ungefähr 4 Sekunden. 1,5-2 Sekunden - Verbindung zu WiFi, eine zusätzliche Sekunde aufgrund des Übergangs zu mqtt über TLS. Es passt zu Ihnen für 4 Sekunden, trotzdem brauchen die Sensoren Zeit, um aufzuwachen. Aber was soll ich tun, wenn das VPN ausfällt (es war deutlich sichtbar, als der Autossh abfiel)? Natürlich habe ich so eingerichtet, dass das System nach 20 Sekunden sowieso einschlafen würde. Aber 20 Sekunden statt 4 sind sehr auffällig.

Im Allgemeinen habe ich beschlossen, dass es besser ist, den mqtt-Server auf einem externen VPS zu belassen. Jetzt, da alles wie eine Uhr funktioniert, bin ich mir nicht sicher, ob dies notwendig ist. Aber ich sehe keinen Sinn darin, es wieder herzustellen.

Öffentliche Adresse für Vis


Vis ist ein beliebtes Visualisierungssystem bei ioBroker. Sie konnten sich nicht die Mühe machen, es selbst auf https zu konfigurieren und ebenfalls nur den Port weiterzuleiten. Darüber hinaus kann sie auf Anwendungsebene nach einem Passwort fragen.

Das ist aber nicht cool. Besonders wenn man bedenkt, dass es für die Arbeit zusätzliche Dienste verbindet. Angenommen, ich zeichne Diagramme im Flot, relativ gesehen verbinde ich mich mit vis.xxx.xx : 8082 / vis / index.html, aber im Inneren befinden sich Links zu vis.xxx.xxx- Diagrammen : 8082 / flot / index.html. Irgendwann stellte sich heraus, dass beim Herstellen einer Verbindung zu / vis ein Kennwort abgefragt wird und auf die Grafikoberfläche ohne Kennwort zugegriffen werden kann.

In einigen Momenten war es im Allgemeinen seltsam - ich wurde auf vis autorisiert, ich sehe die Grafik, aber unten rechts befindet sich ein durchscheinendes Fenster „Keine Verbindung zum Server“. Dieser CSS-Block wurde neu geschrieben, um ihn auszublenden. Sobald ich jedoch anfing, mit Frame zwischen Diagrammen auf demselben Bildschirm zu wechseln, stellte sich heraus, dass meine Überlappung auf dem Display im Frame nicht funktionierte. (Wie sich später herausstellte, sollte es so sein). Ich schalte die Autorisierung aus - alles ist in Ordnung, kein Fluchen.

Also habe ich mich für denselben externen Server entschieden, um nginx im Reverse-Proxy-Modus zu erhöhen. Und schon autorisieren.

Über den Browser hat es funktioniert. Die native Anwendung iobroker.vis vom Play Market konnte sich jedoch nicht auf diese Weise anmelden. Und ich wollte es benutzen. Dies ist zwar eigentlich ein Browser im Fenster, aber es hat eine Reihe von netten Funktionen. Nehmen wir an, Sie stellen den Maßstab ein (93% im vertikalen Modus) und das Bild passt. Auf einem anderen Gerät mit einer anderen Bildschirmauflösung wählen Sie einfach den Koeffizienten aus und fertig. Und im Browser müssen Sie jedes Mal anpassen ...

Okay, denke ich. Ich werde der URL anstelle des Passworts einen kniffligen Code hinzufügen. Typ vis.xxx.xx : 8082 / <lange Sequenz> /vis/index.html. Oft wird ein solcher Trick angewendet.

Fast verdient. Aber mit Pannen zeigte das Graben, dass diese Webanwendung nicht richtig geschrieben wurde. Viele Links darin sind nicht relativ, sondern von der Wurzel.

Okay, ich habe mehrere Links gefunden, die ich für sie geschrieben habe. Sie sagen, wenn der Referrer solchen Code enthält, vertraue immer noch, schreibe die URL neu usw. Aber sie kamen allmählich ans Licht. Also habe ich entschieden, dass dies schief und falsch ist und ein anderer Ansatz erforderlich ist.

VPN


Ich beschloss, ein wenig Zugangsuniversalität zu opfern. Lassen Sie mich von meinem Laptop oder Smartphone aus zugreifen. Aber von den Geräten anderer Leute ist das Internetcafé nicht notwendig, ich werde es schaffen. Dann können Sie einen kleinen Client einrichten, der das VPN installiert. Und darin ist weder SSL noch Autorisierung erforderlich. Gleichzeitig müssen Sie die Links nicht wiederholen.

Der einfachste Weg für mich war Zerotier. Für mein Betriebssystem (Windows, Android, Linux) gibt es Clients. Und es gibt sogar fertige im Docker. Ja. Ich führe alles in Docker aus, über die Funktionen davon später.

Sie installieren den Client, geben einen eindeutigen Code für Ihr Netzwerk ein und bestätigen ihn in der Weboberfläche auf my.zerotier.com. Legen Sie bei Bedarf eine statische Adresse in Ihrem persönlichen privaten Netzwerk fest (a la 10.20.30.0), und fertig. Alle verbundenen Clients sehen sich.

Das einzige, mit dem ich mich ein bisschen befassen musste, war "wie man von einem Gerät in Ihrem Heim-WLAN aus eine Verbindung zu einem Remote-Server herstellt, ohne den Client zu starten". Nun, mein Heimserver ist bereits ein Client, auch wenn er sich selbst weiterleitet. Es stellte sich heraus, dass alles einfach ist. Das Heimnetzwerk 192.168.x.0 sollte auf my.zerotier.com im Abschnitt Verwaltete Routen registriert sein und als Gateway angeben. Dies ist natürlich mein Heimserver. Nun, konfigurieren Sie im WiFi-Netzwerk die Route entsprechend (auf dem WiFi-Router statisch 10.20.30.0 auf dem Heimserver).

Wenn Sie einen Zerotier-Client verbinden, können Sie einen anderen DNS-Server angeben. Jene. Ich habe den Client verbunden, und der Domänenname wird nicht in eine öffentliche, sondern in eine private Adresse aufgelöst, da DNS jetzt auf den Heimserver verweist, auf dem dnsmasq für einzelne IP-Einträge aus dem privaten Zerotier-Netzwerk aktiviert ist.

Sogar Zerotier war mit der effektiven Wahl einer Verbindungsroute zufrieden. Wenn ich einen Zerotier-Client in Heim-WLAN aktiviere, dauert das Pingen an den Heimcomputer (dessen von Zerotier ausgegebene IP-Adresse) die gleichen Millisekunden wie ohne Client (nur über WLAN). Jene. Die Verbindung zur Cloud wird erst im ersten Moment hergestellt. Der weitere Verkehrsaustausch erfolgt direkt und nicht über die Cloud. Wenn Sie beispielsweise OpenVPN auf VPS installieren, wurde derselbe Datenverkehr vom Client zum VPS und dann zurück zum gleichen WiFi-Netzwerk zum Heimserver ausgeführt.

Im Prinzip gibt es sogar einen Chip für Ihre Mond-Server. Fast in einem vom Internet abgeschnittenen Netzwerk soll all diese Wirtschaft eingesetzt werden.

Was ist das Ergebnis?


ESP32 sendet seine Daten an den auf dem VPS bereitgestellten mqtt-Server. Über TLS ist ein Client-Zertifikat erforderlich.

Ein VPN über Zerotier wird mit dem Heimserver installiert. Sonoff rfBridge kommuniziert mit der Tasmota-Firmware über diesen Heimserver von mqtt bis VPS. Es gibt keine Möglichkeit, TLS mit einem Client-Zertifikat festzulegen. Deshalb ist der übliche MQTT für 1883 konfiguriert. Schließlich verschlüsselt der Heimserver diesen Datenverkehr mit Zerotier.

Nun, ich verbinde mich direkt vom Heimnetzwerk und vom Internet aus mit vis, indem ich den Zerotier-Client aktiviere. Sie können es überhaupt nicht ausschalten, das funktioniert auch. Aber nur manchmal brauche ich andere VPN-Clients (zB zum "ILV-verboten"). Zwei VPNs auf einem Smartphone wurden nicht sofort Freunde, aber ich verstand nicht.

Alles ist sehr einfach. Aber der Wurm verschluckte die Seele. Ich habe zwar keinen Kernreaktor, aber plötzlich? Es gab einen Fall, in dem sie TeamViewer (ein Unternehmen, nicht speziell Client-Software) brachen und durch sie Zugriff auf viele Konten erhielten. Und im Allgemeinen habe ich ganz am Anfang geschrieben, dass ich alles liebe, was mir gehört.
Im nächsten Schritt wechselte ich von Zerotier zu OpenVPN. Alles ist in meinen Händen.

Der einzige "Außerirdische" ist der VPS des Anbieters. Nun, ich starte speziell alles in Docker-Containern, um mich sofort bewegen zu können.
Wenn ich wüsste, wie viel ich mit OpenVPN zu tun haben würde, würde ich es vielleicht nicht tun. Fairerweise - die Hauptprobleme waren genau wegen der Container.

Fazit


Im nächsten Artikel werde ich über OpenVPN und die Konfigurationsfunktionen in meinen Bedingungen (Container, Routing anderer Geräte aus dem Heimnetzwerk) sprechen. Es wird mehr Konfigurationen, technische Details und Schwierigkeiten geben. Aber sofort begann der zweite Teil nicht ohne dies zu schreiben. Es wäre nicht klar, warum solche Perversionen überhaupt notwendig sind.

Und für alle Fälle eine Frage für diejenigen, die wissen: Obwohl ich ein VPS und ein kleines (512 MB RAM) habe, wird es weniger als 1% verwendet. Docker-Statistiken:

Bild

Und ich hatte die Idee, alles wie einen Container auf einem Google Cloud Run, Amazon Fargate oder ähnlichem zu starten. Die Bereitstellung eines Servers mit allen Arten von fail2ban über ansible ist kein Problem. Installieren Sie auch Docker. Aber warum, wenn Sie nur einen kleinen Teil seiner Ressourcen benötigen?

Nach meinen Berechnungen würde mich das gleiche Fargate jedoch um ein Vielfaches kosten.

Vielleicht habe ich etwas nicht verstanden? Es wäre also interessant, einen kleinen Container nur für die Weiterleitung des Hafens nach Hause zu haben und nicht einen ganzen VPS. Das gibt es nicht?

All Articles