物联网防火墙himqtt源码之MQTT协议分析-Arduino中文社区 - Powered by Discuz! Archiver

hihttps 发表于 2019-11-4 09:04

物联网防火墙himqtt源码之MQTT协议分析

物联网防火墙himqtt源码之MQTT协议分析 himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,采用epoll模式支持IoT数十万的高并发连接,并且兼容ModSecurity部分规则。 代码非常优秀,非常值得收藏和学习,今天笔者就从结合himqtt的源码来进行MQTT协议分析。一、MQTT协议指令汇总MQTT协议一共有14个指令,如下表所示:其中有9个报文都是固定的2~4个字节,非常简单适合小型物联网设备。
名字值固定报文描述
CONNECT1否客户端请求与服务端建立连接
CONNACK2是服务端确认连接建立
PUBLISH3否发布消息
PUBACK4是收到发布消息确认
PUBREC5是发布消息收到
PUBREL6是发布消息释放
PUBCOMP7是发布消息完成
SUBSCRIBE8否订阅请求
SUBACK9否订阅确认
UNSUBSCRIBE10否取消订阅
UNSUBACK11是取消订阅确认
PING12是客户端发送PING(连接保活)命令
PINGRSP13是PING命令回复
DISCONNECT14是断开连接
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;          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这几个复杂一点的报文协议内容。二、HiMQTT协议分析1、CONNECT连接服务端CONNECT是客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文,其中登录的身份认证如用户名、密码就在这个指令里面。报文协议如下:--------------MQTT CONNECT-----105bytes-----------------------------| 10 67 00 04 4d 51 54 54 04 c2 00 3c 00 19 4d 51 |.g..MQTT...<..MQ|| 54 54 5f 46 58 5f 43 6c 69 65 6e 74 5f 39 69 75|TT_FX_Client_9iu|| 79 38 37 36 35 35 35 00 12 69 6f 74 66 72 65 65 |y876555..iotfree|| 74 65 73 74 2f 74 68 69 6e 67 30 00 2c 59 55 37 |test/thing0.,YU7|| 54 6f 76 38 7a 46 57 2b 57 75 61 4c 78 39 73 39 |Tov8zFW+WuaLx9s9|| 49 33 4d 4b 79 63 6c 69 65 39 53 47 44 75 75 4e |I3MKyclie9SGDuuN|| 6b 6c 36 6f 39 4c 58 6f 3d                      |kl6o9LXo= 10 //CONNECT指令号67 //长度103字节00 04 //MQTT协议长度为4字节4d 51 54 54 //MQTT固定字符串04 //版本3.1.1c2 //连接标记,是否由用户名/密码等00 3c //心跳间隔时间60秒00 19 //用户名长度25字节,后面是用户名4d 51 54 54 5f 46 58 5f 43 6c 69 65 6e 74 5f 39 69 75 79 38 37 36 35 35 3500 12 //密码18字节69 6f 74 66 72 65 65 74 65 73 74 2f 74 68 69 6e 67 30//密码00 2c //will message长度。59 55 37 ......6f 3d//will message内容 2、PUBLISH发布消息PUBLISH 是从客户端向服务端或者服务端向客户端传输一个应用消息,这是通信的最重点,就像HTTP协议的GET一样。报文协议分析如下:/*---------------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*/ 30 //PUBLISH指令号26 //长度39字节00 14 //TOPIC长度20字节68 6f 6d 65 2f 67 61 72 64 65 6e 2f 66 6f 75 6e //TOPIC31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 //发布的消息 在实际编程中,这个地方大多是json格式提交给服务器,SQL注入/XSS攻击很可能从这里对物联网设备发起攻击,所以一定要做攻击检查,himqtt不知道什么原因把ngx_http_dummy_json_parse解析json格式的函数注释掉了。 3、SUBSCRIBE订阅消息SUBSCRIBE是由客户端向服务端发送的,用于创建一个或多个订阅。每个订阅是该客户端关注的一个或多个主题。服务端依据客户端的订阅来匹配主题,然后将对应的PUBLISH报文发送给客户端。报文协议分析如下:---------------MQTT SUBSCRIBE------33bytes-----------------------------| 82 1f 00 01 00 1a 68 6f 6d 65 2f 67 61 72 64 65 |......home/garde|| 6e 2f 66 6f 75 6e 74 61 69 6e 64 65 6c 65 74 65 |n/fountaindelete|| 00 82 //SUBSCRIBE指令1f //长度31字节00 01 //Message Identifier00 1a //TOPIC长度2668 6f 6d 65 2f 67 61 72 64 65 6e 2f 66 6f 75 6e 74 61 69 6e 64 65 6c 65 74 65 //TOPIC00 //request QOS 4、UNSUBSCRIBE取消订阅消息 UNSUBSCRIBE是客户端发送本报文给服务端,用于取消订阅主题。报文协议分析如下:---------------MQTT UNSUBSCRIBE-------32bytes-----------------------------| a2 1e 00 02 00 1a 68 6f 6d 65 2f 67 61 72 64 65 |......home/garde|| 6e 2f 66 6f 75 6e 74 61 69 6e 64 65 6c 65 74 65 |n/fountaindelete| a2 //SUBSCRIBE指令1e //长度30字节00 02 //Message Identifier00 1a //TOPIC长度2668 6f 6d 65 2f 67 61 72 64 65 6e 2f 66 6f 75 6e 74 61 69 6e 64 65 6c 65 74 65 //TOPIC 总体来说,MQTT协议比HTTP协议简单多了,非常适合物联网设备。另外himqtt其实也是一款功能强大的WEB应用防火墙,其他源码我们在另外的文章中再介绍。也许未来几年IPV6普及后,很可能几百亿带电的物体都会联网哦,期待himqtt这类高并发的物联网防火墙能扛起信息安全的大旗,彻底阻挡黑客攻击。    
页: [1]
查看完整版本: 物联网防火墙himqtt源码之MQTT协议分析