Container - mosquitto MQTT server

本页介绍如何使用 MikroTik RouterOS 容器为 IoT 应用运行 eclipse-mosquitto MQTT 服务器,详细说明容器设置步骤,包括网络、环境变量和挂载,并带有 SSL 支持相关警告。

容器 - mosquitto MQTT 服务器

简介

容器功能引入 RouterOS,使得在路由器内运行各种任务所需的各种服务器成为可能。这对于希望减少网络中设备数量的人尤其相关。与其在单独的设备/机器上运行服务器,何不在路由器内部运行呢?

在本指南中,我们将展示如何安装一个名为 eclipse-mosquitto 的基本 MQTT broker(换句话说,服务器)。MQTT 协议是一个非常流行的选择,尤其是在 IoT 拓扑中。它是一种开放的 OASIS 和 ISO 标准轻量级发布-订阅网络协议,用于在设备之间传输消息。典型的拓扑由 MQTT 发布者(发送信息的设备)、MQTT broker(存储数据的服务器)和 MQTT 订阅者(监听服务器上发布数据的设备)组成。

RouterOS 支持 MQTT 发布、订阅功能,而现在我们也可以运行 MQTT broker。

我们即将使用的镜像可以通过 hub.docker 链接找到。

概要

在继续配置之前,请务必研究我们的容器指南。请务必查看免责声明和要求部分,了解所有风险以及你可能需要采取的必要步骤。

你可以通过链接找到支持的架构。

在本指南发布时,eclipse-mosquitto 镜像可用于 ARM32、ARM64 和 AMD64(CHR 和 x86)设备。在本示例中,我们将在 ARM32 架构设备上运行它 → RB1100AHx4。

警告

将展示非常基础且快速的配置。请务必查看 mosquitto 文档页面,了解你可以实现的其他选项和设置的更多信息。如果你想将其用于生产环境,请务必以任何可能的方式加固安全性:

  • 防火墙,以便仅允许来自你信任的 IP 地址访问容器;
  • 从 mosquitto broker/服务器端提高安全性 → 使用强密码、非标准端口等;
  • 使用 SSL MQTT。

容器配置

子菜单: /container

note: 需要 container 软件包。

容器模式

启用容器模式:

/system/device-mode/update container=yes

如果在 X86 上使用容器,你需要通过按下复位按钮或冷重启来确认 device-mode。

网络

为容器添加 veth 接口:

/interface/veth/add name=veth2 address=172.19.0.2/24 gateway=172.19.0.1

为容器创建网桥并将 veth 添加到其中:

/interface/bridge/add name=msqt
/ip/address/add address=172.19.0.1/24 interface=msqt
/interface/bridge/port/add bridge=msqt interface=veth2

如果需要 NAT(可选),为测试目的转发 TCP 1883 端口用于非 SSL MQTT(其中 192.168.88.1 是设备的 LAN IP 地址):

/ip/firewall/nat/add action=dst-nat chain=dstnat dst-address=192.168.88.1 dst-port=1883 protocol=tcp to-addresses=172.19.0.2 to-ports=1883

环境变量和挂载

按照 eclipse-mosquitto docker hub,为配置文件定义挂载。我们将不仅挂载配置文件,而是挂载整个文件夹,因为对于 SSL MQTT,我们还需要将证书上传到该文件夹:

/container/mounts/add list=msqt_config src=/mosquitto_mounted dst=/mosquitto/config

获取镜像

为简化配置,我们将从外部镜像库获取镜像,但你也可以通过 .tar 文件导入。

在本示例中,我们将使用设备自带的存储。RB1100AHx4 有 128 MB 磁盘空间,而基本的 mosquitto 安装占用的空间不应超过约 15 MB。

请确保你已相应设置 "Registry URL"、限制 RAM 使用量(如有必要),并为镜像设置一个目录:

/container/config/set registry-url=https://registry-1.docker.io tmpdir=pull

拉取镜像

