在没有公共IP的情况下安全访问智能家居(第1部分)

介绍


选择一个能反映含义的宽大标题很困难,因此我将立即描述自己为自己设定的任务。

有一个“智能家居”。就我而言,这是带有ioBroker的无风扇家庭服务器,尽管这并不重要。除了家用设备外,我还想从外部将传感器连接到它(例如,在偏远温室的ESP32上)。我决定通过mqtt进行此操作。从Internet访问接口。

平常的事情。但是有细微差别:

  • 提供者无法给我一个公共IP地址。并且没有其他提供商。
  • 我不喜欢绑定到特定的云服务。外部服务也可能关闭(因为gbridge最近发送了通知)。只是万一发生故障,不清楚该怎么办。我更喜欢我自己的(可以转移的),如果发生什么事,可以用很少的血重做。
  • 安全很重要。不是妄想狂,而是将ioBroker放到Internet上,尤其是考虑到其中展示了几种服务(flot ...)。不完全是。

此外,我不想立即显示结果,而是显示过程。进行方式,愿望清单如何转变,决定是否改变。可能可以更正确/更有效地解决某些问题(我不是系统管理员,也不是开发人员)。也许有人不会走得那么远,并利用临时解决方案,例如,我觉得自己不安全或不方便。实际上,这部分描述的是一个可行的选择,但对我来说是“中级”。

mqtt的公共地址


在家里,路由器上的公共IP不会发光(我不是在说固定的,这可以通过dyndns和类似物解决),即提供商没有提供10.x.x.x的选项。因此,您需要租用一个小型VPS,并通过它赚钱。

最简单的方法是通过ssh进行隧道传输。在家庭服务器上(我将其称为iob.xxx.xx)执行:

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

实际上,连接到外部服务器pub.xxx.xx的端口1883时,您会发现自己在家庭iob上:1883,正在运行mqtt(蚊子)容器。

自然,这必须自动启动,失败后恢复连接。因此,我使用了autossh并将其设计为服务。

/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

各种systemctl启用/重新启动等我不会描述。

不幸的是,尽管有自动挂断,但我一直被不断的冻结困扰。因此,我决定无需生产实体,并决定使用通常的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

后来,顺便说一句,事实证明这个提供者是如此倾斜。好吧,或者最便宜的价格为45卢布/月,所以歪歪扭扭地为他工作。该会话会定期挂起,即使仅通过ssh(MobaXterm)连接也是如此。所以最后我从另一个订购了一个VPS(55卢布/月),冻结问题消失了。

顺便说一句,我不仅为价格选择了VPS,还考虑了ping(10-20毫秒)。

通常,此选项非常正常,尤其是考虑到随后我通过TLS仅与端口8883建立了Internet连接。那些。 mosquitto的密码已加密传输。

随后使客户端证书成为必需。那些。首先,在TLS级别,您需要出示客户端证书,然后使用mosquito中指定的密码名登录。那些。进入密码搜索阶段并非易事。
因此,起初我使用了LetsEncrypt的服务器证书,然后由于需要客户端证书,我切换到了自签名。

由于在此过程中我还开发了ESP32的软件,因此我注意到(或者只是想,我已经不记得了),当VPN连接出现问题时,电池消耗会更快。在正常运行期间,需要执行以下周期:唤醒,为传感器供电,连接到WiFi,与mqtt服务器建立连接,在准备就绪时读取传感器读数,转移至mqtt,关闭传感器电源,进入深度睡眠状态10分钟。

通常,这样的周期大约需要4秒钟。1.5到2秒-连接到WiFi,由于通过TLS转换为mqtt而需要额外的一秒钟。它适合您4秒钟,所有这些都一样,传感器需要一些时间才能唤醒。但是,如果VPN掉线了(当autossh掉线时很明显),我该怎么办?当然,我将其设置为在20秒后系统仍将进入睡眠状态。但是20秒而不是4秒非常引人注目。

通常,我认为最好将mqtt服务器保留在外部VPS上。现在一切都像时钟一样,我不确定是否有必要。但是我认为重新制作它没有任何意义。

Vis公共地址


Vis是ioBroker上流行的可视化系统。您可以随意设置,并在https上进行配置,同样只需转发端口即可。此外,她可以在应用程序级别要求输入密码。

但这并不酷。特别是考虑到工作,它会连接其他服务。说,我用flot绘制图形,相对而言,我连接到vis.xxx.xx:8082 / vis / index.html,但是内部有指向vis.xxx.xxx图形的链接:8082 / flot / index.html。在某个时候,事实证明,当连接到/ vis时,要求输入密码,并且图形界面无需密码即可访问。

有时,这通常很奇怪-我在视觉上得到了授权,我看到了该图,但是在右下角有一个半透明的“无连接到服务器”窗口。为该css块重写以将其隐藏。但是,当我开始使用框架在同一屏幕上的图形之间切换时,事实证明我在框架中的显示上的重叠不起作用。 (后来证明,应该是这样)。我关闭了授权-一切都很好,没有咒骂。

因此,我决定在同一台外部服务器上以反向代理模式提高nginx。并且已经对此进行了授权。

