Accès sécurisé à une maison intelligente en l'absence d'une adresse IP publique (partie 1)

introduction


Il est difficile de choisir un titre volumineux qui reflète le sens, je décrirai donc immédiatement la tâche que je me suis fixée.

Il y a une "maison intelligente". Dans mon cas, il s'agit d'un serveur domestique sans ventilateur avec ioBroker, bien que ce ne soit pas important. En plus de la maison, je veux y accrocher des capteurs de l'extérieur (par exemple, sur un ESP32 d'une serre distante). J'ai décidé de le faire via mqtt. Accès à l'interface depuis Internet.

La chose habituelle. Mais il y a des nuances:

  • Le fournisseur n'a aucun moyen de me donner une adresse IP publique. Et il n'y a pas d'autres fournisseurs.
  • Je n'aime pas me lier à des services cloud spécifiques. Un service externe peut également fermer (car gbridge a récemment envoyé une notification). Et juste en cas d'échec, on ne sait pas quoi faire. Je préfère le mien, qui peut être transféré, refait avec peu de sang si quelque chose se passe.
  • La sécurité est importante. Pas de paranoïa, mais mettre ioBroker sur Internet, d'autant plus qu'il existe plusieurs services exposés (flot ...). Pas vraiment.

De plus, je veux montrer non pas immédiatement le résultat, mais le processus. Comment cela s'est passé, comment la liste de souhaits a été transformée, les décisions ont changé. Il est possible que certains points puissent être résolus plus correctement / efficacement (je ne suis pas un administrateur système, pas un développeur). Ou peut-être que quelqu'un n'ira pas aussi loin et ne bénéficiera pas d'une solution provisoire que, par exemple, je n'ai pas trouvée sûre ou pratique pour moi. En fait, ce qui est décrit dans cette partie est tout à fait une option de travail, mais pour moi, c'est «intermédiaire».

Adresse publique de mqtt


À la maison, l'IP publique sur le routeur ne brille pas (je ne parle pas de fixe, cela peut être résolu via des dyndns et des analogues), à savoir, le fournisseur donne 10.x.x.x, sans options. Donc, vous devez louer un petit VPS et en faire un probros.