/container/add remote-image=library/eclipse-mosquitto:latest interface=veth2 root-dir=mosquitto mountlists=msqt_config logging=yes

运行命令后,RouterOS 应开始 "extracting"(解压)软件包。检查 "File System" 中新建的文件夹,并使用命令 /container/print 监控容器状态。

设置 mosquitto 配置文件

要获取 mosquitto.conf 文件,我们需要使用 SFTP(基于 SSH 的文件传输)协议,因此请确保 SSH 服务已启用。你也可以使用 FTP。

打开你的命令终端(Windows 用户以管理员身份打开 "CMD",Linux 用户打开 "Linux Shell 或命令终端"),并导航到你希望下载配置文件的目录。例如,到你 "桌面" 上的 "Container" 文件夹:

C:\WINDOWS\system32>cd C:\Users\Administrator\Desktop\Container

C:\Users\Administrator\Desktop\Container>

向设备的 IP 地址发起 SFTP 连接:

C:\Users\Administrator\Desktop\Container>sftp admin@192.168.88.1
The authenticity of host '192.168.88.1 (192.168.88.1)' can't be established.
RSA key fingerprint is SHA256:lfxxs+xMrXlvP7hiHi9ZAEZlPi6/c5US+r6J7ljhkaA.
Are you sure you want to continue connecting (yes/no/[fingerprint])?yes
Warning: Permanently added '192.168.88.1' (RSA) to the list of known hosts.
Connected to 192.168.88.1.
sftp>

转到 mosquitto 配置文件所在文件夹(使用 dir 或 ls 命令查看当前所在文件夹的内容,使用 cd 命令转到你选择的文件夹)。默认情况下,配置从 "/mosquitto/config/mosquitto.conf" 加载,因此导航到那里并使用 get 命令下载它:

sftp> cd mosquitto/mosquitto/config
sftp> dir
mosquitto.conf
sftp> get mosquitto.conf
Fetching /mosquitto/mosquitto/config/mosquitto.conf to mosquitto.conf
/mosquitto/mosquitto/config/mosquitto.conf

通过你常用的文本编辑器(Notepad 或其他)打开 "mosquitto.conf",并用下面显示的两行覆盖它:

警告

在本节中,我们将为测试目的配置一个基本的非 SSL MQTT 设置。除非你确信所需的安全性/限制措施已经到位,否则非 SSL MQTT 对于生产环境并不安全。

对于生产环境,在可以捕获/嗅探 MQTT 流量的拓扑中,和/或将 MQTT 流量直接经由互联网路由(非本地)的拓扑中,请使用 SSL MQTT。查看 SSL MQTT 一节 获取更多信息。

listener 1883
allow_anonymous true
  • 第一行 listener 1883 将使安装程序监听指定端口上的传入网络连接。
  • 第二行 allow_anonymous true 决定是否允许不提供用户名即可连接的客户端进行连接。

使用相同的 mosquitto.conf 名称覆盖该文件。

在你创建了自己的自定义配置文件后,将其上传到已挂载的目录/文件夹 "mosquitto_mounted"。如果你还没有运行过容器,你将没有 "mosquitto_mounted" 文件夹,可以手动创建它。如果你运行过(/container/start 0),它应该已经自动创建:

sftp> dir
mosquitto           mosquitto_mounted   pub                 pull                skins

从编辑后的 mosquitto.conf 文件所在目录使用 SFTP,并将其 put 到已挂载的目录:

C:\Users\Administrator\Desktop\Container>dir
 Directory of C:\Users\Administrator\Desktop\Container

02/03/2023  12:09 PM    <DIR>          .
02/03/2023  12:09 PM    <DIR>          ..
02/03/2023  12:09 PM            40,449 mosquitto.conf
               1 File(s)         40,449 bytes
               2 Dir(s)  76,166,430,720 bytes free

