MQTT Broker 安全配置:从基础到实战

好,咱们进入第二章。上一章聊了 MQTT 协议本身的安全短板,这一章咱们直接上手,把 Mosquitto 这个最流行的 Broker 给「锁」起来。

我个人习惯,不管项目多急,Broker 到手第一件事不是配功能,而是先做安全基线。你想想看,一个裸奔的 Mosquitto,默认监听 1883 端口,无认证、无加密,谁都能连上来乱发消息——这跟把家门钥匙挂在门把手上有什么区别?

咱们这一章分三块:基础安全配置、用户认证与 ACL、TLS/SSL 证书实战。我会把我在生产环境里踩过的坑、总结的经验都揉进去。

Mosquitto 安全配置三层架构 第一层:基础安全配置 绑定监听地址 · 关闭匿名访问 · 限制最大连接数 · 日志审计 核心目标:缩小攻击面,防止未授权访问 第二层:用户认证与 ACL 密码文件管理 · 用户名/密码认证 · 主题级访问控制列表 核心目标:确保只有合法用户能发布/订阅指定主题 第三层:TLS/SSL 传输加密 自签名证书 · CA 签发证书 · 双向认证 · 加密端口配置 核心目标:防止中间人攻击,保证数据传输机密性

2.1 基础安全配置:先把门关好

Mosquitto 的配置文件通常叫 mosquitto.conf。我见过太多人直接拿默认配置上线,结果被扫描工具扫到 1883 端口就沦陷了。咱们先做几件基础事。

2.1.1 绑定监听地址

默认配置监听所有网络接口(0.0.0.0)。如果你的 Broker 只需要对内网服务,就把它绑到内网 IP 上。

# 只监听内网地址
listener 1883 192.168.1.100

# 如果需要外网访问,单独开一个加密端口
listener 8883 0.0.0.0
我的习惯:生产环境我至少开两个 listener——一个内网明文端口(1883),一个外网 TLS 加密端口(8883)。内网设备走明文,外网设备必须走 TLS。这样既保证性能,又守住安全底线。

2.1.2 关闭匿名访问

默认情况下,Mosquitto 允许匿名客户端连接。这必须关掉。

# 禁止匿名访问
allow_anonymous false

嗯,这里要注意:关掉匿名后,所有客户端都必须提供用户名和密码才能连接。如果你还没配用户文件,连你自己都连不上——别问我怎么知道的,我在测试环境里吃过这个亏。

2.1.3 限制最大连接数

防止恶意客户端耗尽 Broker 资源。

# 最大客户端连接数
max_connections 1000

2.1.4 日志审计

出事之后查日志,是安全运维的基本功。

# 日志配置
log_type all
log_dest file /var/log/mosquitto/mosquitto.log
connection_messages true
避坑指南:我曾经在一个项目中,日志级别开得太低,结果被攻击后根本查不到是谁在什么时候做了什么操作。建议生产环境至少开启 log_type all,并配合日志轮转工具(如 logrotate)防止磁盘写满。

2.2 用户认证与 ACL 配置

关掉匿名只是第一步。接下来咱们要建立用户体系,并且用 ACL 控制每个用户能干什么。

2.2.1 创建密码文件

Mosquitto 使用 mosquitto_passwd 工具管理密码文件。

# 创建密码文件(如果文件不存在,加 -c 参数)
mosquitto_passwd -c /etc/mosquitto/passwd admin

# 添加更多用户(不加 -c)
mosquitto_passwd /etc/mosquitto/passwd sensor01
mosquitto_passwd /etc/mosquitto/passwd user_zhang

密码文件的内容长这样:

admin:$6$SALTsalt$hashedpassword...
sensor01:$6$SALTsalt$hashedpassword...
user_zhang:$6$SALTsalt$hashedpassword...

密码是加盐哈希存储的,不是明文。这一点 Mosquitto 做得还算靠谱。

2.2.2 配置文件中启用密码认证

# 指定密码文件路径
password_file /etc/mosquitto/passwd

2.2.3 ACL 配置实战

ACL(Access Control List)让你精确控制每个用户能发布和订阅哪些主题。这是物联网场景下最核心的安全手段之一。

先创建一个 ACL 文件:

# /etc/mosquitto/acl.conf

# 管理员可以访问所有主题
user admin
topic readwrite #

# 传感器只能发布数据到自己的主题
user sensor01
topic write sensor/temperature/+
topic write sensor/humidity/+

# 普通用户只能订阅特定主题
user user_zhang
topic read sensor/temperature/+
topic read sensor/humidity/+