Le moyen le plus simple est de passer par ssh. Sur le serveur domestique (je l'appellerai iob.xxx.xx) j'exécute:

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

En vous connectant au port 1883 du serveur externe pub.xxx.xx, vous vous retrouvez en réalité sur votre iob domestique: 1883 avec le conteneur mqtt (moustique) en marche.

Naturellement, il faut que cela démarre automatiquement, la connexion est rétablie après une panne. Par conséquent, j'ai utilisé autossh, le concevant comme un service.

/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

Toutes sortes d'activation / redémarrage du système, etc. Je ne décrirai pas.

Malheureusement, malgré l'autossh, j'ai été hanté par des gels constants. J'ai donc décidé qu'il n'était pas nécessaire de produire des entités et j'ai opté pour le ssh habituel:

/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

Par la suite, au fait, il s'est avéré que ce fournisseur était tellement oblique. Eh bien, ou le tarif le moins cher pour 45 roubles / mois fonctionne si mal pour lui. La session se bloque périodiquement, même lorsqu'elle est simplement connectée via ssh (MobaXterm). Donc à la fin je me suis commandé un VPS d'un autre (55 roubles / mois), et les problèmes de gel ont disparu.

Au fait, j'ai choisi moi-même où prendre les VPS non seulement sur la base du prix, mais aussi en tenant compte du ping (10-20 ms).

En général, cette option est tout à fait normale, d'autant plus que j'ai ensuite établi une connexion Internet exclusivement au port 8883 via TLS. Ceux. Le mot de passe du moustique a été transmis crypté.

Par la suite rendu les certificats clients obligatoires. Ceux. tout d'abord, au niveau TLS, vous devez présenter un certificat client, puis connectez-vous avec le nom de mot de passe spécifié dans moustique. Ceux. il n'est pas si facile d'accéder à la phase de recherche de mot de passe.
En conséquence, j'ai d'abord utilisé le certificat de serveur de LetsEncrypt, puis, en raison du besoin de certificats clients, je suis passé à l'auto-signature.

Étant donné que dans le processus, j'ai également travaillé sur le logiciel pour ESP32, j'ai remarqué (ou pensais simplement, je ne me souviens plus) que lorsqu'il y a des problèmes avec la connexion VPN, la batterie sera consommée beaucoup plus rapidement. Pendant le fonctionnement normal, le cycle: réveillez-vous, mettez les capteurs sous tension, connectez-vous au WiFi, établissez une connexion avec le serveur mqtt, lisez les lectures des capteurs lorsqu'ils sont prêts, transférez-les vers mqtt, coupez l'alimentation des capteurs, dormez profondément pendant 10 minutes.

Normalement, un tel cycle prend environ 4 secondes. 1,5-2 secondes - connexion au WiFi, une seconde supplémentaire en raison de la transition vers mqtt via TLS. Cela vous convient pendant 4 secondes, tout de même, les capteurs ont besoin de temps pour se réveiller. Mais si le VPN tombait en panne (il était clairement visible lorsque l'autossh est tombé), que dois-je faire? Bien sûr, je me suis mis en place pour qu'après 20 secondes le système s'endorme quand même. Mais 20 secondes au lieu de 4 est très perceptible.

En général, j'ai décidé qu'il vaut mieux garder le serveur mqtt sur un VPS externe. Maintenant que tout fonctionne comme une horloge, je ne sais pas si c'est nécessaire. Mais je ne vois aucun sens à le refaire.

Adresse publique pour Vis


Vis est un système de visualisation populaire chez ioBroker. Vous ne pouviez pas déranger, et configurez-le vous-même sur https et de même, transférez simplement le port. De plus, elle peut demander un mot de passe au niveau de l'application.

Mais ce n'est pas cool. Surtout si l'on considère que pour le travail, il connecte des services supplémentaires. Disons, je dessine des graphiques en flot, relativement parlant, je me connecte à vis.xxx.xx : 8082 / vis / index.html, mais à l'intérieur il y a des liens vers les graphiques vis.xxx.xxx : 8082 / flot / index.html. À un moment donné, il s'est avéré que lors de la connexion à / vis, un mot de passe est demandé et que l'interface graphique est accessible sans mot de passe.

À certains moments, c'était généralement étrange - j'étais autorisé vis, je vois le graphique, mais en bas à droite, il y a une fenêtre translucide «Pas de connexion au serveur». Réécrit pour ce bloc CSS pour le cacher. Mais, dès que j'ai commencé à utiliser le cadre pour basculer entre les graphiques sur le même écran, il s'est avéré que mon chevauchement sur l'affichage dans le cadre ne fonctionnait pas. (Comme il s'est avéré plus tard, il devrait en être ainsi). J'éteins l'autorisation - tout va bien, pas de jurons.

J'ai donc décidé sur le même serveur externe d'élever nginx en mode proxy inverse. Et déjà faire une autorisation dessus.

Depuis le navigateur, cela a fonctionné. Mais l'application native iobroker.vis du Play Market n'a pas pu se connecter de cette manière. Et je voulais l'utiliser. Bien qu'il s'agisse en fait d'un navigateur dans la fenêtre, mais il possède un certain nombre de fonctionnalités intéressantes. Disons définir l'échelle (93% en mode vertical), et l'image s'adapte. Sur un autre appareil avec une résolution d'écran différente, vous sélectionnez simplement le coefficient, et c'est tout. Et dans le navigateur, vous devez ajuster à chaque fois ...

D'accord, je pense. J'ajouterai un code délicat dans l'URL au lieu du mot de passe. Tapez vis.xxx.xx : 8082 / <séquence longue> /vis/index.html. Souvent, une telle astuce est utilisée.

Presque gagné. Mais avec des problèmes, creuser a montré que cette application Web n'était pas écrite correctement. De nombreux liens à l'intérieur ne sont pas relatifs, mais à partir de la racine.

D'accord, j'ai trouvé plusieurs liens, j'ai écrit pour eux, disent-ils, si le référent contient un tel code, faites toujours confiance, réécrivez l'URL, etc. Mais ils sont progressivement apparus. J'ai donc décidé que c'était tordu, faux et qu'une approche différente était nécessaire.

VPN


J'ai décidé de sacrifier un peu l'universalité de l'accès. Permettez-moi d'avoir accès depuis mon ordinateur portable, mon smartphone. Mais à partir des appareils d'autres personnes, du cybercafé n'est pas nécessaire, je vais gérer. Ensuite, vous pouvez mettre un petit client qui installera le VPN. Et à l'intérieur, ni SSL ni autorisation n'est requis. Et en même temps, vous n'avez pas besoin de refaire les liens.

Le moyen le plus simple pour moi était Zérotier. Pour mon système d'exploitation (Windows, Android, Linux), il y a des clients. Et il y en a même de prêts à l'emploi dans le docker. Oui. Je lance tout dans Docker, sur les fonctionnalités de cela plus tard.

Vous installez le client, entrez un code unique pour votre réseau, puis confirmez- le dans l'interface Web sur my.zerotier.com , si nécessaire, définissez une adresse statique à partir de votre réseau privé personnel (à la 10.20.30.0), et c'est tout. Tous les clients connectés se voient.

La seule chose que j'ai eu à traiter un peu était "comment se connecter à un serveur distant à partir d'un appareil dans votre WiFi domestique sans démarrer le client." Eh bien, mon serveur domestique est déjà un client, même s'il se route lui-même. Il s'est avéré que tout est simple. Le réseau domestique 192.168.x.0 doit être enregistré sur my.zerotier.com dans la section Itinéraires gérés, en spécifiant comme ma passerelle, bien sûr, il s'agit de mon serveur domestique. Eh bien, dans le réseau WiFi, configurez l'itinéraire en conséquence (sur le routeur WiFi, statique 10.20.30.0 sur le serveur domestique).

Lorsque vous connectez un client Zerotier, vous pouvez spécifier un autre serveur DNS. Ceux. J'ai connecté le client et le nom de domaine ne se résout pas à une adresse publique, mais à une adresse privée, car DNS pointe désormais vers le serveur domestique, où dnsmasq paie pour les enregistrements IP individuels du réseau privé Zerotier.

Même Zerotier était satisfait du choix efficace d'un itinéraire de connexion. Si j'active un client Zerotier en WiFi domestique, le ping vers l'ordinateur domestique (son adresse IP délivrée par Zerotier) est le même couple de millisecondes que sans client (uniquement via WiFi). Ceux. La connexion au cloud ne se fait qu'au premier moment. Un échange de trafic supplémentaire est effectué directement, et non via le cloud. Si vous installez, par exemple, OpenVPN sur VPS, le même trafic a été exécuté du client vers VPS, puis de nouveau vers le même réseau WiFi vers le serveur domestique.

En principe, il y a même une puce pour mettre vos serveurs lunaires. Presque dans un réseau coupé d'Internet, toute cette économie est à déployer.

Quel est le résultat?


ESP32 envoie ses données au serveur mqtt déployé sur le VPS. Sur TLS, certificat client requis.

Un VPN via Zerotier est installé avec le serveur domestique. Sonoff rfBridge communique avec le firmware Tasmota via ce serveur domestique de mqtt à VPS. Il n'y a aucun moyen de définir TLS avec un certificat client, donc le MQTT habituel est configuré pour 1883. Quoi qu'il en soit, le serveur domestique cryptera ce trafic à l'aide de Zerotier.

Eh bien, je me connecte directement à vis depuis le réseau domestique et depuis Internet en activant le client Zerotier. Vous ne pouvez pas le désactiver du tout, cela fonctionne également. Mais seulement parfois, j'ai besoin d'autres clients VPN (par exemple, allez dans "Interdit ILV"). Deux VPN sur un smartphone ne sont pas immédiatement devenus amis, mais je n'ai pas compris.

Tout est très simple. Mais le ver a avalé l'âme. Même si je n'ai pas de réacteur nucléaire, mais tout d'un coup? Il y a eu un cas où ils ont cassé TeamViewer (une entreprise, pas spécifiquement un logiciel client), et grâce à eux ont eu accès à de nombreux comptes. Et en général, j'ai écrit au tout début que j'aime tout le mien.
Donc, l'étape suivante, je suis passé de Zerotier à OpenVPN. Tout est entre mes mains.

Le seul «étranger» est le VPS du fournisseur. Eh bien, je lance tout spécialement dans des conteneurs Docker pour pouvoir bouger instantanément.
Si je savais combien je devrais faire face à OpenVPN, peut-être que non. En toute justice - les principaux problèmes étaient précisément à cause des conteneurs.

Conclusion


Dans le prochain article, je parlerai d'OpenVPN et des fonctionnalités de configuration dans mes conditions (conteneurs, routage d'autres appareils depuis le réseau domestique). Il y aura plus de configurations, de détails techniques et de difficultés. Mais aussitôt la deuxième partie n'a pas commencé à écrire sans cela. Il ne serait pas clair pourquoi de telles perversions sont nécessaires.

Et juste au cas où, une question pour ceux qui savent: même si j'ai un VPS et un petit (512 Mo de RAM), il est utilisé à moins de 1%. Docker stats:

image

Et j'ai eu l'idée de tout lancer comme un conteneur sur Google Cloud Run, Amazon Fargate ou quelque chose de similaire. Le déploiement d'un serveur avec toutes sortes de fail2ban via ansible n'est pas un problème. Installez également Docker. Mais pourquoi, si vous n'avez besoin que d'une petite fraction de ses ressources?

Cependant, selon mes calculs, le même Fargate me coûterait beaucoup plus cher.

Peut-être que je n'ai pas compris quelque chose? Il serait donc intéressant d'avoir un petit conteneur uniquement pour le transfert du port d'origine, et non un VPS entier. Il n'y a rien comme ça?

All Articles