C:\Users\Administrator\Desktop\Container>sftp admin@192.168.88.1
Connected to 192.168.88.1.
sftp> dir
mosquitto           mosquitto_mounted   pub                 pull                skins
sftp> cd mosquitto_mounted
sftp> put mosquitto.conf
Uploading mosquitto.conf to /mosquitto_mounted/mosquitto.conf
mosquitto.conf                                                                        100%  162    40.5KB/s   00:00

重启容器:

[admin@MikroTik] > /container/stop 0
[admin@MikroTik] > /container/start 0

请确保等待容器停止(使用 /container/print 命令后应显示 status=stopped),然后再重新启动它。

启动容器

在你确认容器已添加,并且使用 /container/print 后状态已变为 status=stopped 之后,即可启动它:

/container/start 0

如果你启用了容器日志,你将在 Logs 部分看到类似以下内容:

 12:12:46 container,info,debug 1707214366: mosquitto version 2.0.18 starting
 12:12:46 container,info,debug 1707214366: Config loaded from /mosquitto/config/mosquitto.conf.
 12:12:46 container,info,debug 1707214366: Opening ipv4 listen socket on port 1883.
 12:12:46 container,info,debug 1707214366: Opening ipv6 listen socket on port 1883.
 12:12:46 container,info,debug 1707214366: mosquitto version 2.0.18 running

MQTT 发布和订阅

子菜单: /iot/mqtt

note: 需要 iot 软件包。

添加一个 MQTT broker:

/iot/mqtt/brokers/add name=mosquitto username=test address=172.19.0.2

订阅 MQTT broker 和所需主题:

/iot/mqtt/subscribe broker=mosquitto topic=test/topic

发布一条静态 MQTT 消息:

/iot/mqtt/publish broker="mosquitto" topic="test/topic" message="{\"test\":\"123\"}"

检查订阅以查看收到的消息:

/iot/mqtt/subscriptions/recv/print
 0 broker=mosquitto topic="test/topic" data="{"test":"123"}" 
   time=2023-07-12 10:01:40 

你还可以检查容器日志(如果已启用),以确认 mosquitto 正在运行:

 12:47:28 container,info,debug 1675421248: New connection from 172.19.0.1:42240 on port 1883.
 12:47:28 container,info,debug 1675421248: New client connected from 172.19.0.1:42240 as MTD8580EC793C4 (p2, c1, k60, u'test').
 12:47:38 container,info,debug 1675421258: Client MTD8580EC793C4 disconnected.

SSL MQTT

将 非 SSL MQTT 用于生产环境并不安全。人们可以轻易地捕获/嗅探 broker 与发布者之间交换的数据包,从而获取用户凭据和其他敏感信息。

为提高安全性,请使用 SSL MQTT。

第一步是生成证书。在本示例中,我们将使用一个简单的 Root CA 场景(不要求设备/客户端证书)。

请使用官方 mosquitto-tls 用户指南 作为分步参考。

服务器配置

你应该已经生成了 ca.crt(证书颁发机构文件)、server.crt(服务器证书)和 server.key(服务器密钥):

C:\Users\Administrator\Desktop\Container>dir
 Directory of C:\Users\Administrator\Desktop\Container

07/12/2023  10:58 AM    <DIR>          .
07/12/2023  10:58 AM    <DIR>          ..
07/12/2023  10:56 AM             1,322 ca.crt
07/12/2023  10:56 AM             1,854 ca.key
07/12/2023  09:57 AM                35 mosquitto.conf
07/12/2023  10:58 AM             1,164 server.crt
07/12/2023  10:57 AM               960 server.csr
07/12/2023  10:56 AM             1,704 server.key
               6 File(s)          7,039 bytes
               2 Dir(s)  52,401,184,768 bytes free

通过你常用的文本编辑器(Notepad 或其他)打开已挂载的 "mosquitto.conf",并用下面显示的行覆盖它:

