Skip to content

EMQX 配置与安全

EMQX Broker 的认证、ACL、TLS、共享订阅配置参考。


1. 设备认证配置(PostgreSQL 直连)

方案选择

设备认证采用 EMQX 直连 PostgreSQL,不走 HTTP 回调。

相比 HTTP Auth,直连方案的优势:

  • 少一层 HTTP 往返,认证延迟更低
  • MQTT 链路不依赖后端存活,后端重启不影响设备连接
  • 测试与生产环境共用同一数据库,EMQX 配置完全一致,消除环境差异

流程

设备 MQTT CONNECT → EMQX 直接查 PostgreSQL devices 表 → 校验凭证 → allow/deny

EMQX Dashboard 配置要点

在 EMQX Dashboard → Authentication → PostgreSQL 中配置:

配置项说明
Serverpostgres:5432PostgreSQL 地址
Databaseyunstack_iot数据库名
Usernameemqx数据库用户(建议使用只读账号)
Password(从环境变量获取)数据库密码
Password Hash Algorithmbcrypt密码哈希算法

SQL 查询语句

认证查询(Authentication Query):

sql
SELECT password_hash AS password_hash, 'sha256' AS password_hash_algorithm
FROM devices
WHERE physical_id = ${clientid}
  AND username = ${username}
  AND deleted_at IS NULL
LIMIT 1
  • ${clientid} 对应 MQTT ClientId(设备物理 ID / MAC 地址)
  • ${username} 对应 MQTT Username(产品 ProductKey)
  • ${password} 由 EMQX 根据 password_hash_algorithm 自动与查询结果对比,无需在 SQL 中手动比较
  • 返回行 = 认证通过,无返回 = 认证拒绝

注意:设备需提前在数据库中创建(通过配网流程或管理后台预录入),不支持连接时自动注册。


2. ACL 权限规则(EMQX 内置)

概述

使用 EMQX 内置 ACL(基于文件或内置规则),无需 HTTP 回调,也不需要额外配置 PostgreSQL ACL。

核心规则

EMQX 内置 ACL 通过 Topic 模式匹配实现设备隔离:

设备身份允许操作Topic 模式
设备自身({did})Pubsys/{pid}/{did}/thing/event/+/postsys/{pid}/{did}/thing/service/+/set_replysys/{pid}/{did}/thing/config/set_replysys/{pid}/{did}/thing/ota/progress
设备自身({did})Subsys/{pid}/{did}/thing/service/+/setsys/{pid}/{did}/thing/config/setsys/{pid}/{did}/thing/ota/upgrade
后端服务(admin 客户端)Pub/Subsys/+/+/thing/#(共享订阅前缀由后端客户端自行添加)
其他设备拒绝所有 Topic

EMQX Dashboard 配置

在 EMQX Dashboard → Authorization → Built-in Database 中配置规则,使用 ${username}(ProductKey)和 ${clientid}(Physical ID)变量动态匹配。

详细 Topic 定义见 06.MQTT通信协议


3. 共享订阅组配置

对应 06.MQTT通信协议 3.1 节。

订阅列表

后端服务作为 MQTT 客户端,使用共享订阅前缀 $share/group1/ 订阅以下通配符 Topic:

$share/group1/sys/+/+/thing/event/#
$share/group1/sys/+/+/thing/service/+/set_reply
$share/group1/sys/+/+/thing/config/set_reply
$share/group1/sys/+/+/thing/ota/progress

负载均衡

  • 策略:EMQX 默认 round_robin,多个 NestJS 实例平均分摊设备消息
  • 同一条消息只会投递给组内的一个订阅者,不会重复处理
  • 共享订阅在客户端订阅时通过 topic 前缀声明,EMQX 侧无需额外配置

4. 在线状态机制

在线状态由属性上报驱动,不使用 Webhook:

  • 设备上报属性时,后端在 Redis 中设置在线标记,TTL 120 秒
  • 120 秒内无新上报 → Redis key 自动过期 → 设备判定离线
  • 无需配置 EMQX Webhook,与 EMQX 部署无关,后端独立运作

详细流程见 02.核心业务流程 第 2 节。


5. MQTTS TLS 配置

生产环境必须启用 TLS,设备端使用 MQTTS 端口 8883 连接。

EMQX 侧配置

配置项说明
SSL 监听端口8883
TLS 证书文件PEM 格式公签证书或自签名证书
私钥文件PEM 格式,权限 600
客户端证书暂用单向认证(EMQX 不验证设备证书)

证书获取

环境方案
测试/内网自签名证书或 mkcert
生产Let's Encrypt 或云厂商 SSL 证书

设备端要求

ESP32 固件需配置 CA 证书以验证服务器身份,避免中间人攻击。详见 设备接入指南

Nginx 侧

若前端通过 WebSocket over TLS 连接 EMQX,Nginx 也需要配置对应 SSL 证书,将 WSS 请求代理到 EMQX 8083 端口。


6. Dashboard 管理账号

操作说明
默认端口http://<host>:18083
初始密码首次登录后立即修改默认 admin/public
只读账号建议创建仅 Dashboard 查看权限的账号用于日常监控
数据库只读账号建议为 EMQX 认证创建独立的 PostgreSQL 只读用户,仅能查询 devices 表,遵循最小权限原则

7. 部署参考

emqx.conf 关键配置片段

# --- 认证(PostgreSQL 直连)---
authentication = [
  {
    mechanism = "password_based"
    backend = "postgresql"
    server = "postgres:5432"
    database = "yunstack_iot"
    username = "emqx"
    password = "${EMQX_DB_PASSWORD}"
    password_hash_algorithm {
      name = "sha256"
      salt_position = "suffix"
    }
    query = """
      SELECT password_hash AS password_hash, 'sha256' AS password_hash_algorithm
      FROM devices
      WHERE physical_id = ${clientid}
        AND username = ${username}
        AND deleted_at IS NULL
      LIMIT 1
    """
  }
]

# --- ACL(内置规则)---
authorization {
  sources = [
    {
      type = "built_in_database"
      enable = true
    }
  ]
  no_match = "deny"
}

# --- MQTTS ---
listeners.ssl.default {
  bind = "0.0.0.0:8883"
  ssl_options {
    certfile = "/etc/emqx/certs/server.pem"
    keyfile = "/etc/emqx/certs/server.key"
  }
}

Docker Compose 示例

yaml
emqx:
  image: emqx/emqx:5.x
  ports:
    - "1883:1883"      # MQTT
    - "8883:8883"      # MQTTS
    - "8083:8083"      # WebSocket
    - "18083:18083"    # Dashboard
  environment:
    - EMQX_DASHBOARD__DEFAULT_PASSWORD=your_secure_password
    - EMQX_DB_PASSWORD=your_db_password
  volumes:
    - ./emqx/data:/opt/emqx/data
    - ./emqx/certs:/etc/emqx/certs