然后在配置文件中引用:

# 启用 ACL
acl_file /etc/mosquitto/acl.conf

# 如果 ACL 中没有匹配的规则,默认拒绝
acl_deny true
核心原则:最小权限原则。每个用户只给完成其任务所需的最小权限。传感器只需要写权限,不需要读;普通用户只需要读,不需要写。管理员账号要严格管控。

2.2.4 动态 ACL(进阶)

如果你的用户和权限经常变化,静态 ACL 文件就不够灵活了。Mosquitto 支持通过插件实现动态 ACL,比如使用 MySQL 或 Redis 存储权限规则。

# 使用 auth_plugin 实现动态认证
auth_plugin /usr/lib/mosquitto_dynamic_security.so
auth_opt_backend mysql
auth_opt_host localhost
auth_opt_user mosquitto
auth_opt_password secret

这个配置我一般在大型物联网平台中使用,小项目用静态 ACL 就够了。

2.3 TLS/SSL 证书配置实战

认证和 ACL 解决了「你是谁」和「你能干什么」的问题,但数据在传输过程中还是明文的。如果有人抓包,你的传感器数据、控制指令一览无余。TLS/SSL 就是解决这个问题的。

2.3.1 证书类型选择

证书类型 适用场景 成本 安全等级
自签名证书 开发测试、内网环境 免费 中
CA 签发证书 生产环境、外网访问 收费/免费(Let's Encrypt) 高
双向认证(mTLS) 高安全要求场景 较高 极高

2.3.2 自签名证书生成

我演示一下自签名证书的生成过程。生产环境建议用 CA 签发的证书,但自签名证书用于测试和内部网络完全够用。

# 1. 生成 CA 根证书
openssl req -new -x509 -days 3650 -extensions v3_ca \
  -keyout ca.key -out ca.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=MyCA"

# 2. 生成服务器私钥和证书请求
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=mqtt.example.com"

# 3. 用 CA 签发服务器证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

2.3.3 Mosquitto TLS 配置

# 监听加密端口
listener 8883

# 证书路径
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# 要求客户端提供证书(双向认证)
require_certificate false

# 如果启用双向认证,设为 true
# require_certificate true
注意:私钥文件(server.key)的权限必须严格限制,建议设为 600,属主为 mosquitto 用户。我曾经见过有人把私钥设为 644,结果被内部人员拷贝走了——那跟把保险柜密码贴在柜门上一样。

2.3.4 客户端连接示例

配置好之后,客户端连接方式如下:

# 单向认证(客户端验证服务器)
mosquitto_sub -h mqtt.example.com -p 8883 \
  --cafile /etc/mosquitto/certs/ca.crt \
  -t "sensor/temperature" -u "user_zhang" -P "password"

# 双向认证(双方互相验证)
mosquitto_pub -h mqtt.example.com -p 8883 \
  --cafile /etc/mosquitto/certs/ca.crt \
  --cert /etc/mosquitto/certs/client.crt \
  --key /etc/mosquitto/certs/client.key \
  -t "sensor/temperature" -m "25.5" \
  -u "sensor01" -P "password"

2.3.5 使用 Let's Encrypt 免费证书

对于面向公网的 Broker,我强烈建议用 Let's Encrypt。免费、自动续期、浏览器信任。

# 安装 certbot
apt-get install certbot

# 申请证书(需要域名和 80 端口)
certbot certonly --standalone -d mqtt.example.com

# 证书路径
# /etc/letsencrypt/live/mqtt.example.com/fullchain.pem
# /etc/letsencrypt/live/mqtt.example.com/privkey.pem

# 配置 Mosquitto
listener 8883
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
我的经验:Let's Encrypt 证书每 90 天过期,一定要配置自动续期。我写了一个 cron 任务,每月 1 号自动续期并重启 Mosquitto。别等到证书过期了才发现——我在生产环境里经历过一次,所有客户端同时断开,那场面...嗯,不想再体验第二次。

2.4 本章小结

咱们这一章把 Mosquitto 的安全配置从里到外过了一遍。从基础配置(绑定地址、关闭匿名、限制连接、日志审计),到用户认证与 ACL(密码文件、主题级权限控制),再到 TLS/SSL 证书配置(自签名证书、CA 证书、Let's Encrypt)。

这三层配置叠加起来,你的 Broker 基本上就具备了企业级的安全防护能力。当然,安全是一个持续的过程,没有「配完就万事大吉」这回事。定期审计配置、更新证书、检查日志,这些都要形成习惯。