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

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

一、MQTT协议指令汇总

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

名字

固定报文

描述

CONNECT

1

客户端请求与服务端建立连接

CONNACK

2

服务端确认连接建立

PUBLISH

3

发布消息

PUBACK

4

收到发布消息确认

PUBREC

5

发布消息收到

PUBREL

6

发布消息释放

PUBCOMP

7

发布消息完成

SUBSCRIBE

8

订阅请求

SUBACK

9

订阅确认

UNSUBSCRIBE

10

取消订阅

UNSUBACK

11

取消订阅确认

PING

12

客户端发送PING(连接保活)命令

PINGRSP

13

PING命令回复

DISCONNECT

14

断开连接

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这几个复杂一点的报文协议内容。

二、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.1

c2 //连接标记,是否由用户名/密码等

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 35

00 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 //TOPIC

31 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 Identifier

00 1a //TOPIC长度26

68 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

00 //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 Identifier

00 1a //TOPIC长度26

68 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这类高并发的物联网防火墙能扛起信息安全的大旗,彻底阻挡黑客攻击。

物联网防火墙himqtt源码之MQTT协议分析的更多相关文章

  1. 从物联网防火墙himqtt源码谈哈希和红黑树的应用场景区别

    从物联网防火墙himqtt源码谈哈希和红黑树的应用场景区别 himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,很多数据结构适合 ...

  2. 物联网MQTT协议分析和开源Mosquitto部署验证

    在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...

  3. ArrayList源码和多线程安全问题分析

    1.ArrayList源码和多线程安全问题分析 在分析ArrayList线程安全问题之前,我们线对此类的源码进行分析,找出可能出现线程安全问题的地方,然后代码进行验证和分析. 1.1 数据结构 Arr ...

  4. Okhttp3源码解析(3)-Call分析(整体流程)

    ### 前言 前面我们讲了 [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析]( ...

  5. Okhttp3源码解析(2)-Request分析

    ### 前言 前面我们讲了 [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析]( ...

  6. Spring mvc之源码 handlerMapping和handlerAdapter分析

    Spring mvc之源码 handlerMapping和handlerAdapter分析 本篇并不是具体分析Spring mvc,所以好多细节都是一笔带过,主要是带大家梳理一下整个Spring mv ...

  7. HashMap的源码学习以及性能分析

    HashMap的源码学习以及性能分析 一).Map接口的实现类 HashTable.HashMap.LinkedHashMap.TreeMap 二).HashMap和HashTable的区别 1).H ...

  8. ThreadLocal源码及相关问题分析

    前言 在高并发的环境下,当我们使用一个公共的变量时如果不加锁会出现并发问题,例如SimpleDateFormat,但是加锁的话会影响性能,对于这种情况我们可以使用ThreadLocal.ThreadL ...

  9. Netty 源码学习——客户端流程分析

    Netty 源码学习--客户端流程分析 友情提醒: 需要观看者具备一些 NIO 的知识,否则看起来有的地方可能会不明白. 使用版本依赖 <dependency> <groupId&g ...

随机推荐

  1. 使用jQuery快速高效制作网页交互特效----jQuery中的事件与动画

    jQuery中的事件 和WinForm一样,在网页中的交互也是需要事件来实现的,例如tab切换效果,可以通过鼠标单击事件来实现. 事件在元素对象与功能代码中起着重要的桥梁作用. 在JQuery中,事件 ...

  2. 服务器nginx配置显示文件而不是下载

    有时候在服务器上配置某些文件比如TXT文件,在浏览器打开的时候,会弹出下载.如何只让他在浏览器中显示,而不是下载呢.在nginx配置文件中添加一行代码 add_header Content-Type ...

  3. 009_Source Insight 3.5安装及使用

    链接:https://pan.baidu.com/s/1CBEhIhYtZZ6rUjq7yu4J2w提取码:qkv0 复制这段内容后打开百度网盘手机App,操作更方便哦 SourceInsight3. ...

  4. idea2018使用整理

    1.idea怎么设置选中文件时,自动在左侧弹出文件所在位置及文件?

  5. SQLServer常见查询问题

     http://bbs.csdn.net/topics/340078327 1.生成若干行记录 --自然数表1-1M CREATE TABLE Nums(n int NOT NULL PRIMAR ...

  6. python循环导入的问题

    1.问题 循环导入,代码如下: from c import c def b(): print('b') b.py from b import b def a(): # from b import b ...

  7. 【概率论】5-6:正态分布(The Normal Distributions Part I)

    title: [概率论]5-6:正态分布(The Normal Distributions Part I) categories: - Mathematic - Probability keyword ...

  8. 【原】Python基础-序列

    1 序列 在Python中,最基本的数据结构是序列,序列中每个元素被分配一个编号,也称为索引.第一个索引为0,第二个则是1,以此类推.序列中最后一个元素被标为-1,倒数第二个元素被标为-2,以此类推. ...

  9. 常用的etl工具比较

    ETL是什么? ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的过程.(数 ...

  10. Alpha项目冲刺! Day3-产出

    各个成员今日完成的任务 林恩:任务分工,博客撰写,完善设置等模块 杨长元:安卓本地数据库基本建立 李震:完成注册页面 胡彤:完善服务端 寇永明:画图,学习 王浩:画图,学习 李杰:画图,学习 各个成员 ...