3. 用户名密码认证:密码文件创建与管理、配置密码认证、密码加密存储机制

用户名密码认证,是 MQTT 最基础的一道防线。说白了,就是给 Broker 配个门禁,只有拿着正确工牌的人才能进。我见过不少项目,觉得 MQTT 是内网协议,干脆连密码都不设——结果被隔壁部门同事的测试脚本一顿乱发,整个生产环境差点崩了。

今天我们就来聊聊,怎么把这扇门装好、管好、锁好。

3.1 密码文件长什么样?

Mosquitto 的密码文件,格式其实很简单。每一行就是一个用户,用户名和密码用冒号隔开。但注意,密码不能是明文,必须是经过哈希处理的。

我个人习惯,先创建一个空文件,然后用 mosquitto_passwd 工具往里加用户。比如:

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

加完用户后,文件内容大概长这样:

device001:$6$SALTsalt$hashedpasswordstring...
admin:$6$anothersalt$anotherhashedstring...

看到那个 $6$ 了吗?这表示用的是 SHA-512 哈希。Mosquitto 默认就用这个,安全性还不错。

小技巧: 批量添加用户时,可以用 mosquitto_passwd -b 直接在命令行指定密码。但注意,这样密码会暴露在进程列表里,生产环境慎用。

3.2 密码加密存储机制

为什么不能存明文?我在项目中遇到过一件事:某客户把 MQTT 密码文件直接放在了 Git 仓库里,结果被扫描工具扒了出来,整个物联网设备群被当成肉鸡。嗯,从那以后,我对密码存储格外敏感。

Mosquitto 的密码加密流程是这样的:

  1. 用户输入密码时,工具生成一个随机盐值(Salt)。
  2. 将密码和盐值拼接,进行多次哈希迭代(默认 SHA-512,5000 轮)。
  3. 最终结果以 $算法ID$盐值$哈希值 的格式存入文件。

你想想看,就算攻击者拿到了密码文件,没有盐值也破解不了。而且每个用户的盐值都不一样,彩虹表基本废了。

核心要点: 密码文件必须设置严格的权限。我建议 chmod 640,属主设为 mosquitto 用户,组设为 mosquitto 组。千万别用 777,那是给自己挖坑。

下面这张图,帮你理清密码认证的完整流程:

MQTT 用户名密码认证流程 MQTT 客户端 Mosquitto Broker 密码文件 CONNECT (用户名+密码) 读取验证 提取用户名 查找对应哈希记录 SHA-512 哈希比对 返回结果 密码文件结构 device001:$6$salt$hash... admin:$6$salt2$hash2... 每个用户独立盐值 安全建议 • 文件权限 640 • 定期更换密码

3.3 配置密码认证

文件准备好了,怎么让 Broker 用起来?修改 Mosquitto 配置文件就行。我一般会在 /etc/mosquitto/conf.d/ 下单独建一个 auth.conf,方便管理。

# 开启密码认证
allow_anonymous false
password_file /etc/mosquitto/passwd

# 可选:开启 ACL 控制
# acl_file /etc/mosquitto/acl

配置完记得重启服务:

systemctl restart mosquitto
注意: 设置 allow_anonymous false 后,所有未提供用户名密码的客户端都会被拒绝连接。测试时记得先确认自己的客户端配置正确,别把自己锁在外面。我曾经在远程服务器上犯过这个错,结果只能让机房同事帮忙重启。

3.4 密码文件管理实战

日常运维中,密码文件的管理有几个关键操作:

操作 命令 说明
添加用户 mosquitto_passwd /etc/mosquitto/passwd username 交互式输入密码
删除用户 mosquitto_passwd -D /etc/mosquitto/passwd username 从文件中移除该用户
修改密码 mosquitto_passwd /etc/mosquitto/passwd username 重新输入即可覆盖旧密码
查看用户列表 cat /etc/mosquitto/passwd | cut -d: -f1 只显示用户名,不暴露哈希

这里有个坑:修改密码时,Mosquitto 不会自动重新加载密码文件。你需要发送 SIGHUP 信号或者重启服务。我个人习惯用 kill -HUP $(pidof mosquitto),这样不会中断现有连接。

避坑指南: 我曾经在批量更新设备密码时,直接覆盖了密码文件,结果忘了重启 Broker。那批设备全部连接失败,排查了半天才发现是 Broker 还在用旧文件。记住:改完文件,一定要让 Broker 重新加载。

3.5 密码强度与轮换策略

密码再加密,也架不住弱密码。我见过有人把密码设成 123456 或者 password,这种跟没设一样。建议至少 12 位,包含大小写字母、数字和特殊字符。

对于物联网设备,密码轮换是个头疼的问题。设备数量一多,手动改密码不现实。我推荐的做法是:

  • 设备级密码: 使用设备唯一标识(如序列号)加固定前缀,通过脚本批量生成。
  • 管理级密码: 定期更换,至少每 90 天一次。
  • 紧急密码: 用于故障排查,用完即废。

嗯,密码认证这块,说白了就是「防君子不防小人」。真正要防住专业攻击,还得配合 TLS 证书和 ACL 控制。但密码认证作为第一道门槛,做好了一样能挡住 90% 的乱入者。