NanoMQ 0.17 发布,QUIC 双向认证、DDS 代理功能升级


春分时节,万物复苏,NanoMQ 项目又如期为大家献上了最新的 0.17 版本。这一版本主要对 2 个重要功能进行了升级:MQTT over QUIC 的双向认证和 DDS 协议转换代理的序列化代码自动生成。另外还新增了 QUIC 传输层的配置参数,增加了 Retain 消息的持久化,以及发布了 NanoSDK 0.9 版本等诸多更新。

QUIC 双向认证 & 新增配置参数

自从 1994 年提出了 SSL 协议的原始规范以来,TLS 协议也经过了多次版本的更新。最新推出的 TLS 1.3 有望成为有史以来最安全但也最复杂的 TLS 协议。相较于 TLS 1/1.1/1.2,1.3 版本具备更快的连接协商速度,新的密钥协商机制 PSK 和更安全的加密哈希算法。

QUIC 在功能层面等价于 TCP+TLS, 并且已采用最新的 TLS 1.3 代替其原有加密协议(QUIC Crypto)。QUIC 协议默认基于 TLS 1.3 完成数据加密连接,且依赖其实现了0-RTT(1-RTT)快速重连握手功能。

MQTT 3.1.1/5.0 over QUIC

当使用 TLS 进行数据加密传输时,如需要验证客户端合法性,经常会使用到双向认证。在之前的 NanoMQ 版本中, MQTT over QUIC 桥接默认只使用单向认证。从 0.17 版本开始用户能够通过配置开启 QUIC(TLS 1.3)的双向认证。

如何使用 QUIC 的双向认证

首先确认自己使用的 NanoMQ 版本已开启了 QUIC 选项,目前使用双向认证只需在配置中设置对应的客户端证书和私钥等文件路径,注意这部分配置无论是使用传统的 TCP 模式还是 QUIC 模式都一样有效:

旧配置文件格式:

bridge.mqtt.emqx.tls.enable=false
bridge.mqtt.emqx.tls.key_password=yourpass
bridge.mqtt.emqx.tls.keyfile=/etc/certs/key.pem
bridge.mqtt.emqx.tls.certfile=/etc/certs/cert.pem
bridge.mqtt.emqx.tls.cacertfile=/etc/certs/cacert.pem

HOCON 格式:

## 在 bridge 段落中的 connector 部分

