nginx 代理 mqtt 需启用 stream 模块实现四层 tcp 透传,支持 mqtt 3.1.1/5.0;配置在 http 外独立 stream 块,可做明文代理、tls 终止及基于 clientid 的动态路由与访问控制。

Nginx 代理 MQTT 的核心是启用 stream 模块,做四层 TCP 透传,不解析报文、不干预协议语义,因此轻量、兼容所有 MQTT 版本(3.1.1 / 5.0),适合海量设备长连接场景。
确认并启用 stream 模块
该模块自 Nginx 1.9.0 起默认编译进源码,但需验证是否启用:
- 运行
nginx -V 2>&1 | grep --with-stream,有输出即支持 - 若无,Ubuntu/Debian 安装
libnginx-mod-stream;CentOS/RHEL 安装nginx-mod-stream -
注意:stream 配置必须独立写在
http块之外,否则启动失败
配置基础 TCP 代理(端口 1883)
这是最常用的明文接入方式,适用于内网或 TLS 已由设备端自行处理的场景:
- 在
/etc/nginx/nginx.conf顶部添加stream { ... }块 - 用
upstream定义后端 Broker 地址,支持weight、max_fails、fail_timeout等负载策略 - 关键参数:
proxy_responses 1(MQTT 是单次 CONNECT 后长期通信,禁用响应计数) -
proxy_timeout 1h(匹配 Keep Alive 心跳周期,防止空闲断连) - 推荐加
hash $remote_addr consistent;,保障同一设备重连时落在同一台 Broker,利于会话保持
启用 TLS 终止(端口 8883)
让 Nginx 承担 TLS 握手与加解密,Broker 可继续跑明文 1883,降低其 CPU 压力:
- 监听
8883 ssl,指定ssl_certificate和ssl_certificate_key - 强制 TLS 1.2+:
ssl_protocols TLSv1.2 TLSv1.3 - 精简加密套件,例如:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256 - 证书建议使用 Let's Encrypt;若自签,需确保设备信任对应 CA
- 注意:TLS 终止后仍是纯 TCP 流转发,Broker 不需要开启 TLS
增强可观测性与访问控制(可选)
借助 ngx_stream_mqtt_preread_module,可在连接建立初期提取 ClientID 和 Username:
- 启用
mqtt_preread on;,即可使用变量$mqtt_preread_clientid和$mqtt_preread_username - 结合
keyval模块实现按 ClientID 动态路由到不同 upstream - 配合
limit_conn或 IP 白名单,实现设备级限流或黑白名单管控 - 无需修改客户端,零侵入式提升接入层治理能力











