当前位置: 首页 > news >正文

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文?

  • 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。
  • 零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。
  • 灰度发布:根据 IP/地理位写入不同后缀,让同一客户端同时连到测试与生产集群。
  • 兼容旧设备:早期固件不支持密码,网关可注入随机密码并回传至 IAM。

2、指令速查

指令作用典型配置
mqtt on;在虚拟主机启用 MQTT 过滤server { mqtt on; … }
mqtt_buffers N S; (1.25.1)单连接缓存 N × S 字节处理 PUBLISH/ACKmqtt_buffers 256 2k;
mqtt_set_connect field value;重写 CONNECT 字段(clientid / username / password)mqtt_set_connect clientid "$geoip_city_$remote_addr";

弃用mqtt_rewrite_buffer_size ≤ 1.25.0;新版本统一用 mqtt_buffers

3、最小示例:按照 IP 段自动打上租户前缀

# 自动映射租户
geo $remote_addr $tenant {default   default_;10.0.0.0/16  corpA_;172.16.0.0/12 corpB_;
}stream {server {listen 18883;proxy_pass   10.0.0.20:1883;   # 后端 EMQXmqtt on;# ① 每连接缓存 256×2 KB,适配高并发发布mqtt_buffers 256 2k;# ② 重写 ClientID / Usernamemqtt_set_connect clientid  "$tenant${mqtt_preread_clientid}";mqtt_set_connect username  "$tenant${mqtt_preread_username}";}
}

效果
接入设备 sensor01 若来自 10.1.2.3,Gateway 转发的实际 ClientID 将变为 corpA_sensor01。后端可据此分配独立 ACL 与 Topic。

4、高级玩法

需求配置要点
灰度:5 % 设备流向新集群map $mqtt_preread_clientid $bucket { … } + 两条 proxy_pass
密码托管:IoT Hub 统一颁发mqtt_set_connect password "$secure_token";
QoS 带宽保护配合 limit_conn_zone / limit_rate 控制单租户并发与速率
TLS 终端ssl_preread on; → Nginx 解 SNI,再走 MQTT 过滤

5、性能调优

场景建议
大量小消息(<= 256 B)mqtt_buffers 512 512; 减少 re-alloc
高并发长连接(≥ 50 K)缩小 buffer,配合系统 net.core.somaxconn
频繁改写大字段保持 mqtt_buffers N S ≥ 字段最大长度,防止 rewrite too long 错误
观测重写结果access_log 增加 $mqtt_preread_clientid $mqtt_preread_username

6、安全注意事项

  1. 字段长度:MQTT 规范 ClientID ≤ 23 字节(3.1.1),> 23 会被后端拒绝;重写前需 if ($clientid ~ "^.{1,23}$") { … }
  2. 密码明文:模块不自动加密;建议启用 TLS + Password Hash。
  3. 回环风险:若网关与 Broker 在同一台 Nginx,需要拆分端口或使用 proxy_bind

7、结语

ngx_stream_mqtt_filter_module 把「MQTT 连接级改写」下沉到 L4,配合 Stream 生态(keyval / limit_conn / js 等)即可实现动态租户隔离、无感鉴权与流量灰度。对于千万级设备同时在线、高频推送的 IoT 平台,它既保证极低延迟,又提供丰富的运营 & 安全钩子 —— 只需几行配置,你的 Nginx 就能变身“智能 MQTT 接入网关”。

http://www.xdnf.cn/news/953011.html

相关文章:

  • 前端与服务器交互以及前端项目组成。
  • 2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】
  • 【Proteus仿真】【32单片机-A011】HX711电子秤系统设计
  • BIO、NIO、AIO的区别
  • EtherCAT主站转Profinet网关接IS620N伺服驱动器与西门子plc通讯案例
  • Qt Http Server模块功能及架构
  • 【Java多线程从青铜到王者】单例设计模式(八)
  • markdown,nodejs前世今生以及内置模块相关知识点
  • AI原生应用实战:用户画像建模的7种机器学习方法
  • 力扣面试150题--蛇梯棋
  • 开发Vue.js组件的二三事
  • if 选择结构
  • 下载https协议的网络图片,并转为Base64
  • 浅谈非理想性因素对星座图的影响
  • ArcGIS Pro制作水平横向图例+多级标注
  • PIN码vs密码,电脑登录的快捷键你用对了吗?
  • CppCon 2015 学习:STL Algorithms in Action
  • Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
  • The Trade Desk推出DealDesk,试图让交易ID不再糟糕
  • HTTP 与 TCP 协议的区别与联系
  • 【C++】unordered_set和unordered_map
  • tauri项目,如何在rust端读取电脑环境变量
  • 画质MxPro:优化手游体验,畅享高清画质
  • Linux初步介绍
  • 【VLNs篇】07:NavRL—在动态环境中学习安全飞行
  • 多轮对话实现
  • react更新页面数据,操作页面,双向数据绑定
  • 免费数学几何作图web平台
  • 在阿里云上搭建n8n
  • React Native 弹窗组件优化实战:解决 Modal 闪烁与动画卡顿问题