PiCockpit的技术和安全基础

我被要求阐述一下关于安全和技术基础的一些情况。 码头.

涉及的部分

PiCockpit由几个部分组成。

  • 淘宝网
  • 舱门前部
  • picockpit-backend
  • picockpit-api ("papi")
  • 数据库
  • MQTT服务器
  • picockpit软件包库

MQTT服务器

picockpit-frontend和picockpit-client之间的数据是使用MQTT服务器(称为 "broker"),通过Websockets进行交换。我们使用 冯小刚 为了这个目的。

MQTT是一个通信协议,类似于HTTP。它是基于发布/订阅的隐喻,不像HTTP(基于请求/响应)。

在MQTT中,客户端可以连接到代理,并订阅主题--在这种情况下,他们将收到在这些主题上发布的消息。他们也可以在主题上发布消息。

消息可以作为保留信息发布--在这种情况下,经纪人将保留消息,并将其发送给任何订阅了该消息所发布的特定主题的客户。

周期性的 "保持"(keep-alives)会从代理处发送到客户处,然后再返回,以保持连接的运行并确保客户仍然在线。

此外,还可以设置一个最后的遗嘱信息,如果经纪人与客户失去连接,该信息将被公布。

每个Raspberry Pi都有自己的消息主题路径,Raspberry Pi的序列号被用于此目的。

根据我的研究,VerneMQ是作为PiCockpit的MQTT代理的一个完美选择。

  • 它严格专注于MQTT(与RabbitMQ不同)。
  • 它的重点是高性能和高可用性

VerneMQ是用Erlang编写的。Erlang是一种适合电信应用的语言/环境--它被设计成高度并发的、可扩展的,甚至跨越几个节点。它在处理单个消息时也非常轻巧,允许它扩展到数百万条消息。这 VerneMQ博客 使得阅读变得更有吸引力。

安全特征

VerneMQ允许我们使用不同的挂载点,将各个用户的流量完全分开。

一个用户的picockpit-client和picockpit-frontend将只能看到该用户mountpoint中的信息。

挂载点是根据认证数据分配的,这些数据识别出Rasberry Pi(picockpit-client)或JavaScript连接(picockpit-frontend)是属于该特定用户。

为什么是Websockets?

Websockets允许流量穿越防火墙,并且是JavaScript客户端可以通信的唯一方式。

picockpit-client

picockpit-client是用Python编写的,使用了许多库。它被打包成一个Debian软件包(.deb),并被部署到我们的公共资源库,用我们的密钥签名。

对于MQTT通信,我们使用Paho。Paho是一个开源的库。我们在picockpit-frontend中也使用Paho。

picockpit-client在设置过程中与PiCockpit连接(sudo picockpit-client connect)。

在这个过程中,客户端使用API密钥与API进行通信,以获得MQTT凭证。

API密钥和MQTT凭证都以加密的形式保存在用户的Raspberry Pi上(包括盐!)。

picockpit-client被设计为持续在线,如果用户的Pi在线并连接到互联网。这样一来,Pi的数据就可以被读取,用户也可以安全地控制它。

通过禁用picockpit-client服务,picockpit.com将不能再连接到Pi上并接收数据/发送控制命令。

picockpit-client将本地配置文件保存在/etc/picockpit-client文件夹中。

形象

你在上面给出的目录树中看到一个样本结构。

主要的配置文件是 picockpit-client.config.json。这个文件包含了picockpit-client连接到PiCockpit.com的必要凭证。

此外,你可以看到两个目录app/com.picockpit/picontrol/modules和app/com.picockpit/pidoctor/modules

这些包含.json文件,即你可以在这些特定的应用程序中从前端主动运行的命令的定义文件。

例如,如果你不想在PiCockpit.com中显示重启或关机按钮,并且不允许PiCockpit使用该功能,你可以编辑

apps/com.picockpit/picontrol/modules/core.json

并重新启动picockpit-client服务

形象

正如你所看到的,这些文件包含了在网页前端显示的命令的定义。

同样,如果你想扩展功能,添加额外的命令或模块(命令组),你可以在这里通过编辑.JSON文件或创建新的文件来实现。

命令的运行默认使用用户 "pi"。.JSON语法允许你指定命令应该在哪个用户下运行。

picockpit-client以root身份运行,为了执行命令,一个新的线程将被分离出来,用户权限被改变为指定用户。这个改变对那个特定的线程来说是不可逆的,所以应用程序不能重新获得root权限。

可以为PiDoctor创建同样的JSON文件,但语法有些不同。

形象

安全特征

如上所述,用户权限可以为PiControl设置用户进行修改。PiDoctor的测试目前都是以root身份运行。

用户不能在Web界面上定义任何命令,这些命令必须以JSON文件的形式存在于你想控制的特定Pi上。

这是为防止安全问题而设计的,即使是在有人访问你的Web前端的情况下。

用户可以控制他们愿意给予的曝光量。

默认情况下,只有 "关机"、"重启 "和 "更新picockpit-client "控制动作被添加到web界面中。

其他模块(GPIO和PiStats)不允许运行任意的命令。PiStats目前是硬编码的,显示在web界面的信息。

哨子

而GPIO允许控制Raspberry Pi的引脚(包括软件PWM),并读取它们。在分配引脚时要注意(只针对picockpit-client,它不知道其他的应用程序--所以你必须要小心),以及在访问同一个Pi的多个webinterface之间同步状态(例如,如果用户同时使用几个浏览器窗口或设备)。

所有这些信息都是使用MQTT发布/订阅算法传输的。

最后,websocket通信是通过安全端口运行的,所以在与经纪人的通信中,所有进出Pi的数据都是加密的。

picockpit-后端和数据库

picockpit的后端是用 水晶 编程语言,使用 Kemal 作为一个框架。

选择Crystal是因为它的性能、开发者友好性和类型安全性。

Crystal与数据库对话。我们使用MongoDB作为数据库。

安全特征

  • 密码是经过哈希和加盐处理的
  • 用户可以创建多个API密钥,并撤销(删除它们)。
  • API密钥也只以散列和加盐的形式保存--即使有人进入数据库,也无法进行反向工程。

在picockpit客户端和数据库中,只有API密钥的散列衍生物被保存。

而且--不--它们并不直接匹配(这就有点忽略了重点)。 笑一笑),它们需要进一步处理,以验证用户的凭证/Pi的访问。

删除API密钥的同时也删除了某一特定Pi的MQTT凭证。

舱门前部

现在,picockpit的前端越来越多地基于JavaScript,也用于渲染目的。

一个选择是将PiCockpit更多的推向SPA(单页应用程序)。

目前由后端呈现的页面的进一步整合,将在下一步的前台中进行。

我们使用 Vue.jsVuetify.js,以及其他一些用于前端的库,包括使用Websockets的MQTT连接的Paho。

根据你所看到的Pi,webfrontend会订阅相应的MQTT路径。

例如,如果你按下 "关闭 "按钮,一个消息将被发布到定义的MQTT路径上,picockpit-client正在监听。

安全特征

前端强制使用HTTPS连接。与picockpit-client类似,数据通过websockets传输给经纪人,只使用加密的连接(https://)。

在PiControl中,执行像重启或关机这样的 "危险 "动作会受到额外确认对话框的保护。

形象