3. Mosquitto进阶配置:监听器配置、认证与授权、TLS/SSL加密、WebSocket支持

好,咱们接着往下聊。上一章我们把Mosquitto跑起来了,能发能收,感觉挺爽是吧?但说实话,那只是皮毛。生产环境里,你不可能裸奔着让客户端随便连。这一章,咱们来点硬核的——监听器、认证授权、TLS加密,还有WebSocket支持。这些都是我实际项目中天天打交道的东西,踩过的坑也不少,今天一并倒给你。

3.1 监听器配置:不止一个端口那么简单

Mosquitto默认监听1883端口,这是MQTT的明文端口。但实际场景中,你可能需要多个监听器——比如一个给内网设备用(明文),一个给外网用(加密),甚至再来一个给WebSocket用。

我个人习惯把监听器配置写在配置文件最前面,清晰明了。来看个例子:

# 监听1883端口,明文,绑定内网IP
listener 1883 192.168.1.100
protocol mqtt

# 监听8883端口,TLS加密,绑定公网IP
listener 8883 0.0.0.0
protocol mqtt
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# 监听8083端口,WebSocket支持
listener 8083 0.0.0.0
protocol websockets

每个listener后面跟端口和IP地址。IP可以省略,默认监听所有接口。但我在项目中遇到过一个问题——如果你不指定IP,Mosquitto会监听所有网卡,包括Docker的虚拟网卡,有时候会引发奇怪的路由问题。所以,我建议你养成习惯,显式指定IP。

小技巧: 如果你有多个网卡,可以用listener 1883 0.0.0.0监听所有,但最好还是明确绑定到业务网卡上。我曾经因为没指定IP,导致内网设备连到了错误的网卡上,排查了半天。

3.2 认证与授权:别让陌生人进来

默认配置下,Mosquitto允许匿名连接。这在开发环境没问题,但生产环境绝对不行。你想想看,谁都能往你的Broker上发消息,那不乱套了?

Mosquitto支持多种认证方式,最常用的是密码文件和ACL(访问控制列表)。

3.2.1 密码文件认证

先创建密码文件。Mosquitto自带一个工具叫mosquitto_passwd

# 创建密码文件,添加用户
mosquitto_passwd -c /etc/mosquitto/passwd user1
# 会提示输入密码,输入两次即可

# 添加更多用户(不加-c,否则会覆盖)
mosquitto_passwd /etc/mosquitto/passwd user2

然后在配置文件中启用:

allow_anonymous false
password_file /etc/mosquitto/passwd

这样,客户端连接时必须提供用户名和密码。嗯,这里要注意——密码文件里的密码是经过哈希的,不是明文,所以相对安全。但别以为这样就万事大吉了,明文传输的密码还是会被抓包看到。所以,TLS加密才是王道。

3.2.2 ACL授权:谁可以做什么

认证只是第一步,授权才是关键。ACL文件定义了每个用户能订阅和发布哪些主题。

创建一个ACL文件,比如/etc/mosquitto/acl

# 允许user1读写所有以sensor/开头的主题
user user1
topic readwrite sensor/#

# 允许user2只读sensor/temperature
user user2
topic read sensor/temperature

# 允许匿名用户读取public/主题
pattern read public/%

然后在配置中引用:

acl_file /etc/mosquitto/acl

ACL的规则是从上到下匹配的,第一条匹配到了就停止。所以,把更具体的规则放在前面,通用的放后面。我在项目中遇到过一个问题——有个用户明明有权限,但就是连不上。后来发现是ACL顺序搞反了,通用规则先匹配到了,直接拒绝了。嗯,这种坑踩一次就记住了。

避坑指南: 我曾经在生产环境里忘记重启Mosquitto,改了ACL文件后以为生效了。结果用户反馈权限不对,排查了半天才发现是没重启。记住,修改配置后一定要重启服务,或者用kill -HUP发送SIGHUP信号重载配置。

3.3 TLS/SSL加密:给数据穿上防弹衣

