如何在Ubuntu 16.04上安装和保护Mosquitto MQTT消息传递代理

介绍

MQTT是一种机器到机器消息协议,旨在为“物联网”设备提供轻量级发布/订阅通信。它通常用于车辆的地理跟踪车队,家庭自动化,环境传感器网络和公用事业规模的数据收集。 Mosquitto是一个受欢迎的MQTT服务器(或 代理 ,在MQTT中的用法),具有良好的社区支持,易于安装和配置。 在本教程中,我们将安装Mosquitto,从Let's Encrypt检索SSL证书,并设置我们的代理使用SSL来保护受密码保护的MQTT通信。

先决条件

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

第1步 - 安装Mosquitto

Ubuntu 16.04在默认软件存储库中有一个相当新版本的Mosquitto。使用非root用户登录,并使用 apt-get安装Mosquitto。
sudo apt-get install mosquitto mosquitto-clients
默认情况下,Ubuntu将在安装后启动Mosquitto服务。让我们测试默认配置。我们将使用我们刚刚安装的一个Mosquitto客户端订阅我们的代理上的一个主题。 主题是您向其发布消息和订阅的标签。 它们被布置为层次结构,因此,例如,您可以具有 sensors/outside/tempsensors/outside/humidity 。如何安排主题取决于你和你的需要。在本教程中,我们将使用一个简单的测试主题来测试我们的配置更改。 第二次登录到您的服务器,因此您有两个端子并排。在新终端中,使用 mosquitto_sub订阅测试主题:
mosquitto_sub -h localhost -t test
-h用于指定MQTT服务器的主机名, -t是主题名。 由于 mosquitto_sub正在等待消息到达,因此在按 ENTER后没有输出。切换回您的其他终端并发布消息:
mosquitto_pub -h localhost -t test -m "hello world"
为options mosquitto_pub相同 mosquitto_sub ,尽管这次我们使用附加 -m选项指定我们的消息。 点击 ENTER ,你应该看到 hello world弹出在另一个终端。您发送了第一个MQTT消息! 在第二个终端中输入 CTRL+C ,退出 mosquitto_sub ,但保持与服务器的连接打开。我们将在第5步中再次使用它进行另一个测试。 接下来,我们将使用Certbot(新的Let's Encrypt客户端)使用SSL保护我们的安装。

第2步 - 安装Certbot让我们加密证书

Let's Encrypt是一项新服务,通过自动API提供免费的SSL证书。有许多客户端可以与API通信,而Ubuntu包括其默认存储库中的官方客户端,但它有点过时,缺乏我们需要的一个重要功能。 相反,我们将从Ubuntu PPA或 个人包存档安装官方客户端。这些是替代存储库,其中包含更多最近或更晦涩的软件。首先,添加存储库。
sudo add-apt-repository ppa:certbot/certbot
您需要按 ENTER接受。然后,更新包列表以选取新存储库的包信息。
sudo apt-get update
最后,安装官方Let's Encrypt客户端,名为 certbot
sudo apt-get install certbot
现在我们已经 certbot certbot,让我们运行它来获取我们的证书。

第3步 - 运行Certbot

certbot需要回答Let's Encrypt API发出的加密挑战,以证明我们控制我们的域。 它使用端口 80 (HTTP)和/或 443 (HTTPS)来完成此操作。 我们只使用端口 80 ,所以让我们允许现在在该端口的传入流量:
sudo ufw allow http
OutputRule added
我们现在可以运行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在它们即将到期时自动更新它们。

第4步 - 设置Certbot自动续订

让我们加密的证书只有九十天有效。这是为了鼓励用户自动执行证书续订过程。我们需要设置一个定期运行的命令来检查到期的证书并自动更新。 为了每天运行更新检查,我们将使用 cron作为运行周期性作业的标准系统服务。 我们通过打开和编辑名为 crontab的文件告诉 cron要做什么。
sudo crontab -e
系统将提示您选择文本编辑器。选择你最喜欢的,你会看到默认的 crontab ,其中有一些帮助文本。粘贴到文件末尾的下一行,然后保存并关闭它。
crontab
. . .
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"
该行的 15 3 * * *部分表示“每天上午3:15运行以下命令”。 Certbot的 renew命令将检查系统上安装的所有证书,并更新任何设置为在三十天内到期的证书。 --noninteractive告知Certbot不要等待用户输入。 --post-hook "systemctl restart mosquitto"将重新启动Mosquitto以获取新证书,但前提是证书已更新。 这个 post-hook功能是Let's Encrypt客户端的旧版本缺少的,以及为什么我们从PPA而不是默认的Ubuntu存储库安装。没有它,我们必须每天重新启动Mosquitto,即使没有实际更新的证书。虽然您的MQTT客户端应配置为自动重新连接,但明智的做法是避免每天中断它们,这是没有正当理由的。 现在,自动证书更新已设置,我们将回到配置Mosquitto更安全。

第5步 - 配置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。不幸的是,我们通过互联网发送密码未加密。我们将通过添加SSL加密到Mosquitto来解决。

第6步 - 配置MQTT SSL

要在我们的连接上设置SSL加密,我们首先必须更新我们的加密证书的文件权限。 mosquitto进程不作为 root用户运行,而是出于安全原因作为用户 mosquitto运行。 默认情况下,SSL证书需要 root权限才能读取。 而不是更改文件的所有者,只需将它们放在 mosquitto组就 足够了
sudo chgrp -R mosquitto /etc/letsencrypt/archive/mqtt.example.com/
chgrp -R将更新指定目录的组以及其中的所有文件和目录。 然而,当Certbot更新证书时,它将创建新的文件,它将再次具有 组,当我们重新启动Mosquitto时,我们会得到一个错误。 要解决这个问题,我们需要在证书目录上设置SGID(set group ID)权限。 SGID只是另一个文件权限选项,如读,写和执行。在这种情况下,在证书目录上设置SGID将导致在目录中创建的所有后续文件继承 mosquitto组。 我们用 chmod g+s设置SGID位:
sudo chmod g+s /etc/letsencrypt/archive/mqtt.example.com/
通过列出目录来检查是否已进行所有更改:
sudo ls -al /etc/letsencrypt/archive/mqtt.example.com/
我们应该看到目录本身( . )的SGID位设置:
Outputdrwxr-sr-x 2 root mosquitto 4096 Oct  5 17:48 .
注意 drwxr-sr-x中的 s ,并确保组是 mosquitto 。 您还可以查看 mosquitto组的证书文件的 权限
Output-rw-r--r-- 1 root mosquitto 1809 Oct  1 16:42 cert1.pem
如果检出,我们准备更新我们的Mosquitto配置。打开我们以前启动的配置文件:
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。 接下来的三行, certfilecafilekeyfile ,都将Mosquitto指向相应的Let's Encrypt文件来设置加密连接。 保存并退出文件,然后重新启动Mosquitto以更新设置:
sudo systemctl restart mosquitto
更新防火墙以允许连接到端口 8883
sudo ufw allow 8883
OutputRule added
现在我们再次使用 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启用S​​SL,并告诉它在哪里查找根证书。 这些通常由操作系统安装,因此对于Mac OS,Windows等, mosquitto_pub使用根证书来验证Mosquitto服务器的证书是否由Let's Encrypt证书颁发机构正确签名。 请注意,即使您连接到 8883的标准安全端口, mosquitto_pubmosquitto_sub也不会尝试使用此选项(或类似的 --cafile选项)的SSL连接。 如果一切顺利的测试,我们会看到 你好再次出现在另一个 mosquitto_sub终端。这意味着您的服务器已完全设置!如果你想扩展MQTT协议来使用websockets,你可以按照最后一步。

第7步 - 通过Websockets配置MQTT(可选)

为了使用Web浏览器中的JavaScript来讲MQTT,协议适用于通过标准websockets工作。如果您不需要此功能,则可以跳过此步骤。 我们需要添加一个 listener块到我们的Mosqiutto配置:
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与上一个块相同,除了端口号和 protocol websockets行。 没有用于MQTT的官方标准化端口通过websockets,但 8083是最常见的。 保存并退出文件,然后重新启动Mosquitto。
sudo systemctl restart mosquitto
现在,打开防火墙中的端口 8083
sudo ufw allow 8083
为了测试这个功能,我们将使用一个基于浏览器的公共MQTT客户端。有几个,但是 mqtt-admin是简单和直接。 在浏览器中打开mqtt-admin 。您将看到以下内容: mqtt-admin的初始屏幕 按如下所示填写连接信息:
  • 协议应该是WSS(代表用W EB 小号 OCKET 小号 ecure)。
  • 主机应该是您的Mosquitto服务器的域, mqtt.example.com
  • 端口应为8083
  • 用户应该是您的Mosquitto用户名; 在这里,我们使用sammy
  • 密码应该是您选择的密码。
  • ClientId可以保留默认值mqtt-admin
按下 保存设置后mqtt-admin将连接到您的Mosquitto服务器。 在下一个屏幕中,填写 Topic作为 测试 ,输入任何有关 Payload的消息,然后按 发布 。 该消息将显示在 mosquitto_sub终端中。

结论

我们现在已经设置了一个安全的,密码保护的MQTT服务器,使用来自Let's Encrypt服务的自动更新SSL证书。这将作为一个强大和安全的消息平台,用于任何项目你梦想。一些流行的软件和硬件与MQTT协议工作良好包括:
  • OwnTracks是一个开源的地理跟踪应用,您可以在手机上安装。 OwnTracks将定期向MQTT服务器报告位置信息,然后您可以将其存储和显示在地图上,或者根据您的位置创建警报并激活物联网硬件。
  • Node-RED是一个基于浏览器的图形界面,用于将物联网“布线”在一起。您将一个节点的输出拖动到另一个节点的输入,并可以通过过滤器,在各种协议之间将信息路由到数据库等。 MQTT得到了Node-RED的很好的支持。
  • ESP8266是一个具有MQTT功能的便宜的wifi微控制器。你可以连接一个发布温度数据到一个主题,或者订阅气压压力主题,并在暴风雨来临时发出蜂鸣声!
这些只是MQTT生态系统中的几个流行示例。有更多的硬件和软件在那里说的协议。如果你已经有一个喜欢的硬件平台或软件语言,它可能有MQTT功能。有乐趣让你的“东西”彼此交谈!
赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