如何在CentOS7上安装和保护MosquittoMQTT消息代理

来自菜鸟教程
跳转至:导航、​搜索

介绍

MQTT 是一种机器对机器的消息传递协议,旨在为“物联网”设备提供轻量级的发布/订阅通信。 它通常用于地理跟踪车队、家庭自动化、环境传感器网络和公用事业规模的数据收集。

Mosquitto 是一种流行的 MQTT 服务器(或 broker,用 MQTT 的说法),具有强大的社区支持并且易于安装和配置。

在本教程中,我们将安装 Mosquitto,从 Let's Encrypt 检索 SSL 证书,并设置我们的代理以使用 SSL 来保护我们受密码保护的 MQTT 通信。

先决条件

在开始本教程之前,您需要:

  • 具有非 root、启用 sudo 的用户和基本防火墙设置的 CentOS 7 服务器。 New CentOS 7 Server Checklist 涵盖了这个(以及更多)。
  • 根据 如何使用 DigitalOcean 设置主机名,指向您的服务器的域名。 本教程将自始至终使用 mqtt.example.com
  • (可选)nano 文本编辑器。 本教程将始终使用 nano,您可以随时使用 sudo yum -y install nano 安装它,或者替换您喜欢的文本编辑器。

第 1 步 — 安装 Mosquitto

CentOS 7 默认没有 mosquitto 软件包。 要安装它,我们将首先安装一个名为 Extra Packages for Enterprise Linux 或 EPEL 的额外软件存储库。 这个存储库充满了可以很好地安装在 CentOS、Red Hat 和其他面向企业的 Linux 发行版上的附加软件。

以非 root 用户登录并使用 yum 包管理器安装 epel-release 包。

sudo yum -y install epel-release

这会将 EPEL 存储库信息添加到我们的系统中。 -y 选项在整个过程中自动对一些提示回答是。 现在我们可以安装 mosquitto 包了。

sudo yum -y install mosquitto

该软件包带有一个简单的默认配置,因此让我们运行它来测试我们的安装。

sudo systemctl start mosquitto

我们还需要启用该服务以确保它在我们重新启动系统时启动:

sudo systemctl enable mosquitto

现在让我们测试一下默认配置。 mosquitto 软件包带有一些命令行 MQTT 客户端。 我们将使用其中一个订阅代理上的主题。

Topics 是您发布和订阅消息的标签。 它们按层次结构排列,例如,您可以使用 sensors/outside/tempsensors/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 步中再次使用它进行另一个测试。

接下来,我们将使用新的 Let's Encrypt 客户端 Certbot 通过 SSL 保护我们的安装。

第 2 步 — 为 Let's Encrypt 证书安装和运行 Certbot

Let's Encrypt 是一项通过自动化 API 提供免费 SSL 证书的新服务。 官方的 Let's Encrypt 客户端称为 Certbot,它包含在我们在上一步中安装的 EPEL 存储库中。

使用 yum 安装 Certbot。

sudo yum -y install certbot

Certbot 需要回答 Let's Encrypt API 发出的加密挑战,以证明我们控制了我们的域。 它使用端口 80 (HTTP) 和/或 443 (HTTPS) 来完成此操作。 我们将只使用端口 80,所以现在让我们允许该端口上的传入流量。

使用 firewall-cmd 添加 HTTP 服务。

sudo firewall-cmd --permanent --add-service=http

重新加载防火墙以使更改生效。

sudo firewall-cmd --reload

我们现在可以运行 Certbot 来获取我们的证书。 我们将使用 --standalone 选项告诉 Certbot 自行处理 HTTP 质询请求,并且 --standalone-supported-challenges http-01 将通信限制为端口 80-d 用于指定您想要证书的域,certonly 告诉 Certbot 只检索证书而不执行任何其他配置步骤。

sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com

运行命令时,系统会提示您输入电子邮件地址并同意服务条款。 完成此操作后,您应该会看到一条消息,告诉您该过程成功以及您的证书存储在哪里。

