首页
社区
课程
招聘
[原创]物联网防火墙himqtt源码之MQTT协议分析
发表于: 2019-10-31 09:50 9500

[原创]物联网防火墙himqtt源码之MQTT协议分析

2019-10-31 09:50
9500


himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,采用epoll模式支持IoT数十万的高并发连接,并且兼容ModSecurity部分规则。 代码非常优秀,非常值得收藏和学习,今天笔者就从结合himqtt的源码来进行MQTT协议分析。

MQTT协议一共有14个指令,如下表所示:其中有9个报文都是固定的2~4个字节,非常简单适合小型物联网设备。






 

MQTT协议由指令号(1字节)+长度(1-4字节不定)+内容组成,比如下面第一个字节0x30表示publish发布消息指令,0x26表示后面的内容长度就是38个字节。

---------------MQTT PUBLISH-  ------40bytes-------------------------------------------

| 30 26 00 14 68 6f 6d 65 2f 67 61 72 64 65 6e 2f   |0&..home/garden/|

| 66 6f 75 6e 74 61 69 6e 31 32 33 34 35 36 37 38  |fountain12345678|

| 39 30 61 62 63 64 65 66                        |90abcdef

先到github上下载himqtt最新源码,https://github.com/qq4108863/himqtt/ ,打开src/waf/mqtt.c文件。

特别注意的是:长度占用的字节数是可变的(1-4字节),具体的计算方法在process_mqtt_msg这个函数里面,理论上这种算法后续消息内容是最大长度是268435455字节(约255M)。

  static void process_mqtt_msg(mqtt_waf_msg *req)

{

......

/* decode mqtt variable length */

  len = len_len = 0;

  p   = req->buf + 1;

  eop = &req->buf[req->pos];

  while (p < eop) {

    lc = *((const unsigned char *) p++);

    len += (lc & 0x7f) << 7 * len_len;

    len_len++;

    if (!(lc & 0x80)) break;

    if (len_len > 4){

req->msg_state = MQTT_MSG_ERROR;

return;

    }

  }

.....

}

......

长度和协议校验正确后,根据收到的消息类型,以此对不同的指令进行处理,代码逻辑非常清晰:

switch (mqtt_msg_type)

{

case MQTT_CONNECT:

req->msg_state = mqtt_connect(req,p,end,&mm);

break;

case MQTT_CONNACK:

break;

case MQTT_PUBLISH:

req->msg_state = mqtt_publish(req,p,end,&mm);

break;

case MQTT_SUBSCRIBE:

req->msg_state = mqtt_subscribe(req,p,end,&mm);

break;

case MQTT_UNSUBSCRIBE:

req->msg_state = mqtt_unsubscribe(req,p,end,&mm);

......

下面我们主要CONNECT、PUBLISH、SUBSCRIBE、UNSUBSCRIBE这几个复杂一点的报文协议内容。

CONNECT是客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文,其中登录的身份认证如用户名、密码就在这个指令里面。报文协议如下:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//