tls_version tlsv1.2
port 8883
allow_anonymous true
cafile /mosquitto/config/ca.crt
keyfile /mosquitto/config/server.key
certfile /mosquitto/config/server.crt
  • tls_version 行设置最低 TLS 版本。
  • port 8883 将使安装程序监听指定端口上的传入网络连接。
  • allow_anonymous true 决定是否允许不提供用户名即可连接的客户端进行连接。

警告

我们使用的是用于测试目的的基本 SSL 配置。allow_anonymous true 对于生产环境来说不是一个安全的设置。

  • cafile /mosquitto/config/ca.crt 行指定 CA 证书文件的路径。
  • keyfile /mosquitto/config/server.key 行指定服务器密钥文件的路径。
  • certfile /mosquitto/config/server.crt 行指定服务器证书文件的路径。

将证书文件和更新后的支持 SSL 的 mosquitto.conf 文件上传到已挂载的文件夹 "mosquitto_mounted":

C:\Users\Administrator\Desktop\Container>sftp admin@192.168.88.1
Connected to 192.168.88.1.
sftp> cd mosquitto_mounted
sftp> dir
mosquitto.conf
sftp> put ca.crt
Uploading ca.crt to /mosquitto_mounted/ca.crt
ca.crt                                                                                100% 1322   323.0KB/s   00:00
sftp> put server.crt
Uploading server.crt to /mosquitto_mounted/server.crt
server.crt                                                                            100% 1164   227.3KB/s   00:00
sftp> put server.key
Uploading server.key to /mosquitto_mounted/server.key
server.key                                                                            100% 1704   415.7KB/s   00:00
sftp> dir
ca.crt           mosquitto.conf   server.crt       server.key
sftp> put mosquitto.conf
Uploading mosquitto.conf to /mosquitto_mounted/mosquitto.conf
mosquitto.conf                                                                        100%  162    32.2KB/s   00:00

重启容器:

[admin@MikroTik] > /container/stop 0
[admin@MikroTik] > /container/start 0

使用日志确认 broker 监听 8883 端口:

 11:20:41 container,info,debug 1689160841: mosquitto version 2.0.15 starting
 11:20:41 container,info,debug 1689160841: Config loaded from /mosquitto/config/mosquitto.conf.
 11:20:41 container,info,debug 1689160841: Opening ipv4 listen socket on port 8883.
 11:20:41 container,info,debug 1689160841: Opening ipv6 listen socket on port 8883.
 11:20:41 container,info,debug 1689160841: mosquitto version 2.0.15 running
 11:22:24 system,info,account user admin logged in from 10.5.217.34 via local

测试连接

将 CA 证书(ca.crt)上传到 RouterOS 中设备的 "File List":

/file/print
Columns: NAME, TYPE, SIZE, CREATION-TIME
#  NAME                TYPE             SIZE  CREATION-TIME      
0  skins               directory              1970-01-01 03:00:02
1  pub                 directory              2023-01-04 11:05:04
2  disk7               disk                   2023-07-12 09:52:07
3  mosquitto           container store        2023-07-12 09:52:09
4  mosquitto_mounted   container store        2023-07-25 16:38:37
5  pull                directory              2023-07-12 09:52:09
6  ca.crt              .crt file        1322  2023-07-12 11:28:23

导入证书:

/certificate/import file-name=ca.crt passphrase=""

为 SSL 连接添加 MQTT broker:

/iot/mqtt/brokers/add name=mosquittoSSL username=test address=172.19.0.2 port=8883 ssl=yes

订阅 MQTT broker 和所需主题:

/iot/mqtt/subscribe broker=mosquittoSSL topic=test/topic

发布一条静态 MQTT 消息:

/iot/mqtt/publish broker="mosquittoSSL" topic="test/topic" message="{\"test\":\"123\"}"

检查订阅以查看收到的消息:

/iot/mqtt/subscriptions/recv/print
 0 broker=mosquittoSSL topic="test/topic" data="{"test":"123"}" 
   time=2023-07-12 10:20:40