明文传输的MQTT,说白了就是在裸奔。任何能抓到包的人都能看到你的消息内容。TLS加密就是给数据穿上防弹衣。

3.3.1 生成证书

你需要三样东西:CA证书、服务器证书、服务器私钥。可以用OpenSSL自己生成,也可以用Let's Encrypt这样的免费CA。

自己生成CA和服务器证书的步骤:

# 1. 生成CA私钥和证书
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.crt

# 2. 生成服务器私钥和证书请求
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr

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

然后把server.crtserver.key放到Mosquitto的证书目录,比如/etc/mosquitto/certs/

3.3.2 配置TLS监听器

在配置文件中添加TLS监听器:

listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1.2

这里有个细节——tls_version建议指定为tlsv1.2或更高。TLSv1.0和1.1已经被废弃了,不安全。我见过有些老系统还在用TLSv1.0,说实话,那跟没加密区别不大。

3.3.3 客户端连接

客户端连接TLS端口时,需要指定CA证书来验证服务器身份。以mosquitto_pub为例:

mosquitto_pub -h broker.example.com -p 8883 \
  --cafile /path/to/ca.crt \
  -t "test/topic" -m "Hello TLS" \
  -u user1 -P password
重要提醒: 如果你用了TLS,密码还是通过加密通道传输的,所以相对安全。但别忘了,客户端也需要验证服务器的证书。如果客户端不验证CA,那中间人攻击还是有可能的。我见过有人图省事,客户端不验证证书,结果被中间人劫持了。嗯,这种坑千万别踩。

3.4 WebSocket支持:让浏览器也能玩MQTT

传统的MQTT基于TCP,浏览器里没法直接用。但WebSocket可以。Mosquitto从1.4版本开始支持WebSocket,配置起来很简单。

3.4.1 启用WebSocket监听器

在配置文件中添加:

listener 8083
protocol websockets

就这么简单。客户端可以通过WebSocket连接到ws://broker.example.com:8083

如果你需要WebSocket也走TLS,那就用wss://

listener 8084
protocol websockets
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

3.4.2 前端连接示例

浏览器端用MQTT.js库连接:

const mqtt = require('mqtt')
const client = mqtt.connect('ws://broker.example.com:8083', {
  username: 'user1',
  password: 'password'
})

client.on('connect', function () {
  console.log('连接成功')
  client.subscribe('sensor/#')
})

client.on('message', function (topic, message) {
  console.log(topic, message.toString())
})

WebSocket支持让MQTT的应用场景大大扩展了。我在项目中做过一个实时监控大屏,前端直接用WebSocket连Broker,数据延迟不到100毫秒。说实话,效果比轮询好太多了。

小技巧: WebSocket连接会占用更多资源,因为每个连接都是一个长连接。如果并发量很大,建议在Broker前面加一层Nginx做负载均衡和WebSocket代理。我有个项目高峰期有5000个WebSocket连接,单机Mosquitto扛不住,加了Nginx后稳如老狗。

3.5 综合配置示例

最后,给你一个完整的配置示例,把上面所有内容整合到一起:

# 基础配置
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log

# 明文监听器(内网)
listener 1883 192.168.1.100
protocol mqtt

# TLS监听器(外网)
listener 8883 0.0.0.0
protocol mqtt
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1.2

# WebSocket监听器(明文)
listener 8083 0.0.0.0
protocol websockets

# WebSocket监听器(加密)
listener 8084 0.0.0.0
protocol websockets
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# 认证与授权
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

这个配置基本覆盖了大部分生产场景。你根据实际需求调整IP和端口就行。我个人习惯把不同用途的监听器分开,方便后期排查问题。比如内网设备连1883,外网设备连8883,前端页面连8083或8084。出了问题,看日志就知道是哪个通道的问题。

好了,这一章的内容就到这里。下一章咱们聊聊Mosquitto的集群和高可用部署,那才是真正的大招。到时候我会分享一些我在大规模部署中踩过的坑,保证让你少走弯路。