如何在 Ubuntu 20.04 上安装和保护 Mosquitto MQTT 消息代理
在此页
- 先决条件
- 第 1 步 - 安装 Mosquitto 服务器和客户端
- 第 2 步 - 配置 MQTT 密码身份验证
- 第 3 步 - 测试 Mosquitto 客户端
- 第 4 步 - 安装 SSL
- 第 5 步 - 配置 MQTT SSL
- 第 6 步 - 配置 SSL 续订
- 第 7 步 - 配置 Websocket
- 结论
Mosquitto 是一个使用消息队列遥测传输 (MQTT) 协议的开源消息代理。该协议旨在为物联网 (IoT) 设备提供轻量级通信。它通常用于车辆的 GPS 跟踪、家庭自动化、环境传感器和大规模数据收集。
MQTT 协议在 TCP/IP 模型之上运行。由于是轻量级的,它的代码占用空间小,因此您可以使用最少的资源为设备创建应用程序。它依赖于发布/订阅模型。在此模型中,客户端连接到 Mosquitto 服务器,后者充当代理将信息发送到订阅频道的其他客户端。
在本教程中,您将安装 Mosquitto 并设置代理以使用 SSL 来保护通信。
先决条件
- 具有 sudo 权限的非根用户的 Ubuntu 20.04 服务器。
- 指向您的服务器的域名 (
myqtt.example.com
)。
第 1 步 - 安装 Mosquitto 服务器和客户端
Ubuntu 附带旧的 1.6 版本的 Mosquitto。要安装最新版本,请添加官方 Mosquitto 存储库。
$ sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa
安装 Mosquitto 服务器和客户端。
$ sudo apt install mosquitto mosquitto-clients
检查服务器的状态。
$ sudo systemctl status mosquitto
? mosquitto.service - Mosquitto MQTT Broker
Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-01-25 09:18:40 UTC; 25s ago
Docs: man:mosquitto.conf(5)
man:mosquitto(8)
Main PID: 119694 (mosquitto)
Tasks: 1 (limit: 2274)
Memory: 1.0M
CGroup: /system.slice/mosquitto.service
??119694 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Jan 25 09:18:39 <userid> systemd[1]: Starting Mosquitto MQTT Broker...
Jan 25 09:18:40 <userid> systemd[1]: Started Mosquitto MQTT Broker.
第 2 步 - 配置 MQTT 密码验证
Mosquitto 附带一个实用程序来生成名为 mosquitto_passwd
的密码文件。 Mosquitto 将所有配置存储在 /etc/mosquitto
目录中。
运行以下命令在 /etc/mosquitto/passwd
为用户名 username
生成加密密码文件。输入您选择的密码。
$ sudo mosquitto_passwd -c /etc/mosquitto/passwd username
Password:
Reenter password:
接下来,在/etc/mosquitto/conf.d
目录下创建一个default.conf
文件并打开进行编辑。
$ sudo nano /etc/mosquitto/conf.d/default.conf
粘贴以下行以指定密码文件的位置。如果您省略侦听器字段,它将始终匿名连接,而不管配置如何。
listener 1883
password_file /etc/mosquitto/passwd
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
重新启动 Mosquitto 服务器以实施更改。
$ sudo systemctl restart mosquitto
第 3 步 - 测试 Mosquitto 客户端
根据用例,您可以使用 Mosquitto 客户端发送和接收关于不同主题的消息。客户端是订阅者或发布者。
下一步是订阅主题。在 MQTT 协议中,主题是指服务器/代理用来为连接的客户端过滤消息的字符串。以下是您可以在家庭自动化应用程序中使用的一些示例主题。
- 家/灯/sitting_room
- 家/灯/厨房
- 家/灯/master_bedroom
- 家/灯/kids_bedroom
要订阅主题,请在主题后运行 mosquitto_sub -t
命令。例如,要订阅 home/lights/kitchen
主题,请运行以下命令。
$ mosquitto_sub -u username -P YOUR_PASSWORD -t "home/lights/kitchen"
不要关闭现有窗口。打开一个新的终端窗口,使用以下命令向 home/lights/kitchen
主题发布消息。
$ mosquitto_pub -u username -P YOUR_PASSWORD -m "ON" -t "home/lights/kitchen"
返回到第一个终端窗口,您将收到 ON
有效负载。
ON
接下来,从第二个终端发送关于同一主题的 OFF
消息。
$ mosquitto_pub -u username -P YOUR_PASSWORD -m "OFF" -t "home/lights/kitchen"
第一个终端将显示新发布的消息。
ON
OFF
如果您尝试发送未经身份验证的评论,它将失败。例如,尝试以下命令。
$ mosquitto_sub -t "home/lights/sitting_room"
Connection error: Connection Refused: not authorised.
不推荐这样做,但是如果你想在没有身份验证的情况下运行命令,你需要将以下行添加到 /etc/mosquitto/conf.d/default.conf
文件中。
allow_anonymous true
第 4 步 - 安装 SSL
要使用 Lets Encrypt 安装 SSL 证书,我们需要下载 Certbot 工具。为此,我们将使用 Snapd 包安装程序。
安装快照安装程序。
$ sudo apt install snapd
确保您的 Snapd 版本是最新的。
$ sudo snap install core
$ sudo snap refresh core
安装 Certbot。
$ sudo snap install --classic certbot
使用以下命令通过创建指向 /usr/bin
目录的符号链接来确保 Certbot 命令运行。
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
生成 SSL 证书。
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m -d mqtt.example.com
上述命令会将证书下载到服务器上的 /etc/letsencrypt/live/mqtt.example.com
目录。
生成 Diffie-Hellman 组证书。
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
为 Lets Encrypt 自动更新创建一个挑战网站根目录。
$ sudo mkdir -p /var/lib/letsencrypt
创建 Cron 作业以更新 SSL。它将每天运行以检查证书并在需要时更新。为此,首先,创建文件 /etc/cron.daily/certbot-renew
并打开它进行编辑。
$ sudo nano /etc/cron.daily/certbot-renew
粘贴以下代码。
#!/bin/sh
certbot renew --cert-name mqtt.example.com --webroot -w /var/lib/letsencrypt/
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
更改任务文件的权限以使其可执行。
$ sudo chmod +x /etc/cron.daily/certbot-renew
第 5 步 - 配置 MQTT SSL
现在我们已经准备好 SSL 证书,我们需要为 Mosquitto 提供对它们的访问。为此,我们需要将证书复制到 Mosquitto 可以访问它们的位置。
$ sudo cp /etc/letsencrypt/live/mqtt.example.com/fullchain.pem /etc/mosquitto/certs/server.pem
$ sudo cp /etc/letsencrypt/live/mqtt.example.com/privkey.pem /etc/mosquitto/certs/server.key
将 /etc/mosquitto/certs
目录的所有权更改为安装期间创建的 mosquitto
用户。
$ sudo chown mosquitto: /etc/mosquitto/certs
为 Mosquitto 启用 SSL 加密的下一步是指定 SSL 证书的位置。打开配置文件进行编辑。
$ sudo nano /etc/mosquitto/conf.d/default.conf
将以下代码粘贴到文件末尾。
. . .
listener 8883
certfile /etc/mosquitto/certs/server.pem
cafile /etc/ssl/certs/ISRG_Root_X1.pem
keyfile /etc/mosquitto/certs/server.key
dhparamfile /etc/ssl/certs/dhparam.pem
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。请务必在文件末尾留下一个尾随换行符。
listener 8883
部分设置了加密的监听器。是MQTT+SSL的标准端口,简称MQTTS。接下来的四行指定 SSL 文件的位置。
重新启动 Mosquitto 以更新设置。
$ sudo systemctl restart mosquitto
您需要更新防火墙以允许连接到端口 8883。
$ sudo ufw allow 8883
接下来,我们需要使用 mosquitto_pub
命令测试功能。
$ mosquitto_pub -h mqtt.example.com -t "home/lights/kitchen" -m "hello" -p 8883 --capath /etc/ssl/certs/ -u username -P YOUR_PASSWORD
如您所见,我们包含了某些附加参数,包括端口号和 SSL 证书的路径。每当您需要使用 SSL 时,您总是必须指定完整的主机名,即 mqtt.example.com
而不是 localhost
否则,它会报错。
您还需要每次都添加 --capath
指令。它告诉 Mosquitto 客户端查找操作系统安装的根证书。
第 6 步 - 配置 SSL 续订
Certbot 会在您的证书过期前自动续订它。但是需要告诉它把更新后的证书复制到/etc/mosquitto/certs
目录下,然后重启Mosquitto服务。
我们将通过创建一个 shell 脚本来做到这一点。在 /etc/letsencrypt/renewal-hooks/deploy
目录中创建文件 mosquitto-copy.sh
。
$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh
将以下代码粘贴到其中。将 MY_DOMAIN
变量的值替换为您的域。 $ {RENEWED_LINEAGE}
变量在更新时指向/etc/letsencrypt/live/mqtt.example.com
目录。
# Set which domain this script will be run for
MY_DOMAIN=mqtt.example.com
# Set the directory that the certificates will be copied to.
CERTIFICATE_DIR=/etc/mosquitto/certs
if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then
# Copy new certificate to Mosquitto directory
cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key
# Set ownership to Mosquitto
chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Ensure permissions are restrictive
chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Tell Mosquitto to reload certificates and configuration
pkill -HUP -x mosquitto
fi
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
使文件可执行。
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh
该脚本将在每次成功续订证书时自动运行。
如果您正在运行 Mosquitto 和像 Nginx 这样的 Web 服务器,您需要指示 Certbot 在更新之前停止服务器并在完成后重新启动它。为此,打开文件 etc/letsencrypt/renewal/mqtt.example.com.conf
。
$ sudo nano /etc/letsencrypt/renewal/mqtt.example.com.conf
在文件末尾添加以下行。根据您正在使用的网络服务器更改命令。
pre_hook = systemctl stop nginx
post_hook = systemctl start nginx
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
运行 Certbot 试运行以进行验证。
$ sudo certbot renew --dry-run
如果您没有看到任何错误,则表示一切都已设置。
第 7 步 - 配置 Websocket
您可以使用 Websockets 功能将 Mosquitto 配置为在使用 Javascript 的浏览器中使用 MQTT 协议。要启用它,请打开配置文件。
$ sudo nano /etc/mosquitto/conf.d/default.conf
将以下行粘贴到文件末尾。
. . .
listener 8083
protocol websockets
certfile /etc/mosquitto/certs/server.pem
cafile /etc/ssl/certs/ISRG_Root_X1.pem
keyfile /etc/mosquitto/certs/server.key
dhparamfile /etc/ssl/certs/dhparam.pem
通过按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
如果您注意到,除了端口号和协议字段外,它与我们用于启用 SSL 的块相同。 8083 是 MQTT 使用 WebSockets 进行对话的最常用端口。
重新启动 Mosquitto 服务。
$ sudo systemctl restart mosquitto
打开8083端口。
$ sudo ufw allow 8083
我们需要使用基于浏览器的 MQTT 客户端来测试 WebSockets 功能。有很多可用的客户端,但我们将使用 HiveMQ Websocket 客户端来实现我们的目的。在浏览器中启动客户端,您将看到以下内容。

如上面的屏幕截图所示,填写如图所示的字段。
- 主机应该是您的 Mosquitto 服务器的域,mqtt.example.com。
- 端口应为 8083。
- ClientID 字段可以保留原样。
- 用户名应该是您的 Mosquitto 用户名。
- 密码应该是您在上面创建的密码。
- 选中 SSL 框。
按“连接”按钮,HiveMQ 客户端将连接到您的 Mosquitto 服务器。
连接后,输入 home/lights/kitchen
作为主题,输入任何消息并按发布。

该消息将显示在您的 mosquitto_sub
终端窗口中,确认连接成功。

这说明Websockets实现成功。
结论
这结束了我们在基于 Ubuntu 20.04 的机器上设置安全、密码保护和 SSL 加密的 MQTT 服务器。如果您有任何问题,请在下面的评论中发表。