我们有我们的证书。 现在我们需要确保 Certbot 在它们即将到期时自动更新它们。

第 3 步 — 设置 Certbot 自动续订

Let's Encrypt 的证书有效期只有九十天。 这是为了鼓励用户自动化他们的证书更新过程。 我们需要设置一个定期运行的命令来检查过期证书并自动更新它们。

为了每天运行更新检查,我们将使用 cron,这是一种用于运行定期作业的标准系统服务。 我们通过打开和编辑一个名为 crontab 的文件来告诉 cron 要做什么。

sudo EDITOR=nano crontab -e

EDITOR=nano 将使 crontab 文件在 nano 编辑器中打开。 如果您更喜欢默认的 vi 编辑器,请将其关闭。

您现在应该看到默认的 crontab,一个空白文件。 粘贴以下行,然后保存并关闭文件。

crontab

15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"

该行的 15 3 * * * 部分表示“每天凌晨 3:15 运行以下命令”。 Certbot 的 renew 命令将检查系统上安装的所有证书,并更新任何设置为在 30 天内到期的证书。 --noninteractive 告诉 Certbot 不要等待用户输入。

--post-hook "systemctl restart mosquitto" 将重新启动 Mosquitto 以获取新证书,但前提是证书已更新。

现在自动证书更新已设置完毕,我们将回到配置 Mosquitto 以提高安全性。

第 4 步 — 配置 MQTT 密码

让我们将 Mosquitto 配置为使用密码。 Mosquitto 包含一个实用程序,用于生成名为 mosquitto_passwd 的特殊密码文件。 此命令将提示您输入指定用户名的密码,并将结果放在 /etc/mosquitto/passwd 中。

sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy

现在我们将替换默认配置文件并告诉 Mosquitto 使用此密码文件来要求所有连接的登录。 首先,删除现有的mosquitto.conf

sudo rm /etc/mosquitto/mosquitto.conf

现在打开一个新的空白配置。

sudo nano /etc/mosquitto/mosquitto.conf

粘贴在下面。

/etc/mosquitto/mosquitto.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 加密来解决这个问题。

第 5 步 — 配置 MQTT SSL

要启用 SSL 加密,我们需要告诉 Mosquitto 我们的 Let's Encrypt 证书的存储位置。 打开我们之前启动的配置文件。

sudo nano /etc/mosquitto/mosquitto.conf

在文件末尾粘贴以下内容,留下我们已经添加的两行:

/etc/mosquitto/mosquitto.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。 接下来的三行 certfilecafilekeyfile 都将 Mosquitto 指向相应的 Let's Encrypt 文件以设置加密连接。

保存并退出文件。

在我们重新启动 Mosquitto 以加载新配置之前,我们需要在默认的 mosquitto 服务文件中修复一件事。 这是 systemd 用来确定如何运行 mosquitto 的文件。 在您喜欢的编辑器中打开它。

sudo nano /etc/systemd/system/multi-user.target.wants/mosquitto.service

查找显示 User=mosquitto 的行并将其删除,然后保存并退出文件。

Mosquitto 仍然会以 mosquitto 用户身份运行,但是当它第一次启动时,它将拥有 root 权限,并且能够加载我们的 Let's Encrypt 证书(仅限于 [ X206X]root 访问,出于安全原因)。 加载证书后,它会下拉到 mosquitto 用户。

我们需要重新加载 systemd 本身,因此它会注意到我们对服务文件所做的更改。

sudo systemctl daemon-reload

现在我们可以重新启动 Mosquitto 来更新设置。

sudo systemctl restart mosquitto

更新防火墙以允许连接到端口 8883

sudo firewall-cmd --permanent --add-port=8883/tcp

并重新加载防火墙。

sudo firewall-cmd --reload

现在我们再次使用 mosquitto_pub 进行测试,并为 SSL 提供了一些不同的选项。

mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --cafile /etc/ssl/certs/ca-bundle.crt -u "sammy" -P "password"

请注意,我们使用的是完整主机名而不是 localhost。 因为我们的 SSL 证书是为 mqtt.example.com 颁发的,所以如果我们尝试与 localhost 建立安全连接,我们会收到错误消息,指出主机名与证书主机名不匹配(即使它们都指向相同的 Mosquitto 服务器)。

--cafile /etc/ssl/certs/ca-bundle.crtmosquitto_pub 启用 SSL,并告诉它在哪里查找根证书。 这些通常由您的操作系统安装,因此 Mac OS、Windows 等的路径不同。 mosquitto_pub 使用根证书来验证 Mosquitto 服务器的证书是否由 Let's Encrypt 证书颁发机构正确签名。 重要的是要注意 mosquitto_pubmosquitto_sub 不会在没有此选项(或类似的 --capath 选项)的情况下尝试 SSL 连接,即使您正在连接到标准安全8883 的端口。

如果测试一切顺利,我们将在另一个 mosquitto_sub 终端中再次看到 hello 。 这意味着您的服务器已完全设置好! 如果您想扩展 MQTT 协议以使用 websockets,您可以执行最后一步。

第 6 步 — 通过 Websockets 配置 MQTT(可选)

为了在 Web 浏览器中使用 JavaScript 使用 MQTT,该协议适用于标准 websockets。 如果您不需要此功能,则可以跳过此步骤。

我们需要在 Mosquitto 配置中再添加一个 listener 块。

sudo nano /etc/mosquitto/mosquitto.conf

在文件末尾,添加以下内容:

/etc/mosquitto/mosquitto.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 firewall-cmd --permanent --add-port=8083/tcp

最后一次重新加载防火墙。

sudo firewall-cmd --reload

为了测试这个功能,我们将使用一个公共的、基于浏览器的 MQTT 客户端。 有一些,但 mqtt-admin 简单明了。 在浏览器中打开 mqtt-admin 。 您将看到以下内容:

填写连接信息如下:

  • Protocol 应该是 wss(代表 websocket secure)。
  • Host 应该是 Mosquitto 服务器的域 mqtt.example.com
  • 端口应该是8083
  • User 应该是你的 Mosquitto 用户名; 在这里,我们使用了 sammy
  • Password 应该是您选择的密码。
  • ClientId可以保留默认值,mqtt-admin

保存设置后,mqtt-admin将连接到你的Mosquitto服务器。 在下一个屏幕中,将 Topic 填写为 test,为 Payload 输入任何消息,然后按 Publish。 该消息将显示在 mosquitto_sub 终端中。

结论

我们现在已经设置了一个安全的、受密码保护的 MQTT 服务器,它可以自动更新来自 Let's Encrypt 服务的 SSL 证书。 这将为您梦想的任何项目提供强大且安全的消息传递平台。 一些适用于 MQTT 协议的流行软件和硬件包括:

  • OwnTracks,一款可以安装在手机上的开源地理追踪应用。 OwnTracks 会定期向您的 MQTT 服务器报告位置信息,然后您可以将其存储并显示在地图上,或者根据您的位置创建警报并激活 IoT 硬件。
  • Node-RED 是一个基于浏览器的图形界面,用于将物联网“连接”在一起。 您将一个节点的输出拖到另一个节点的输入,并且可以通过过滤器、在各种协议之间、将信息路由到数据库等。 Node-RED 很好地支持 MQTT。
  • ESP8266 是具有 MQTT 功能的廉价 wifi 微控制器。 您可以连接一个以将温度数据发布到主题,或者订阅气压主题并在暴风雨来临时发出蜂鸣声!

这些只是 MQTT 生态系统中的几个流行示例。 有更多的硬件和软件可以使用该协议。 如果您已经拥有喜欢的硬件平台或软件语言,它可能具有 MQTT 功能。 让你的“东西”互相交谈,玩得开心!