物聯網防火墻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這類高并發的物聯網防火墻能扛起資訊安全的大旗,徹底阻擋黑客攻擊,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/59937.html
標籤:其他
上一篇:以太網幀前導碼、幀間隙
