)
环境信息系统Windows 10Mosquitto 版本2.1.2OpenSSL 版本4.0.0工作目录E:\mqtt-tls一、工具安装1.1 MosquittowingetinstallEclipseFoundation.Mosquitto安装后自动加入 PATH。验证mosquitto-h1.2 OpenSSLwingetinstallShiningLight.OpenSSL.Light若安装后命令找不到手动将C:\Program Files\OpenSSL-Win64\bin加入系统 Path 变量sysdm.cpl→ 高级 → 环境变量 → Path → 新建 → 粘贴路径。验证openssl version1.3 创建工作目录mkdirE:\mqtt-tlscdE:\mqtt-tls命令含义mkdirmake directory创建文件夹cdchange directory切换当前目录二、实验一裸 MQTT 发布/订阅目的理解 Broker 核心工作接受连接 → 记录订阅 → 匹配转发。终端 1启动 Brokertaskkill /f /im mosquitto.exe# 清理残留进程mosquitto-v-p1883参数含义-vverbose打印所有连接、订阅、转发事件-p 1883监听端口MQTT 默认 1883启动成功标志mosquitto version 2.1.2 running Opening ipv4 listen socket on port 1883.该终端保持运行它是消息中转站。终端 2订阅者mosquitto_sub-hlocalhost-p1883-tsensor/temp-d参数含义-hhostBroker 地址-ttopic订阅的主题-ddebug打印底层报文详情运行后终端卡住等待消息。终端 3发布者mosquitto_pub-hlocalhost-p1883-tsensor/temp-m25.3-d参数含义-mmessage要发送的消息正文mosquitto_pub默认发完一条就断开。观察 Broker 日志New client connected from ::1:53698 as auto-C132... Received SUBSCRIBE ... sensor/temp Received PUBLISH ... sensor/temp, ... (4 bytes) Sending PUBLISH to auto-C132...日志字段含义auto-C132...客户端未用-i指定 IDBroker 自动生成p4MQTT 协议版本 3.1.1c1clean session true断连不保留会话k60keepalive 60 秒心跳d0, q0, r0, m0dup/QoS/retain/messageID 标志三、实验二通配符匹配目的理解匹配单层和#匹配多层的行为。终端配置终端 1mosquitto-v-p1883终端 2订阅mosquitto_sub-hlocalhost-p1883-tsensor//temp-v终端 3#订阅mosquitto_sub-hlocalhost-p1883-tsensor/#-v通配符匹配规则示例sensor/line1/temp任意一层sensor//temp✅ 匹配#任意多层含零层sensor/#✅ 匹配所有 sensor 下的子主题四、实验三保留消息目的理解 retain 机制——新订阅者立即获得最后一条状态消息。对应方案中status/A设备上线公告。发布保留消息mosquitto_pub-hlocalhost-p1883-tstatus/A-m{status:online}-r-d参数含义-rretainBroker 存储该消息。之后任何订阅者订阅匹配主题时Broker 立即投递这条最后状态新订阅者立即可得mosquitto_sub-hlocalhost-p1883-tstatus/-v即使发布者早已断开订阅者一连接就收到status/A {status:online}。五、实验四TLS 单向认证目的加密传输 客户端验证服务器身份。5.1 生成证书cdE:\mqtt-tls# 1. CA 根证书你自建的发证机构openssl genrsa-outca.key2048openssl req-new-x509-days365-keyca.key-outca.crt-subj/CNMyTestCA# 2. Broker 证书服务器的身份证openssl genrsa-outbroker.key2048openssl req-new-keybroker.key-outbroker.csr-subj/CNlocalhostechosubjectAltNameDNS:localhost,IP:127.0.0.1broker.ext openssl x509-req-inbroker.csr-CAca.crt-CAkeyca.key-CAcreateserial-outbroker.crt-days365-extfilebroker.ext命令含义openssl genrsa生成 RSA 私钥2048 位openssl req -new -x509生成自签名根证书自己给自己发证openssl req -new无-x509生成证书签名请求CSR等 CA 签发-subj /CN...证书的主体名称CN 必须是客户端连接时使用的地址subjectAltName证书扩展字段声明对哪些域名/IP 有效openssl x509 -req用 CA 私钥签发证书-CAcreateserial首次签发时自动创建序列号文件5.2 证书三件套作用文件持有者作用ca.key只有你CA 私钥钢印泄密则整个体系作废ca.crtBroker 所有设备CA 根证书公章样本用来验证证书真伪broker.key只有 Broker服务器私钥TLS 握手时证明身份broker.crtBroker握手时出示服务器身份证由 CA 签发5.3 Broker 配置test.conflistener 8883 cafile ./ca.crt certfile ./broker.crt keyfile ./broker.key tls_version tlsv1.2 allow_anonymous true配置项含义listener 8883监听 MQTT TLS 标准端口cafileCA 根证书验证客户端用双向认证时必需certfile服务器证书keyfile服务器私钥tls_version tlsv1.2强制 TLS 1.2禁用老旧的 SSL/TLSallow_anonymous true允许无用户名密码连接Mosquitto 2.1.x 写listener后默认关闭5.4 启动 连接# 终端 1Brokermosquitto-ctest.conf-v# 终端 2订阅mosquitto_sub-hlocalhost-p8883--cafileca.crt-thello-d# 终端 3发布mosquitto_pub-hlocalhost-p8883--cafileca.crt-thello-mTLS加密成功-d成功标志Client (null) received CONNACK (0) ← 连接成功 OpenSSL: TLSv1.2, cipher TLS_AES_256_GCM_SHA384 ← 加密套件5.5 验证无 CA 证书被拒mosquitto_pub-hlocalhost-p8883-thello-m能进来吗-d错误OpenSSL Error: error:0A000086:SSL routines::certificate verify failedTLS 握手层直接终止——客户端不信任自签服务器。六、实验五mTLS 双向认证目的服务器也验证客户端身份——只有持有合法证书的设备才能连接。6.1 生成客户端证书openssl genrsa-outclient.key2048openssl req-new-keyclient.key-outclient.csr-subj/CNdevice-Aopenssl x509-req-inclient.csr-CAca.crt-CAkeyca.key-CAcreateserial-outclient.crt-days365参数含义-subj /CNdevice-A客户端身份标识device-A是该设备的名称6.2 启用双向认证追加到test.conf并重启 Brokerrequire_certificate true配置项含义require_certificate true强制客户端出示证书无证书者 TLS 握手直接断6.3 验证无证书被拒mosquitto_sub-hlocalhost-p8883--cafileca.crt-thello-d错误OpenSSL Error: tlsv13 alert certificate required对比三种拒绝的区别错误发生在哪层原因积极拒绝TCP 连接层Broker 根本没启动certificate verify failedTLS 握手客户端验服务器客户端没提供 ca.crt不信任服务器certificate requiredTLS 握手服务器验客户端服务器要求客户端证书客户端没给CONNACK (5) not authorisedMQTT 协议层TLS 已过但 MQTT 认证失败6.4 带证书连接客户端三件套齐全时# 订阅mosquitto_sub-hlocalhost-p8883--cafileca.crt--certclient.crt--keyclient.key-thello-d# 发布mosquitto_pub-hlocalhost-p8883--cafileca.crt--certclient.crt--keyclient.key-thello-m双向认证成功-d→ 连接成功消息正常收发。6.5 完整证书体系E:\mqtt-tls\ ├── ca.key ← CA 私钥绝对保密 ├── ca.crt ← CA 根证书分发至所有节点 ├── broker.key ← 服务器私钥 ├── broker.crt ← 服务器证书CA 签发CNlocalhost ├── client.key ← 客户端私钥 ├── client.crt ← 客户端证书CA 签发CNdevice-A ├── test.conf ← Mosquitto TLSmTLS 配置 └── *.csr *.ext ← 中间产物签发完毕可删除七、安全层级演进图第三次实验mTLS 双向认证 ┌─────────────────────────────────────────────┐ │ 客户端出示证书服务器也验证客户端 │ │ 必须同时持有 ca.crt client.crt client.key │ └─────────────────────────────────────────────┘ ↑ 第二次实验TLS 单向加密 ┌─────────────────────────────────────────────┐ │ 服务器出示证书客户端验证服务器 │ │ 线路上 AES-256-GCM 加密窃听者看到乱码 │ │ 需持有 ca.crt 才能连接 │ └─────────────────────────────────────────────┘ ↑ 第一次实验裸 MQTT ┌─────────────────────────────────────────────┐ │ 无加密明文传输 │ │ 25.3 人人可见无需任何凭证 │ └─────────────────────────────────────────────┘八、命令速查表mosquitto 命令命令作用mosquitto -v前台 verbose 模式启动调试必开mosquitto -c test.conf -v指定配置文件启动mosquitto -c test.conf --test-config仅检查配置语法不真正启动mosquitto -d后台 (daemon) 模式net start/stop mosquitto控制 Windows 服务版 Mosquittotaskkill /f /im mosquitto.exe强制终止 mosquitto 进程mosquitto_sub / mosquitto_pub 参数参数含义-hBroker 地址-p端口-t主题-m消息正文仅 pub-ddebug 模式-v打印主题名仅 sub-r保留消息仅 pub-qQoS 等级0/1/2-i指定 Client ID--cafileCA 根证书路径--cert客户端证书路径--key客户端私钥路径--no-clean-session断连后保留会话配合-cnetstat参数含义netstat -ano列出所有网络连接和监听端口| findstr 端口号过滤指定端口通配符通配符匹配任意一层#任意多层只能放在末尾九、明天迁移到云服务器本地实验和云服务器部署的底层机制完全一致仅需修改三处改动点本地云服务器证书 CNlocalhost域名或公网 IP-h连接地址localhost域名或公网 IP防火墙无需配置安全组放行 TCP 8883SSL 证书重新签发步骤云服务器上# 仅改 CN 和 SAN其他不变openssl req-new-keybroker.key-outbroker.csr-subj/CN你的域名或公网IPechosubjectAltNameDNS:你的域名,IP:你的公网IPbroker.ext openssl x509-req-inbroker.csr-CAca.crt-CAkeyca.key-CAcreateserial-outbroker.crt-days365-extfilebroker.ext十、核心概念索引概念一句话定义Broker消息中转程序接收连接、记录订阅、匹配转发TLS传输层安全协议加密 身份验证 完整性保护CA证书颁发机构签发和验证证书证书三件套ca.crt(公章) broker.crt(身份证) broker.key(指纹)mTLS双向 TLS客户端和服务器互相出示证书retain保留消息新订阅者立即收到最后一条PID进程标识符操作系统给每个程序的唯一编号netstat查看网络连接和监听端口的工具CONNACK (0)连接成功CONNACK (5)连接被拒未授权