介绍
MQTT是一种机器到机器的消息传递协议,旨在为“物联网”设备提供轻量级的发布/订阅通信。 它通常用于地理跟踪车队,家庭自动化,环境传感器网络和公用事业规模数据收集。
Mosquitto是一种流行的MQTT服务器(或MQTT中的代理 ),具有出色的社区支持,易于安装和配置。
在本教程中,我们将安装Mosquitto并设置我们的代理以使用SSL来保护受密码保护的MQTT通信。
先决条件
在开始本教程之前,您需要:
- 一个Ubuntu 18.04服务器,具有非root,sudo启用的用户和基本防火墙设置,详见本Ubuntu 18.04服务器设置教程 。
- 根据如何使用DigitalOcean设置主机名,指向服务器的域名。 本教程将始终使用
mqtt.example.com
。 - 自动更新的Let's加密SSL证书,用于您的域和Mosquitto,使用Certbot工具生成。 您可以在Ubuntu 18.04上的如何使用Certbot独立模式检索Let的加密SSL证书中学习如何设置它。 您可以在第4步中将
systemctl restart mosquitto
添加为renew_hook
。确保使用在先前先决条件步骤中配置的相同域。
第1步 - 安装Mosquitto
Ubuntu 18.04在其默认软件存储库中有一个相当新版本的Mosquitto,因此我们可以从那里安装它。
首先,使用非root用户登录并使用apt update
包列表:
sudo apt update
现在,使用apt install
安装Mosquitto:
sudo apt install mosquitto mosquitto-clients
默认情况下,Ubuntu将在安装后启动Mosquitto服务。 我们来测试默认配置。 我们将使用我们刚刚安装的Mosquitto客户端之一来订阅我们经纪人的主题。
主题是您向其发布消息和订阅的标签。 它们按层次排列,因此您可以使用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_pub
相同,但这次我们使用额外的-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
这应该打开一个空文件。 粘贴如下:
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.
在我们再次尝试使用密码之前,请再次切换到第二个终端窗口,并使用用户名和密码订阅“test”主题:
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的加密证书的位置。 打开我们之前启动的配置文件:
sudo nano /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的加密证书颁发机构正确签名。 重要的是要注意, mosquitto_pub
没有此选项(或类似的--cafile
选项), mosquitto_pub
和mosquitto_sub
将不会尝试SSL连接,即使您连接到8883
的标准安全端口也是如此。
如果测试结果一切正常,我们会再次看到hello出现在另一个mosquitto_sub
终端中。 这意味着您的服务器已完全设置好! 如果您想扩展MQTT协议以使用websockets,您可以按照最后一步操作。
第4步 - 通过Websockets配置MQTT(可选)
为了在Web浏览器中使用JavaScript来说MQTT,该协议适用于标准websockets。 如果您不需要此功能,则可以跳过此步骤。
我们需要在Mosquitto配置中再添加一个listener
块:
sudo nano /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在websockets上没有官方标准化端口,但8083
是最常见的。
保存并退出该文件,然后重新启动Mosquitto。
sudo systemctl restart mosquitto
现在,在防火墙中打开端口8083
。
sudo ufw allow 8083
要测试此功能,我们将使用基于浏览器的公共MQTT客户端。 有一些,但Eclipse Paho JavaScript Client简单易用。 在浏览器中打开Paho客户端 。 你会看到以下内容:
填写连接信息如下:
- 主机应该是您的Mosquitto服务器的域,
mqtt.example.com
。 - 端口应为
8083
。 - ClientId可以保留为默认值js-utility-DI1m6 。
- 路径可以保留为默认值/ ws 。
- 用户名应该是您的Mosquitto用户名; 在这里,我们使用了sammy 。
- 密码应该是您选择的密码。
其余字段可以保留其默认值。
按下Connect后 ,基于Paho浏览器的客户端将连接到您的Mosquitto服务器。
要发布消息,请导航到“ 发布消息”窗格,将“ 主题”填写为“ 测试” ,然后在“ 消息”部分中输入任何消息。 接下来,按发布 。 该消息将显示在您的mosquitto_sub
终端中。
结论
我们现在已经建立了一个安全的,受密码保护且受SSL保护的MQTT服务器。 这可以作为您梦寐以求的任何项目的强大而安全的消息传递平台。 一些与MQTT协议配合良好的流行软件和硬件包括:
- OwnTracks ,一款可以在手机上安装的开源地理跟踪应用。 OwnTracks将定期向您的MQTT服务器报告位置信息,然后您可以将其存储并显示在地图上,或根据您的位置创建警报并激活IoT硬件。
- Node-RED是一个基于浏览器的图形界面,用于将物联网“连接”在一起。 您将一个节点的输出拖动到另一个节点的输入,并可以通过过滤器,各种协议之间,数据库等信息路由信息。 Node-RED非常支持MQTT。
- ESP8266是一款具有MQTT功能的廉价wifi微控制器。 您可以连接一个以将温度数据发布到主题,或者可能订阅气压主题并在风暴来临时发出蜂鸣声!
这些只是MQTT生态系统中的一些流行示例。 有更多的硬件和软件可以说协议。 如果您已经拥有最喜欢的硬件平台或软件语言,它可能具有MQTT功能。 玩得开心让你的“事情”互相交流!