从浏览器可以正常工作。但是Play市场上的本地应用程序iobroker.vis无法以这种方式登录。我想使用它。尽管这实际上是窗口中的浏览器,但是它具有许多不错的功能。假设设置了比例(垂直模式下为93%),图像就适合了。在另一台屏幕分辨率不同的设备上,只需选择系数即可。而且在浏览器中,您每次都需要调整...

好吧,我想。我将在网址中添加一个复杂的代码,而不是密码。键入vis.xxx.xx:8082 / <长序列> /vis/index.html。通常会使用这种技巧。

差不多赚了。但是出现故障后,挖掘发现该Web应用程序编写不正确。其中的许多链接不是相对的,而是从根开始的。

好的,我找到了一些链接,我为他们写了,他们说,如果引荐来源网址包含此类代码,则仍然信任,重写URL等。但是他们逐渐暴露出来。因此,我认为这是歪曲,错误的,需要另一种方法。

虚拟专用网


我决定牺牲一点访问通用性。让我可以从我的笔记本电脑,智能手机进行访问。但我会从其他人的设备中,从网吧中移除。然后,您可以放置​​一个小型客户端来安装VPN。在其中,不需要SSL或授权。同时,您无需重做链接。

对我来说,最简单的方法是Zerotier。对于我的操作系统(Windows,Android,Linux),有客户端。甚至在docker中有现成的。是。我稍后将在docker中运行所有功能。

安装客户端后,为您的网络输入一个唯一的代码,然后在my.zerotier.com上的Web界面中进行确认,如有必要,请从您的个人专用网络中设置一个静态地址(la 10.20.30.0),仅此而已。所有连接的客户端都可以看到对方。

我唯一需要处理的就是“如何在不启动客户端的情况下从家庭WiFi中的设备连接到远程服务器”。好吧,我的家庭服务器即使已经路由了自己,也已经是一个客户端。事实证明,一切都很简单。归属网络192.168.x.0应该在my.zerotier.com的“受管路由”部分中注册,并指定为我的网关,这自然是我的归属服务器。好吧,在WiFi网络中,相应地配置路由(在WiFi路由器上,在主服务器上为静态10.20.30.0)。

连接Zerotier客户端时,可以指定其他DNS服务器。那些。我连接了客户端,域名解析不是一个公共地址,而是一个私有地址,因为DNS现在指向家庭服务器,其中dnsmasq为来自Zerotier私有网络的单个IP记录提供支持。

甚至Zerotier也对有效选择连接路径感到满意。如果我在家庭WiFi中激活了Zerotier客户端,则对家用计算机(由Zerotier发出的IP地址)执行ping操作与没有客户端(仅通过WiFi)的毫秒数相同。那些。仅在第一时间连接到云。进一步的流量交换是直接进行的,而不是通过云进行的。例如,如果在VPS上安装OpenVPN,则相同的流量会从客户端流到VPS,然后再流回相同的WiFi网络再到家庭服务器。

原则上,甚至有一个芯片可以放置您的卫星服务器。几乎要在与Internet断开的网络中部署所有这种经济方式。

结果是什么?


ESP32会将其数据发送到VPS上部署的mqtt服务器。通过TLS,需要客户端证书。

家用服务器安装了通过Zerotier的VPN。 Sonoff rfBridge通过此家庭服务器从mqtt到VPS与Tasmota固件进行通信。无法使用客户端证书设置TLS,因此通常的MQTT配置为1883。无论如何,归根结底,家用服务器将使用Zerotier加密此流量。

好吧,我直接从家庭网络连接到vis,并通过激活Zerotier客户端从Internet连接到vis。您根本无法关闭它,这也可以。但是只有有时候我需要其他VPN客户端(例如,转到“ ILV-forbidden”)。一台智能手机上的两个VPN并没有立即成为朋友,但我不明白。

一切都非常简单。但是蠕虫吞噬了灵魂。虽然我没有核反应堆,但突然之间?在某些情况下,他们破坏了TeamViewer(一家公司,而不是专门用于客户端软件),并通过他们获得了许多帐户的访问权限。总的来说,我一开始就写道我爱我的一切。
因此,下一步,我从Zerotier切换到OpenVPN。一切都在我手中。

唯一的“外国人”是提供商的VPS。好吧,我专门在docker容器中启动所有东西,以便能够立即移动。
如果我知道我需要对付OpenVPN多少钱,也许我不会。公平地说-主要问题恰恰是由于容器造成的。

结论


在下一篇文章中,我将讨论OpenVPN及其所处条件下的配置功能(容器,从家庭网络路由其他设备)。将会有更多的配置,技术细节和困难。但是第二部分马上没有没有这个就开始写。尚不清楚为什么根本需要这样的变态。

以防万一,对于那些知道的人来说,这是一个问题:尽管我有一个VPS和一个小的VPS(512MB RAM),但使用率不到1%。 docker stats:

图片

我想到了将它们全部启动的方法,就像在某些Google Cloud Run,Amazon Fargate或类似工具上启动一个容器一样。通过ansible部署具有各种fail2ban的服务器不是问题。也安装Docker。但是,如果只需要其一小部分资源,那为什么呢?

但是,根据我的计算,同一个Fargate会让我多花很多倍。

也许我听不懂?因此,拥有一个仅用于转发端口回家的小容器而不是整个VPS会很有趣。没有这样的事吗?

All Articles