说起在 Linux 上搭 EMQX MQTT 服务器我最开始的记忆并不是什么高光时刻而是一次被安全扫描报告打脸的过程。那时候我刚在一台 CentOS 7.9 机器上把 EMQX 部署完设备接入、Dashboard、消息订阅一切正常结果安全同事发来一份扫描报告里面赫然写着“1883 端口 MQTT 协议明文传输存在凭据与数据被嗅探风险”。我才意识到自己之前为了图省事跳过了 SSL/TLS 配置设备每次连接的账密其实都是裸奔在网络上。这篇记录就是从那一次打脸开始的完整走一遍 Linux 环境下安装 EMQX、生成证书、配置 SSL/TLS 加密连接、处理扫描告警的实战流程。无论你是物联网开发者、后端工程师还是刚接触消息代理的运维只要你打算让设备“安全地”接入 MQTT 服务这篇内容应该能帮你少踩不少坑。1. 为什么 MQTT 要上 TLS明文风险的现实教训1.1 MQTT 的“轻量”设计其实是在裸奔MQTT 协议在设计之初就把“轻量、低带宽、低开销”放在第一位所以协议层面的安全机制非常有限。它默认跑在 1883 端口客户端的用户名和密码是在 CONNECT 报文里以明文形式发送的之后的 topic 和 payload 也全部是明文。这个设计对单片机、低功耗传感器是友好的但放到公网或者不受控的内网环境里就相当于把门钥匙放在门口的脚垫下面。我举一个真实例子。后来我在另一个项目里帮同事排查设备 GPS 数据偶发丢失的问题当时的临时方案是在接入交换机的镜像口抓包。tcpdump 一开几秒钟内就能从包里直接读出某台设备的用户名、密码以及它上报的经纬度坐标。那一刻我特别庆幸这是一个测试环境如果这是在公网生产环境后果不难想象。可能你会想既然数据是发到自己服务器上的中间不经过乱七八糟的节点是不是就不用加密了但实际上物联网设备的接入链路往往很长设备 - 无线路由 - 运营商网络 - 云服务器链路中的任何一跳被监听报文就可能被还原。内网环境也不是绝对安全办公网络里抓到接入交换机的镜像流量比你在公网上被定向攻击还要容易。1.2 公网与内网TLS 不是可选项如果你只在本地虚拟机里跑 EMQX用 localhost 连接那不加 TLS 确实没什么问题。但只要你把服务暴露到局域网给多台设备用或者部署到云服务器上让设备通过公网 IP 接入TLSTransport Layer Security传输层安全协议就应该是默认要求。TLS 做的事情简单说就是在 MQTT 之上包了一层“加密隧道”。握手阶段客户端与服务端协商密钥之后的 MQTT 数据全部通过这层隧道传输即使被中间设备抓到包看到的也是一堆密文。代价是握手上会多几个网络往返以及设备端多一点点 CPU 开销。现在的硬件普遍不差这笔开销换来的安全性是非常值得的。选择哪种版本的 TLS 也很关键。TLS 1.0 和 1.1 已经被协议规范废弃而且存在 POODLE、BEAST 这类知名攻击手段当前至少应该启用 TLS 1.2有条件就直接上 TLS 1.3。EMQX 新版默认已经支持 TLS 1.2 / 1.3但前提是你在配置里明确启用安全版本这个后面会讲。2. 选型与安装EMQX 5.x 在 Linux 上的落地2.1 环境准备先把系统底子打牢不同 Linux 发行版的依赖细节不太一样但核心就三件事能联网、有 wget/curl、OpenSSL 版本别太老。这里我不建议再用好几年没更新的旧版系统跑新版本 EMQX如果手头只有 CentOS 7.x至少确认 OpenSSL 版本在 1.1.1 以上因为它关系到 TLS 1.3 的支持。安装前可以先快速看一眼系统信息# 查看发行版 cat /etc/os-release # 查看 OpenSSL 版本 openssl version如果是 Debian/Ubuntu 系的系统执行下面的命令补全基础工具sudo apt update sudo apt install -y ca-certificates wget curl opensslCentOS/RHEL 系则换成sudo yum install -y ca-certificates wget curl openssl这里单独把 ca-certificates 拎出来说是因为后面的证书链验证会依赖系统 CA 证书库。有时候遇到“证书不受信任”的问题不一定是证书本身有问题而是系统的根证书库太旧或者压根没装这个包。2.2 EMQX 版本怎么选4.x 还是 5.x这是我刚接触 EMQX 时比较困惑的一个点。网上大量教程还在写 4.x 的配置语法而官方新文档已经全面转向 5.x。两者的差异不只是在界面上配置文件格式也换了。4.x 用的是listener.ssl.external这种扁平配置风格5.x 改成了 HOCON 格式用嵌套块来描述 listener。从实际选型角度来看新项目建议直接上 5.x原因有三个官方对 4.x 的维护力度在下降新特性都集中在 5.x。5.x 的 Dashboard 更强集群管理、监控指标都内置了。5.x 的配置文件分模块化组织比 4.x 的单一大文件清晰很多。下表是我整理的对比方便你做决定维度EMQX 4.xEMQX 5.x配置文件格式Key-Value 风格HOCON 嵌套块Dashboard 风格老式管理后台新版可观测界面集群管理需要较多手工配置内置节点管理与监控插件体系独立插件包更模块化不少内置功能面板化适合场景老项目维护、对 4.x 配置熟悉新项目、需要长期维护如果你只是想在笔记本或一台测试机上快速验证功能选 5.x 的最新稳定版就行。安装方式建议用官方 APT/YUM 源这样升级方便不用每次手动下载解压包。Debian/Ubuntu 的安装非常简单curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash sudo apt install -y emqxRHEL/CentOS 则是curl -s https://assets.emqx.com/scripts/install-emqx-rpm.sh | sudo bash sudo yum install -y emqx想尝鲜或者内网离线的环境也可以去官方 GitHub Releases 下载对应发行版的 zip 包解压后手动启动。不过那种方式没有 systemd 服务文件进程守护要自己搞定我一般只在容器里这么干。2.3 第一次启动要养成的好习惯安装完成后先把服务启动并设为开机自启sudo systemctl start emqx sudo systemctl enable emqx sudo systemctl status emqx默认情况下 EMQX 会监听这些端口1883MQTT 明文、8083WebSocket 明文、8084WebSocket TLS、18083Dashboard 管理界面。启动后访问http://服务器IP:18083就能打开管理后台默认账号是admin默认密码是public。这里有一个我见过很多人忽略的点第一次登录后一定要立刻改掉默认密码并且把 Dashboard 的监听地址限制到可信网段。Dashboard 本身没有内建限流和复杂防护暴露在公网上很容易被暴力破解尝试。早期我见过有人默认密码挂着跑了好几个月扫描器上去直接就能看到所有 MQTT 客户端会话。如果你打算生产环境只走 TLS明文 1883 端口最好直接关掉或者绑定到内网地址避免设备不小心走错端口造成数据裸奔。这个我们后面配置 SSL 时一并处理。3. 证书从哪里来自签名、Lets Encrypt 与文件组织3.1 不同证书来源的适用边界想要启用 SSL/TLS首先得有一张服务器证书。证书来源基本分三类自签名、免费 CALets Encrypt、商业 CA。下面是它们的对比证书类型成本客户端信任难度有效期适用场景自签名免费高每台客户端都要手动导入可自定义内网测试、开发环境Lets Encrypt免费低系统证书库自动信任90 天公网生产环境商业 CA付费低系统自动信任1-2 年客户有合规要求、涉密项目如果你在内网测试没有公网域名也别纠结自签名证书足够。但必须在所有客户端设备上把这张证书加入信任列表否则客户端在 TLS 握手阶段会因为“证书不受信任”直接断开连接。公网生产环境我更推荐 Lets Encrypt免费且自动续期主流客户端基本零配置就能信任。商业 CA 适合那些需要提供合规证书链的项目但物联网设备场景相对少见。3.2 用 OpenSSL 生成一张带 SAN 的自签名证书自签名证书的生成网上教程一抓一大把但大多数生成的是一张不带 SANSubject Alternative Name的“裸证书”。现代 TLS 客户端在校验证书时不再只看证书里的 Common Name而是看 SAN 字段里的域名或 IP 是否与连接地址匹配。如果不带 SAN你连 MQTTX 这种桌面客户端都会报 hostname 不匹配一些 Android 客户端更是直接拒绝连接。所以生成证书时一定记得加上-addext指定 SANsudo mkdir -p /etc/emqx/certs cd /etc/emqx/certs sudo openssl req -x509 \ -newkey rsa:2048 \ -keyout server.key \ -out server.crt \ -days 365 \ -nodes \ -subj /CN192.168.1.100 \ -addext subjectAltNameIP:192.168.1.100,DNS:mqtt.example.com把192.168.1.100和mqtt.example.com替换成你自己的服务器 IP 和域名。SAN 可以同时写多个 IP 和 DNS用逗号分隔。如果你只是内网测试IP:你的服务器IP就够用了。生成完成后目录下会有两个文件server.crt证书和server.key私钥。私钥一定要保密它一旦泄露等于你的 TLS 加密被中间人脱了裤子。3.3 证书文件的权限管理EMQX 服务默认以emqx用户运行所以证书文件不仅要让进程能读到还不能让其他无关用户随便读。推荐把证书目录 owner 改成emqx私钥权限设置成 600sudo chown -R emqx:emqx /etc/emqx/certs sudo chmod 644 /etc/emqx/certs/server.crt sudo chmod 600 /etc/emqx/certs/server.key这里有一个经验教训我在给 4.x 版本配置证书时把私钥权限设成了 644EMQX 启动时报了一个奇怪的badarg错误日志也没有直接提示“权限过宽”排查了半个小时才发现是私钥文件权限问题。虽然自签名测试环境下 644 也能跑但生产环境出于安全考虑私钥一定只允许emqx用户读写。3.4 用 acme.sh 申请 Lets Encrypt 证书公网环境更省心的做法是用 acme.sh 申请 Lets Encrypt 证书。它支持 DNS API、HTTP 验证、Nginx 模式等多种签发方式而且内置自动续期。这里给一个最简单的 HTTP 验证示例前提是服务器 80 端口可访问curl https://get.acme.sh | sh -s email你的邮箱 ~/.acme.sh/acme.sh --issue \ -d mqtt.example.com \ --standalone签发成功后证书相关文件位于~/.acme.sh/mqtt.example.com/目录下。通常我们把它安装到固定目录方便 EMQX 引用~/.acme.sh/acme.sh --install-cert \ -d mqtt.example.com \ --key-file /etc/emqx/certs/server.key \ --fullchain-file /etc/emqx/certs/server.crt \ --reloadcmd systemctl restart emqx--install-cert会把证书和私钥复制到指定路径并配置续期成功后自动重启 EMQX。这里要提醒一句Lets Encrypt 证书有效期只有 90 天千万不要忽略自动续期配置否则某天凌晨所有设备会同时掉线而且客户端日志里只会显示“证书过期”。4. EMQX 的 SSL/TLS 配置从 1883 到 88834.1 端口规划为什么是 8883先理清 MQTT 相关端口的作用因为很多人会把它们混在一起端口协议用途1883MQTT/TCP明文 MQTT 连接8883MQTT/TLS加密 MQTT 连接8083WebSocket明文 WebSocket MQTT8084WebSocket/TLS加密 WebSocket MQTTWSS8883 是 IANA 注册的标准 MQTT over SSL 端口就像 HTTPS 默认用 443 一样。所以客户端程序里默认会去寻找这个端口习惯上我们也都沿用 8883不另辟蹊径。如果你不需要公网明文连接可以把 1883 绑定到内网或者直接在配置里停掉避免设备误连明文端口。4.2 5.x 的 HOCON 配置改法EMQX 5.x 的主配置路径是/etc/emqx/emqx.conf。推荐的做法是在/etc/emqx/conf.d/目录下新建一个 overlay 文件比如ssl.conf这样后续管理和回滚都方便。配置内容如下listeners.ssl.default { bind 0.0.0.0:8883 ssl_options { cacertfile /etc/emqx/certs/cacert.pem certfile /etc/emqx/certs/server.crt keyfile /etc/emqx/certs/server.key verify verify_none versions [tlsv1.2, tlsv1.3] } }逐个字段解释一下bind监听地址和端口。0.0.0.0表示所有网卡都监听如果只想让内网访问改成内网 IP 即可。cacertfileCA 证书路径。自签名场景把server.crt复制一份为cacert.pem即可使用 Lets Encrypt 时一般可以省略但写上也没问题。certfile和keyfile服务器证书和私钥。verify客户端证书校验策略。verify_none表示只做单向 TLS 加密不校验客户端证书verify_peer表示要求客户端必须携带受信任的证书也就是双向 TLSmTLS适合设备级身份认证。versions允许的 TLS 协议版本。这里显式声明只启用 1.2 和 1.3把老版本挡在外面。如果你是第一次做加密连接我建议先用verify_none把链路跑通确认加密正常后再考虑升级到verify_peer双向认证。一上来就搞 mTLS证书排错会比较痛苦。4.3 4.x 的老配置风格网上搜到的大量教程仍然是 4.x 语法如果你用的是 4.x对应配置大概长这样listener.ssl.external 8883 listener.ssl.external.keyfile /etc/emqx/certs/server.key listener.ssl.external.certfile /etc/emqx/certs/server.crt listener.ssl.external.cacertfile /etc/emqx/certs/cacert.pem listener.ssl.external.verify verify_none listener.ssl.external.tls_versions tlsv1.2,tlsv1.3注意 4.x 里的变量名是tls_versions而不是versions。如果你是从 4.x 老教程迁移到 5.x最容易踩的坑就是把tls_versions直接抄到 5.x 配置文件里导致启动失败。4.4 重启、防火墙与常见启动报错配置保存后重启 EMQXsudo systemctl restart emqx如果配置有语法错误或者证书路径不对服务会起不来。此时一定要看日志sudo tail -n 100 /var/log/emqx/emqx.log我遇到过的启动报错主要有三类{bad_return, ...}/keyfile ... noperm私钥文件权限过宽或 owner 不对回到 3.3 小节检查权限。{error, ...} ... no such file ...证书路径写错或者文件不存在。{options, ...} ... invalid versionsTLS 版本字段写错确认是versions而不是老版的tls_versions。服务启动成功后还要保证防火墙放行 8883 端口。CentOS 7/8 使用 firewalldsudo firewall-cmd --permanent --add-port8883/tcp sudo firewall-cmd --reloadUbuntu 如果用了 ufwsudo ufw allow 8883/tcp sudo ufw reload这里提醒一下某些云服务商的安全组规则也要一并放行比如阿里云、腾讯云只改服务器防火墙是不够的控制台安全组入口同样需要加一条规则。5. 那个令人头疼的 CVE-2016-2183 扫描告警5.1 告警的真相SWEET32 与 3DES很多人在配置完 TLS 后拿着扫描器去扫服务器结果报告里出现一条“SSL/TLS 协议信息泄露漏洞 (CVE-2016-2183)【原理扫描】”心里会慌是不是我的 EMQX 配置有问题其实这条告警和 EMQX 本身关系不大它针对的是 TLS 密码套件。CVE-2016-2183 对应的就是 SWEET32 攻击。简单说如果服务器在 TLS 握手过程中仍然允许使用 3DES三重数据加密算法这类基于 64 位分组的旧块密码攻击者可以通过生日攻击原理在长时间会话中逐步恢复部分明文数据。现代 TLS 推荐的是 AES-GCM、ChaCha20-Poly1305 这类 AEAD关联数据加密套件。3DES 属于上古时代的遗产很多默认配置为了兼容老设备还把它保留在支持的列表里扫描器一检测到就报了“原理扫描”。这里“原理扫描”四个字很关键意思是扫描器并没有真的发起一次完整的攻击验证而是基于 TLS 握手时服务端返回的支持套件列表做的判断。换句话说你并不一定已经被攻击但确实存在风险敞口。5.2 如何查看当前支持的密码套件先用openssl ciphers看看系统支持哪些套件openssl ciphers -v ALL:SECLEVEL0 | grep 3DES再通过s_client查看 EMQX 实际协商时使用的套件。TLS 握手上会有一个 ClientHello 和 ServerHello服务端最终选择哪个套件受客户端支持列表影响但你也能用它快速验证服务端能力echo | openssl s_client -connect 127.0.0.1:8883 -tls1_2 2/dev/null | grep Cipher is还能用 nmap 的脚本枚举服务端支持的套件列表nmap --script ssl-enum-ciphers -p 8883 127.0.0.1如果输出里出现3DES-CBC3-SHA或DES-CBC3-SHA之类的名称那扫描器报 CVE-2016-2183 就一点也不冤枉。5.3 在 EMQX 里禁用弱套件与旧 TLS 版本要消除告警核心思路不是“打补丁”而是告诉服务端请把这些旧套件从我支持的列表里删掉。在 EMQX 5.x 的ssl_options中增加ciphers字段和honor_cipher_orderlisteners.ssl.default { bind 0.0.0.0:8883 ssl_options { cacertfile /etc/emqx/certs/cacert.pem certfile /etc/emqx/certs/server.crt keyfile /etc/emqx/certs/server.key verify verify_none versions [tlsv1.2, tlsv1.3] honor_cipher_order true ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305 } }这个ciphers列表是我在多个项目里验证过的优先级从高到低清一色是 AEAD 套件完全没有 3DES、RC4、CBC 模式的旧套件。honor_cipher_order true的作用是告诉 EMQX“以服务端的优先顺序为准”避免客户端用一个弱套件来拉低协商等级。同时再把versions限定在[tlsv1.2, tlsv1.3]。这相当于把 TLS 1.0/1.1 全部禁掉因为老版本本身就有 BOODLE、BEAST 等一堆历史问题没必要为了兼容度极低的旧设备保留。重启 EMQX 后再看一眼协商结果的套件情况。5.4 重新扫描后的验证结果重启之后用 nmap 再扫一遍nmap --script ssl-enum-ciphers -p 8883 127.0.0.1这时候输出列表中应该看不到任何3DES或RC4字样的套件只有 AES-GCM 和 ChaCha20 系列。再配合openssl s_client验证一次echo | openssl s_client -connect 127.0.0.1:8883 -tls1_2 2/dev/null | grep Cipher is正常情况下你会看到Cipher is ECDHE-RSA-AES128-GCM-SHA256或类似 AEAD 套件名称。此时扫描器再上报 CVE-2016-2183 告警的概率就几乎为零了。这里要特别提醒一句禁用弱套件之前先确认你的客户端是老设备还是新设备。我遇到过工业场景里一些用了几年的 DTU 网关固件写死了只支持 TLS 1.0 3DES你这边一禁用那批设备直接全部连不上。所以生产环境要留出过渡期先在测试环境确认所有客户端都能兼容新的套件策略再推到生产。6. 客户端连接实测与安全细节复盘6.1 MQTTX 图形工具的连接配置配置完成并重启后拿 MQTTX跨平台 MQTT 客户端工具做一次真实连接测试是最直观的。在 MQTTX 里新建连接时重点看这几个字段Host 填mqtts://192.168.1.100或者直接填 IP。Port 填8883。选择 SSL/TLS。证书验证方式自签名证书场景下选择“CA 证书”然后把服务器端server.crt导入为受信任的 CA。如果你用的是 Lets Encrypt一般不用手动导入系统证书库已经信任它。如果一切正常客户端会显示连接成功并且顶部能看到 TLS 相关的握手信息。如果提示unable to verify the first certificate那大概率是 CA 证书没有导入或者导入的是错误文件。6.2 mosquitto 命令行发布/订阅测试很多自动化场景不会用图形工具而是直接用命令行客户端。推荐安装mosquitto-clients# Debian/Ubuntu sudo apt install -y mosquitto-clients # CentOS/RHEL sudo yum install -y mosquitto订阅端mosquitto_sub \ -h 192.168.1.100 \ -p 8883 \ --cafile /etc/emqx/certs/server.crt \ -t test/topic \ -u admin \ -P public \ -v发布端mosquitto_pub \ -h 192.168.1.100 \ -p 8883 \ --cafile /etc/emqx/certs/server.crt \ -t test/topic \ -m hello emqx tls \ -u admin \ -P public--cafile指定用于验证服务器的 CA 证书文件。如果少了这一步mosquitto 客户端会因为没有找到受信任的 CA 而直接拒绝连接。使用 Lets Encrypt 证书时可以省略但显式指出来也没问题。6.3 openssl s_client 与 tcpdump 双重验证有时候客户端工具会做一些额外的证书逻辑导致问题定位困难。我习惯先用openssl s_client直接把 TLS 握手过程拉出来看echo | openssl s_client \ -connect 192.168.1.100:8883 \ -servername mqtt.example.com 2/dev/null | \ grep -E Protocol|Cipher|Verify如果输出中有Protocol : TLSv1.3 Cipher : TLS_AES_256_GCM_SHA384 Verify return code: 0 (ok)说明 TLS 层完整跑通。如果Verify return code不是 0把返回的错误码记下来去查原因常见的是20 unable to get local issuer certificate意味着 CA 链没有配全。再进一步可以用 tcpdump 抓包确认 MQTT 数据已经是密文sudo tcpdump -i any port 8883 -A对比 1883 明文端口抓到的 MQTT 报文你会在 8883 端口看到一堆二进制乱码这才是正常状态。我以前给客户演示时经常做这个对比视觉冲击力很强说服力也强。6.4 连接失败排查清单排查 TLS 连接问题是整个流程里最耗时的环节。我把常见现象和对应原因整理成一个表照着查能省不少时间现象可能原因解决方向客户端提示证书不受信任客户端没有导入 CA 证书或导入的不是完整证书链导入server.crt或 Lets Encrypt 完整链握手提示 hostname 不匹配证书 SAN 中没有当前连接使用的 IP/域名重新生成带正确 SAN 的证书连接超时服务器防火墙或云安全组未放行 8883检查 firewalld/ufw/安全组EMQX 启动报错证书文件路径错、权限过宽、配置语法错看/var/log/emqx/emqx.log老设备连不上设备端只支持 TLS 1.0/1.1 或弱套件确认设备固件兼容性或临时保留兼容套件客户端时间是过去/未来证书有效期校验失败同步设备系统时间NTP 校准其中时间问题值得多说一句。TLS 证书都有有效期客户端在握手阶段会比对本地时间与证书的有效期。很多嵌入式设备出厂后时间没有同步直接停留在 1970 年于是证书永远显示“未生效”连接自然失败。以前排查过一起“昨天还能连今天突然全部掉线”的事故最后发现是设备端 NTP 服务器不可达时间漂移了 10 分钟。6.5 证书轮换别让自动化续期变成空中楼阁使用自签名证书的话到期后要重新生成并且所有客户端的信任列表要跟着更新这是个大工程所以生产环境我不建议用自签名证书。如果你用 Lets Encryptacme.sh 的--install-cert --reloadcmd已经能完成自动续期和重启。但这里我建议再加一个“到期前检查”的兜底脚本写到 cron 里#!/bin/bash CERT_FILE/etc/emqx/certs/server.crt EXPIRE_DAYS$(echo | openssl s_client -connect 127.0.0.1:8883 -servername mqtt.example.com 2/dev/null | \ openssl x509 -noout -enddate 2/dev/null | cut -d -f2) # 简单判断如果证书还有不到 14 天到期就手动续期并重启 if openssl x509 -checkend $((14 * 24 * 3600)) -noout -in $CERT_FILE; then echo 证书有效期充足 else ~/.acme.sh/acme.sh --renew -d mqtt.example.com --force ~/.acme.sh/acme.sh --install-cert -d mqtt.example.com \ --key-file /etc/emqx/certs/server.key \ --fullchain-file /etc/emqx/certs/server.crt \ --reloadcmd systemctl restart emqx fi把脚本放到/usr/local/bin/check-emqx-cert.sh加执行权限再写入 crontab 每天凌晨跑一次chmod x /usr/local/bin/check-emqx-cert.sh echo 0 3 * * * /usr/local/bin/check-emqx-cert.sh | sudo crontab -以前我犯过的错误是只配置了自动续期却忘了--reloadcmd里实际调用的命令是否存在。结果证书明明续了EMQX 却没重启继续加载旧证书直到某个早晨客户端全部掉线才反应过来。所以脚本里一定要带上重启 EMQX 的动作并且定期人工检查一次续期日志。我个人在实际运维里的习惯是生产环境的 EMQX 默认只开放 8883 端口明文 1883 端口要么关闭要么绑定到内网管理网段每次扫描器报出 TLS 相关告警先去看密码套件列表而不是急着升级 EMQX 版本证书轮换脚本写完一定要模拟执行一遍确认reloadcmd真正生效再让它进 crontab。TLS 这东西配置一次并不复杂难的是之后每一次证书轮换、每一个新设备接入时都保证链路不裸奔。毕竟在物联网场景里设备掉线还能重连数据泄露可没法重来。