bridges.mqtt {
  nodes = [
      {
          name = emqx
          enable = true
          connector {
              ......
              conn_properties = {
                  ......
              }
              # # Ssl config ##
              # # Ssl config is also valid when working in MQTT over QUIC mode ##
              ssl {
                  enable = false
                  key_password = "yourpass"
                  keyfile = "/etc/certs/key.pem"
                  certfile = "/etc/certs/cert.pem"
                  cacertfile = "/etc/certs/cacert.pem"
              }
          }

NanoMQ 的 MQTT over TCP 部分采用的是 MbedTLS 库进行加解密,与标准的 TCP 连接不同,QUIC 部分采用的是 MsQUIC 子模块项目内置的 OpenSSL API。OpenSSL 和 MbedTLS 两个目前最流行的 SSL 库在 NanoMQ 项目中可以同时兼容运行。

目前 NanoMQ 的 MQTT over QUIC 桥接功能暂时不支持 Windows 环境下运行。由于平台兼容性问题,在 Windows 环境中需要替换使用 schannel 来进行 TLS/SSL 加解密。计划在后续的版本中完成 Winodws 环境适配。

新增 QUIC 传输层配置参数

根据用户反馈,为了保持连接不断来克服一些极端弱网情况,新版本暴露了 2 个 QUIC 传输层参数供用户自行配置调优。

  • quic_initial_rtt 初始的 RTT(Round Trip Time) 预测值。QUIC 采用单向递增的 Packet Number 来标识数据包,即时是重传包也有独特的编号,不会引起重传的歧义性,这样采样 RTT 的测量更准确。QUIC 通过 ACK 记录的接收的数据报文和 ACK 报文之间的延迟来估算RTT,RTT 用于丢失检测和触发重传。这一值就是初始估计网络中的 RTT 情况,用户可以根据实际网络环境设置合理的 RTT 来保证连接不断。

  • quic_send_idleTimeout重置 QUIC 传输层拥塞控制检测的最大空闲时间。拥塞控制会修改内部发送的滑动窗口大小,此值影响 QUIC 传输层对于网络变动的敏感度和自动流控。

配置选项如下:

bridge.mqtt.emqx.quic_initial_rtt=60
bridge.mqtt.emqx.quic_send_idleTimeout=60

IDL 序列化代码生成工具

此前我们提到需要用户自己根据 IDL 格式来开发转 JSON 的序列化/反序列化代码,未来将提供一个自动化的代码生成工具。为了方便 MQTT 用户能够简单快速上手 DDS Proxy 功能,3 月这一工具正式发布:NanoMQ 推出了 IDL 代码生成器功能:idl-serial-code-gen。此工具能够根据用户的 DDS IDL 文件来自动生成 JSON 序列化和反序列化代码。

由于 DDS 协议为不可读不可直接分析的二进制流,为了提高系统的可互操作性,需要将 DDS 系统的数据在 NanoMQ 中进行必要的转换以供其他中间件如 eKuiper 分析使用。idl-serial-code-gen 工具可以自动生成代码来完成 IDL 结构体和 JSON 格式文本之间的互相转换。

目前 idl-serial-code-gen 工具支持以下 IDL 特性。

  • Primitive types

  • Structs

  • String and string with template

  • Sequence template

  • Enums

  • Part of Annotations

在上一版本的 NanoMQ DDS Proxy 中,默认所有主题都使用同一个 IDL 结构体定义,这限制了单实例能够转接的数据类型。新版本新增了 DDS 主题和 MQTT 主题的对应配置选项,供用户配置转发的 Topic 对应关系。

forward_rules = {
      ## DDS to MQTT
    dds_to_mqtt = {
        from_dds = "MQTTCMD/topic1"
        to_mqtt = "DDS/topic1"
        struct_name = "remote_control_result_t"
  }
    ## MQTT to DDS
    mqtt_to_dds = {
        from_mqtt = "DDSCMD/topic1"
        to_dds = "MQTT/topic1"
        struct_name = "remote_control_req_t"
  }
}

同理 nanomq_cli 工具命令行启动时也需要指定结构体名称:启动DDS客户端订阅DDS主题 MQTT/topic1 并指定接收的结构体名称 remote_control_req_t。

$ ./nanomq_cli ddsproxy sub -t "MQTT/topic1" --struct "remote_control_req_t"

目前默认 DDS 和 MQTT 主题之间一一对应,不允许一个 MQTT 主题上转接多个 DDS 主题。

编译 IDL 代码生成器 idl-serial-code-gen

编译 IDL 代码生成器 idl-serial

$ git clone https://github.com/nanomq/idl-serial.git
$ cd idl-serial
$ mkdir build && cd build
$ cmake -G Ninja ..
$ ninja 
$ sudo ninja install

编译完成生成可执行文件 idl-serial-code-gen

生成 Json<->Struct 转换代码

使用 idl 文件 dds_structs.idl 生成 C 代码 idl_convert.cidl_convert.h

## 生成C代码 idl_convert.c 和 idl_convert.h
$ ./idl-serial-code-gendds_structs.idlidl_convert

编译NanoMQ与DDS Proxy

  1. 将以上步骤中生成的代码文件 idl_convert.cidl_convert.h 拷贝到 nanomq_cli/dds2mqtt 路径下

  2. 通过 cmake 参数 IDL_FILE_PATH 指定 idl 文件路径 (不指定则默认为工程路径下的 etc/idl/dds_type.idl)

$ git clone https://github.com/emqx/nanomq.git
$ cd nanomq
## 拷贝以上生成的文件到 nanomq_cli/dds2mqtt/路径下
$ cp {YOUR_PATH}/idl_convert.* nanomq_cli/dds2mqtt
$ mkdir build && cd build
$ cmake -G Ninja -DIDL_FILE_PATH={IDL_PATH} -DCMAKE_PREFIX_PATH={DDS_LIBRARY_PATH} -DBUILD_DDS_PROXY=ON ..
$ ninja 
$ sudo ninja install

目前虽然有了自动化代码生成工具,但 DDS Porxy 功能编译安装过程较为繁琐,对于不熟悉工程结构和 DDS 操作的用户来说比较困难。下一版本将通过 Cmake 来集成这一工具并自动化编译过程,无需再手动生成源码文件和拷贝文件到工程下。

NanoSDK 0.9 版本发布

与 NanoMQ 0.17 一同发布的还有 NanoSDK 0.9 版本。这一版本将 NanoMQ 中创新的 MQTT over QUIC 多流连接功能和在桥接中使用的新的回调函数同步至 NanoSDK。NanoSDK 0.10 版本也在筹备开发中,将提供 MQTT5 over QUIC 协议支持和继续增加类 Paho 的使用方法。

其他修复和更新

NanoMQ 0.17 版本还有一些小功能更新:

  1. 支持 Retain 消息持久化至 SQLite3: 根据用户需求,为 NanoMQ 新增了,当开启 SQLite 的消息缓存和持久化功能时默认存储所有的 Retain 消息至 SQLite。

  2. MQTT5 桥接增加更多配置参数: 为 MQTT5 桥接新增了遗愿消息相关的配置参数。

此外还有一些问题修复和优化:

  1. 修复桥接连接中拒绝接受带有 Subscription Identifier 消息的问题。

  2. 修复桥接连接接收到 Retain 消息时会造成数据类型不兼容而导致的协议错误断开。

  3. 修正了 HTTP API api/v4/clients 中获取到的错误的会话保持状态。

  4. 修改了 Broker 的行为:当客户端使用会话保持功能并断开连接时, 之前 Broker 希望能够复用此 Socket 等待客户端自动重连,而不会主动关闭。如今已修改为普通关闭操作。此功能的讨论:点击查看

  5. 在 NanoNNG 模块中更新了新的 nng_mqtt_quic_open_conf API 用于开启 QUIC 连接。

  6. 优化 CMakeList 修复 OpenSSL 和 MbedTLS 库在编译阶段造成的不兼容问题。

即将到来

NanoMQ 项目目前的重点是提升 NanoSDK 的易用性和支持 MQTT5 over QUIC 桥接,并且将继续完善 DDS 协议代理功能和提供更多更丰富的文档和教程。原计划中的 SOME/IP 协议代理将推迟至下一个版本发布。

版权声明: 本文为 EMQ 原创,转载请注明出处。

原文链接:https://www.emqx.com/zh/blog/nanomq-newsletter-202303


相關推薦

2023-12-30

0.2.3 负载均衡中的HTTP2 HTTP2 协议处理 try_files 功能的实现 修复bug wmproxy wmproxy 已用 Rust 实现 http/https 代理,socks5 代理,反向代理,负载均衡,静态文件服务器,四层 TCP/UDP 转发,内网穿透,后续将实现 websocket 代理等,

2024-01-20

V0.2.5 已实现websocket代理, 可以快速的将websocket流量转成tcp流量 完善命令行模式, 启动将更加简单   wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 负载均衡, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现web

2023-12-23

0.2.2 内网穿透优化 HTTP转发 HTTPS转发(证书在服务器,内网为HTTP) TCP转发(纯粹的TCP转发,保持原样的协议) PROXY转发(服务端接收数据,内网的客户端当成PROXY客户端,相当于逆向访问内网服务器,[新增]) wmproxy wmproxy已用Rus

2024-02-08

0.2.7 添加多地址解析监听 以下是常见的IP解析示例情况,本地ip为192.168.0.100示例: 正常IP解析 127.0.0.1:8869 解析成 ipv4 127.0.0.1 端口 8869,只接受本地来的连接信息 0.0.0.0:8869 解析成 ipv4 0.0.0.0 端口 8869,可接受所有

2022-10-30

EsearchX for java 是基于 okhttp + snack3 开发的,一个代码直白和简单的 Elasticsearch ORM 框架。 支持 jdk8、jdk11、jdk17、jdk19 支持 es7.x、es8.x 采用 lambda 链式写法,很是清新 public class DemoApp { public void demo() { EsContext esx = new EsContext(

2023-07-27

数据可视化引擎 G2 v5.0.17 版本现已发布,具体更新内容包括: refactor(theme):更改一些主题属性 #5307 fix(label):清除无效标签 #5310 chore:添加每周报告 #5311 fix(chart):chart.clear 保留一些全局选项 #5318 feat(

2023-08-05

Proxy 是 golang 实现的高性能 http、https、websocket、tcp、udp、socks5 代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP 端口映射、SSH 中转、TLS 加密传输、协议转换、DNS 防污染智能代理、前置 CDN/Nginx 反代、代理连

2024-04-14

Proxy 是 golang 实现的高性能 http、https、websocket、tcp、udp、socks5 代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP 端口映射、SSH 中转、TLS 加密传输、协议转换、DNS 防污染智能代理、前置 CDN/Nginx 反代、代理连

2024-04-12

Proxy 是 golang 实现的高性能 http、https、websocket、tcp、udp、socks5 代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP 端口映射、SSH 中转、TLS 加密传输、协议转换、DNS 防污染智能代理、前置 CDN/Nginx 反代、代理连

2023-10-28

已实现初步的反向代理支持,包含主动式健康检查,四层代理,七层代理,及配置的热加载等功能 wmproxy将用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器, 后续将实现websocket代理, 内外网穿透等, 会将实现过程分享

2023-11-04

0.2.0功能: 1. 实现内存缓冲区, 防止内存增长过多 2. 实现流量控制, 可限制某一请求占用过多流量   已实现初步的反向代理支持,包含主动式健康检查,四层代理,七层代理,及配置的热加载等功能 wmproxy 将用 Rust&n

2024-04-11

OpenSSL 3.3.0 已发布,此版本在 OpenSSL 3.2 中引入的 QUIC 连接支持的基础上,对 QUIC 传输协议支持做了许多改进。 OpenSSL 3.2 的重点是 QUIC 客户端支持,而 OpenSSL 3.3 则在 QUIC 服务器端做了更多工作。有关 OpenSSL 当前 QUIC HTTP/3 支持的

2023-11-25

OpenSSL 3.2之后的下一个功能性更新,最迟将于2024年4月30日发布。预计该版本将包括QUIC服务器支持。

2023-12-09

0.2.1 1. 请求流量控制 2. 负载均衡 3. http接口重构 wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起