如何在Debian9上安装和保护MosquittoMQTT消息代理
介绍
MQTT 是一种机器对机器的消息传递协议,旨在为“物联网”设备提供轻量级的发布/订阅通信。 它通常用于地理跟踪车队、家庭自动化、环境传感器网络和公用事业规模的数据收集。
Mosquitto 是一种流行的 MQTT 服务器(或 broker,用 MQTT 的说法),具有强大的社区支持并且易于安装和配置。
在本教程中,我们将安装 Mosquitto 并设置我们的代理以使用 SSL 来保护我们受密码保护的 MQTT 通信。
先决条件
在开始本教程之前,您需要:
- 一个 Debian 9 服务器,具有非 root、启用 sudo 的用户和基本防火墙设置,如 this Debian 9 server setup tutorial 中所述。
- 指向您的服务器的域名,如我们的 DigitalOcean DNS 产品文档 中所述。 本教程将自始至终使用
mqtt.example.com
。 - 使用 Certbot 工具生成的可自动更新的 Let's Encrypt SSL 证书,用于您的域和 Mosquitto。 您可以在 如何使用 Certbot 独立模式检索让我们在 Debian 9 上加密 SSL 证书中了解如何设置。 您可以在步骤 4 中将
systemctl restart mosquitto
添加为renew_hook
。 请务必使用在上一个先决条件步骤中配置的相同域。
第 1 步 — 安装 Mosquitto
Debian 9 在其默认软件存储库中有一个相当新的 Mosquitto 版本,因此我们可以从那里安装它。
首先,使用您的非 root 用户登录并使用 apt update
更新软件包列表:
sudo apt update
现在,使用 apt install
安装 Mosquitto:
sudo apt install mosquitto mosquitto-clients
默认情况下,Debian 会在安装后启动 Mosquitto 服务。 让我们测试一下默认配置。 我们将使用我们刚刚安装的 Mosquitto 客户端之一来订阅我们代理上的主题。
Topics 是您发布和订阅消息的标签。 它们按层次结构排列,例如,您可以使用 sensors/outside/temp
和 sensors/outside/humidity
。 您如何安排主题取决于您和您的需求。 在本教程中,我们将使用一个简单的测试主题来测试我们的配置更改。
再次登录您的服务器,这样您就有了两个并排的终端。 在新终端中,使用 mosquitto_sub
订阅测试主题:
mosquitto_sub -h localhost -t test
-h
用于指定MQTT服务器的主机名,-t
为主题名。 点击 ENTER
后您将看不到任何输出,因为 mosquitto_sub
正在等待消息到达。 切换回您的另一个终端并发布一条消息:
mosquitto_pub -h localhost -t test -m "hello world"
mosquitto_pub
的选项与 mosquitto_sub
相同,但这次我们使用附加的 -m
选项来指定我们的消息。 点击 ENTER
,你应该会看到 hello world 在另一个终端弹出。 您已经发送了您的第一条 MQTT 消息!
在第二个终端输入CTRL+C
退出mosquitto_sub
,但保持与服务器的连接打开。 我们将在第 5 步中再次使用它进行另一个测试。
接下来,我们将使用基于密码的身份验证来保护我们的安装。
第 2 步 — 配置 MQTT 密码
让我们将 Mosquitto 配置为使用密码。 Mosquitto 包含一个实用程序,用于生成名为 mosquitto_passwd
的特殊密码文件。 此命令将提示您输入指定用户名的密码,并将结果放在 /etc/mosquitto/passwd
中。
sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy
现在我们将为 Mosquitto 打开一个新的配置文件,并告诉它使用这个密码文件来要求所有连接的登录:
sudo nano /etc/mosquitto/conf.d/default.conf
这应该打开一个空文件。 粘贴以下内容:
/etc/mosquitto/conf.d/default.conf
allow_anonymous false password_file /etc/mosquitto/passwd
确保在文件末尾留下一个尾随换行符。
allow_anonymous false
将禁用所有未经身份验证的连接,并且 password_file
行告诉 Mosquitto 在哪里查找用户和密码信息。 保存并退出文件。
现在我们需要重新启动 Mosquitto 并测试我们的更改。
sudo systemctl restart mosquitto
尝试在没有密码的情况下发布消息:
mosquitto_pub -h localhost -t "test" -m "hello world"
该消息应被拒绝:
OutputConnection Refused: not authorised. Error: The connection was refused.
在我们再次使用密码尝试之前,再次切换到您的第二个终端窗口,并订阅“测试”主题,这次使用用户名和密码:
mosquitto_sub -h localhost -t test -u "sammy" -P "password"
它应该连接并坐下,等待消息。 您可以在本教程的其余部分保持此终端打开并保持连接,因为我们会定期向它发送测试消息。
现在使用您的另一个终端发布消息,再次使用用户名和密码:
mosquitto_pub -h localhost -t "test" -m "hello world" -u "sammy" -P "password"
消息应该像第 1 步一样通过。 我们已经成功地为 Mosquitto 添加了密码保护。 不幸的是,我们通过互联网发送未加密的密码。 接下来我们将通过向 Mosquitto 添加 SSL 加密来解决这个问题。
第 3 步 — 配置 MQTT SSL
要启用 SSL 加密,我们需要告诉 Mosquitto 我们的 Let's Encrypt 证书的存储位置。 打开我们之前启动的配置文件:
sudo nano /etc/mosquitto/conf.d/default.conf
在文件末尾粘贴以下内容,留下我们已经添加的两行:
/etc/mosquitto/conf.d/default.conf
. . . listener 1883 localhost listener 8883 certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
同样,请务必在文件末尾留下一个尾随换行符。
我们将两个单独的 listener
块添加到配置中。 第一个,listener 1883 localhost
,更新端口 1883
上的默认 MQTT 侦听器,这是我们迄今为止一直连接的。 1883
是标准的未加密 MQTT 端口。 该行的 localhost
部分指示 Mosquitto 仅将此端口绑定到 localhost 接口,因此无法从外部访问。 无论如何,外部请求都会被我们的防火墙阻止,但最好是明确的。
listener 8883
在端口 8883
上设置加密侦听器。 这是 MQTT + SSL 的标准端口,通常称为 MQTTS。 接下来的三行 certfile
、cafile
和 keyfile
都将 Mosquitto 指向相应的 Let's Encrypt 文件以设置加密连接。
保存并退出文件,然后重新启动 Mosquitto 以更新设置:
sudo systemctl restart mosquitto
更新防火墙以允许连接到端口 8883
。
sudo ufw allow 8883
OutputRule added Rule added (v6)
现在我们使用 mosquitto_pub
再次测试,SSL 有几个不同的选项:
mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --capath /etc/ssl/certs/ -u "sammy" -P "password"
请注意,我们使用的是完整主机名而不是 localhost
。 因为我们的 SSL 证书是为 mqtt.example.com
颁发的,所以如果我们尝试与 localhost
建立安全连接,我们会收到错误消息,指出主机名与证书主机名不匹配(即使它们都指向相同的 Mosquitto 服务器)。
--capath /etc/ssl/certs/
为 mosquitto_pub
启用 SSL,并告诉它在哪里查找根证书。 这些通常由您的操作系统安装,因此 Mac OS、Windows 等的路径不同。 mosquitto_pub
使用根证书来验证 Mosquitto 服务器的证书是否由 Let's Encrypt 证书颁发机构正确签名。 重要的是要注意 mosquitto_pub
和 mosquitto_sub
不会在没有此选项(或类似的 --cafile
选项)的情况下尝试 SSL 连接,即使您正在连接到标准安全8883
的端口。
如果测试一切顺利,我们将在另一个 mosquitto_sub
终端中再次看到 hello 。 这意味着您的服务器已完全设置好! 如果您想扩展 MQTT 协议以使用 websockets,您可以执行最后一步。
第 4 步 — 通过 Websockets 配置 MQTT(可选)
为了在 Web 浏览器中使用 JavaScript 使用 MQTT,该协议适用于标准 websockets。 如果您不需要此功能,则可以跳过此步骤。
我们需要在 Mosquitto 配置中再添加一个 listener
块:
sudo nano /etc/mosquitto/conf.d/default.conf
在文件末尾,添加以下内容:
/etc/mosquitto/conf.d/default.conf
. . . listener 8083 protocol websockets certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
同样,请务必在文件末尾留下一个尾随换行符。
除了端口号和 protocol websockets
行之外,这与前一个块基本相同。 MQTT over websockets 没有官方标准化端口,但 8083
是最常见的。
保存并退出文件,然后重新启动 Mosquitto。
sudo systemctl restart mosquitto
现在,在防火墙中打开端口 8083
。
sudo ufw allow 8083
为了测试这个功能,我们将使用一个公共的、基于浏览器的 MQTT 客户端。 那里有一些,但是 Eclipse Paho JavaScript Client 使用起来简单直接。 在浏览器中打开Paho客户端。 您将看到以下内容:
填写连接信息如下:
- Host 应该是 Mosquitto 服务器的域
mqtt.example.com
。 - 端口应该是
8083
。 - ClientId 可以保留默认值,js-utility-DI1m6。
- Path可以保留默认值,/ws。
- Username 应该是你的 Mosquitto 用户名; 在这里,我们使用了 sammy。
- Password 应该是您选择的密码。
其余字段可以保留其默认值。
按下 Connect 后,基于 Paho 浏览器的客户端将连接到您的 Mosquitto 服务器。
要发布消息,请导航到 Publish Message 窗格,将 Topic 填写为 test,然后在 Message 部分输入任何消息. 接下来,按 发布 。 该消息将显示在您的 mosquitto_sub
终端中。
结论
我们现在已经设置了一个安全的、受密码保护和 SSL 保护的 MQTT 服务器。 这可以作为您梦想的任何项目的强大且安全的消息传递平台。 一些与 MQTT 协议配合良好的流行软件和硬件包括:
- OwnTracks,一款可以安装在手机上的开源地理追踪应用。 OwnTracks 会定期向您的 MQTT 服务器报告位置信息,然后您可以将其存储并显示在地图上,或者根据您的位置创建警报并激活 IoT 硬件。
- Node-RED 是一个基于浏览器的图形界面,用于将物联网“连接”在一起。 您将一个节点的输出拖到另一个节点的输入,并且可以通过过滤器、在各种协议之间、将信息路由到数据库等。 Node-RED 很好地支持 MQTT。
- ESP8266 是具有 MQTT 功能的廉价 wifi 微控制器。 您可以连接一个以将温度数据发布到主题,或者订阅气压主题并在暴风雨来临时发出蜂鸣声!
这些只是 MQTT 生态系统中的几个流行示例。 有更多的硬件和软件可以使用该协议。 如果您已经拥有喜欢的硬件平台或软件语言,它可能具有 MQTT 功能。 让你的“东西”互相交谈,玩得开心!