MQTT抓包分析

1. 概述

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發佈/訂閱(Publish/Subscribe)模式的輕量級通信協議,該協議構建於TCP/IP協議上,由IBM在1999年發佈,目前最新版本爲v3.1.1。MQTT最大的優勢在於能夠以極少的代碼和有限的帶寬,爲遠程設備提供實時可靠的消息服務。作爲一種低開銷、低帶寬佔用的即時通信協議,MQTT在物聯網、小型設備、移動應用等方面有普遍的應用。衆所周知,TCP/IP參考模型能夠分爲四層:應用層、傳輸層、網絡層、鏈路層。TCP和UDP位於傳輸層,應用層常見的協議有HTTP、FTP、SSH等。MQTT協議運行於TCP之上,屬於應用層協議,所以只要是支持TCP/IP協議棧的地方,均可以使用MQTT。服務器

2. MQTT客戶端

一個使用MQTT協議的應用程序或者設備,它老是創建到服務器的網絡鏈接。客戶端能夠:
(1)發佈其餘客戶端可能會訂閱的信息;  //發佈消息
(2)訂閱其它客戶端發佈的消息;   //訂閱消息
(3)退訂或刪除應用程序的消息;    //退訂消息
(4)斷開與服務器鏈接。        //斷開,鏈接服務器
網絡

3. MQTT服務器

MQTT服務器以稱爲「消息代理」(Broker),能夠是一個應用程序或一臺設備。它是位於消息發佈者和訂閱者之間,它能夠:
(1)接受來自客戶的網絡鏈接;         //接受客戶端鏈接
(2)接受客戶發佈的應用信息;        //接收客戶端發佈的消息
(3)處理來自客戶端的訂閱和退訂請求;    //處理消息的訂閱及退訂
(4)向訂閱的客戶轉發應用程序消息。     //推送消息
session

4. MQTT消息格式

每條MQTT命令消息的消息頭都包含一個固定的報頭,有些消息會攜帶一個可變報文頭和一個負荷。消息格式以下:ide

固定報文頭 | 可變報文頭 | 負荷ui

4.1 固定報文頭(Fixed Header)

MQTT固定報文頭最少有兩個字節,第一字節包含消息類型(Message Type)和QoS級別等標誌位。第二字節開始是剩餘長度字段,該長度是後面的可變報文頭加消息負載的總長度,不包括用於編碼剩餘長度字段自己的字節數,該字段最多容許四個字節。

編碼

圖4-1固定報頭報文結構

剩餘長度字段單個字節最大值爲二進制0b0111 1111,16進制0x7F。也就是說,單個字節能夠描述的最大長度是127字節。爲何不是256字節呢?由於MQTT協議規定,單個字節第八位(最高位)若爲1,則表示後續還有字節存在,第八位起「延續位」的做用。
例如,數字64,編碼爲一個字節,十進制表示爲64,十六進制表示爲0×40。數字321(65+2*128)編碼爲兩個字節,重要性最低的放在前面,第一個字節爲65+128=193(0xC1),第二個字節是2(0x02),表示2×128。
因爲MQTT協議最多隻容許使用四個字節表示剩餘長度(如表1),而且最後一字節最大值只能是0x7F不能是0xFF,因此能發送的最大消息長度是256MB,而不是512MB。


圖4-2數據包類型


圖4-3數據包類型標識位

4.2 可變報文頭(Variable Header)

可變報文頭主要包含協議名、協議版本、鏈接標誌(Connect Flags)、心跳間隔時間(Keep Alive timer)、鏈接返回碼(Connect Return Code)、主題名(Topic Name)等,後面會針對主要部分進行講解。

加密

圖4-4可變報頭結構

4.2.1 消息質量(QoS)

MQTT消息質量有三個等級,QoS 0,QoS 1和 QoS 2。
QoS 0:最多分發一次。消息的傳遞徹底依賴底層的TCP/IP網絡,協議裏沒有定義應答和重試,消息要麼只會到達服務端一次,要麼根本沒有到達。
QoS 1:至少分發一次。服務器的消息接收由PUBACK消息進行確認,若是通訊鏈路或發送設備異常,或者指定時間內沒有收到確認消息,發送端會重發這條在消息頭中設置了DUP位的消息。
QoS 2:只分發一次。這是最高級別的消息傳遞,消息丟失和重複都是不可接受的,使用這個服務質量等級會有額外的開銷。
3d

4.2.2 遺願標誌(Will Flag)

在可變報文頭的鏈接標誌位字段(Connect Flags)裏有三個Will標誌位:Will Flag、Will QoS和Will Retain Flag,這些Will字段用於監控客戶端與服務器之間的鏈接情況。若是設置了Will Flag,就必須設置Will QoS和Will Retain標誌位,消息主體中也必須有Will Topic和Will Message字段。
那遺願消息是怎麼回事呢?服務器與客戶端通訊時,當遇到異常或客戶端心跳超時的狀況,MQTT服務器會替客戶端發佈一個Will消息。固然若是服務器收到來自客戶端的DISCONNECT消息,則不會觸發Will消息的發送。
所以,Will字段能夠應用於設備掉線後須要通知用戶的場景。
代理

4.2.3 鏈接保活心跳機制(Keep Alive Timer)

MQTT客戶端能夠設置一個心跳間隔時間(Keep Alive Timer),表示在每一個心跳間隔時間內發送一條消息。若是在這個時間週期內,沒有業務數據相關的消息,客戶端會發一個PINGREQ消息,相應的,服務器會返回一個PINGRESP消息進行確認。若是服務器在一個半(1.5)心跳間隔時間週期內沒有收到來自客戶端的消息,就會斷開與客戶端的鏈接。心跳間隔時間最大值大約能夠設置爲18個小時,0值意味着客戶端不斷開blog

4.3 有效負荷(Payload)

Payload直譯爲負荷,可能讓人摸不着頭腦,實際上能夠理解爲消息主體(body)。

圖4-5消息結構

當MQTT發送的消息類型是CONNECT(鏈接)、PUBLISH(發佈)、SUBSCRIBE(訂閱)、SUBACK(訂閱確認)、UNSUBSCRIBE(取消訂閱)時,則會帶有負荷。
(1)CONNECT,消息體內容主要是:客戶端的ClientID、訂閱的Topic、Message以及用戶名和密碼。
(2)SUBSCRIBE,消息體內容是一系列的要訂閱的主題以及QoS。
(3)SUBACK,消息體內容是服務器對於SUBSCRIBE所申請的主題及QoS進行確認和回覆。
(4)UNSUBSCRIBE,消息體內容是要訂閱的主題。
(5)PUBLISH,消息體內容是相關主題的數據。

5. MQTT控制報文

介紹MQTT協議的報文組成並經過wireshark抓取報文包分析報文內容

5.1 鏈接服務端(CONNECT)

Connect報文在MQTT客戶端鏈接服務器時發出,報文由三部分組成,下面將分別介紹

5.1.1 固定報頭(fixed header)


圖5-1 CONNECT固定報頭報文

Connect名稱的值爲1,低四位保留,剩餘長度保存可變報頭(10字節)加上有效載荷的長度。

5.1.2 可變報頭(variable header)

Connect報文的可變報頭包含協議名,協議等級,鏈接標誌和保持鏈接

圖5-2 CONNECT可變報頭報文

報文協議名以前有兩個字節的報文標識符,惟一標識這條報文。

鏈接標誌包含用戶名標誌(username flag)、密碼標誌(password flag)、遺囑標誌(will flag)、遺囑服務指令(will Qos)、遺囑保留標誌(will retain)、清除會話標誌(clean session)、保留位(reserved)。
用戶名標誌(username flag):若用戶名標誌被置爲1,有效載荷中必須包含用戶名字段。
密碼標誌(password flag):若密碼標誌被置爲1,有效載荷中必須包含密碼字段,當用戶標誌被置爲0時,密碼標誌必須被置0.。
遺囑標誌(will flag):若遺囑標誌被置1,遺囑服務指令(will Qos)與遺囑保留標誌(will retain)會被服務器用到,遺囑消息中必須包含will topic和will message。
遺囑服務指令(will Qos):若是遺囑標誌被設置爲0,遺囑QoS也必須設置爲0(0x00),若是遺囑標誌被設置爲1,遺囑QoS的值能夠等於0(0x00),1(0x01),2(0x02)。它的值不能等 於3。
遺囑保留標誌(will retain):若遺囑保留標誌位被置位,服務器將保留遺囑消息(保留髮布),當客戶端異常斷開鏈接時將遺囑發給訂閱遺囑主題的客戶。
清除會話標誌(clean session):標誌被設置爲1,客戶端和服務端必須丟棄以前的任何會話並開始一個新的會話(以前的訂閱與發佈消息被刪除),若標誌爲0,恢復與服務器會話鏈接,若沒有鏈接 新建一個會話鏈接(不刪除以前與客戶端的會話信息並保存斷開本次會話以後的Qos1與Qos2消息)。
保留位(reserved):若是不爲0必須斷開客 戶端鏈接。

報文最後兩字節爲發送心跳包的間隔時間,當客戶端沒有數據發給服務器時,鬚髮送心跳包(pingreq)到服務器,保證鏈接不斷開。

5.1.3 有效載荷(Payload)

CONNECT報文的有效載荷(payload)包含一個或多個以長度爲前綴的字段,可變報頭中的 標誌決定是否包含這些字段。若是包含的話,必須按這個順序出現:客戶端標識符,遺囑主題,遺囑消息,用戶名,密碼。
客戶端標識符(client identifier):服務器經過識別客戶標識符,肯定客戶端,識別二者間的MQTT會話相關狀態,服務器容許客戶端提供一個零字節的標識符,但clean session必須置1。

圖5-3 CONNECT消息報文

5.2鏈接請求確認(CONNACK)

Connack爲服務器確認客戶端連上服務給出的迴應。

5.2.1 固定報頭(fixed header)


圖5-4 CONNACK固定報頭報文

5.2.2 可變報頭(variable header)


圖5-5 CONNACK可變報頭報文

  • 第一字節1~7位保留,第0位是當前會話標誌(session present),若清除會話標誌被置1,該位爲0,若清除會話標誌爲0且服務器沒有與客戶端會話保存,該位置0,有保存置1
    第二字節保存鏈接返回碼,若鏈接成功返回0。


  • 圖5-6 鏈接返回碼


    圖5-7 CONNECT響應報文

    5.3發佈消息(PUBLISH)

    發佈消息可由客戶端或服務器發出,被消息訂閱者接收。

    5.3.1 固定報頭(fixed header)


    圖5-8 PUBLISH固定報頭報文

    固定報頭第一字節的低四位分別保存重發標誌(DUP),服務質量(Qos),保留標誌(RETAIN)。
    重發標誌(DUP):當該位被置1,表示該條報文爲重發報文,客戶端或服務端請求重發一個PUBLISH報文時,必須將DUP標誌設置爲1。對於QoS 0的消息,DUP標誌必須設置爲0。
    服務質量(Qos):表示發送質量,取值有00 01 10。
    保留標誌(RETAIN):若該位被置1,表示服務器必須保存其應用消息和質量等級,若爲0,表示該消息不須保存,若是服務端收到一條保留(RETAIN)標誌爲1的QoS 0消息,它必須丟棄以前爲那個主題保留的任何消息。它應該將這個新的QoS0消息看成那個主題的新保留消息,可是任什麼時候候均可以選擇丟棄它,保留標誌爲1且有效載荷爲零字節的PUBLISH報文會被服務端看成正常消息處理,它會被髮送給訂閱主題匹配的客戶端。此外,同一個主題下任何現存的保留消息必須被移除,所以這個主題以後的任何訂閱者都不會收到一個保留消息。

    5.3.2 可變報頭(variable header)

    可變報頭按順序包含主題名和報文標識符。

    5.3.3 有效載荷(Payload)

    若Qos爲0,無響應,若Qos爲1,返回PUBACK報文,若Qos爲2,返回PUBREC報文。

    圖5-9 publish消息報文

    5.4發佈確認(PUBACK)

    由服務器或客戶端確認已接收到pub消息

    5.4.1 固定報頭(fixed header)


    圖5-10 puback固定報頭報文

    5.4.2 可變報頭(variable header)

    只有兩字節的報文標識(報文標識爲pub報文標識)

    圖5-11 puback消息報文

    5.5發佈收到 PUBREC(QoS 2,第一步)

    5.5.1 固定報頭(fixed header)


    圖5-12 pubrec固定報頭報文

    5.5.2 可變報頭(variable header)

    只有兩字節的報文標識(報文標識爲pub報文標識)

    圖5-13 pubrec消息報文

    5.6發佈釋放 PUBREL(QoS 2,第二步)

    5.6.1 固定報頭(fixed header)


    圖5-14 pubrel固定報頭報文

    5.6.2 可變報頭(variable header)

    只有兩字節的報文標識(報文標識爲pub報文標識)

    圖5-15 pubrel消息報文

    5.7發佈完成 PUBCOMP(QoS 2,第三步)

    5.7.1 固定報頭(fixed header)


    圖5-16 pubcomp固定報頭報文

    5.7.2 可變報頭(variable header)

    只有兩字節的報文標識(報文標識爲pub報文標識)

    圖5-17 pubcomp消息報文

    5.8訂閱主題(SUBSCRIBE)

    客戶端經過訂閱消息的方式來接收服務端下發的消息

    5.8.1 固定報頭(fixed header)

    SUBSCRIBE控制固定報頭的第3,2,1,0位是保留位,必須分別設置爲0,0,1,0。服務端必須將其它的任何值都當作是不合法的並關閉網絡鏈接

    圖5-18 subscribe固定報頭報文

    5.8.2 可變報頭(variable header)

    只有兩字節的報文標識

    5.8.3 有效載荷(Payload)


    圖5-19 subscribe有效載體報文

    消息載體包含若干主題過濾器和服務質量等級
    PUB時指定的qos是服務器確定按此規則接收,可是最終訂閱者不必定。
    SUB時指定的qos表示訂閱者能夠接收的最高消息等級,也就是可能收到更低等級的消息


    圖5-20 subscribe消息報文

    5.9訂閱確認(SUBACK)

    SUBACK報文包含一個返回碼清單,它們指定了SUBSCRIBE請求的每一個訂閱被授予的最大QoS等級。

    5.9.1 固定報頭(fixed header)


    圖5-21 suback固定報頭報文

    5.9.2 可變報頭(variable header)

    只有兩字節的報文標識

    5.9.3 有效載荷(Payload)


    圖5-22 suback有效載體報文

    容許的返回碼爲0x00-最大Qos0,0x01-最大Qos1,0x02-最大Qos2,0x80-失敗

    圖5-23 suback消息報文

    5.10取消訂閱 (UNSUBSCRIBE)

    5.10.1 固定報頭(fixed header)


    圖5-24 unsubscribe固定報頭報文

    5.10.2 可變報頭(variable header)

    只有兩字節的報文標識

    5.10.3 有效載荷(Payload)

    包含須要取消訂閱的主題過濾器的列表.

    圖5-25 unsubscribe消息報文

    5.11取消訂閱確認 (UNSUBACK)

    5.11.1 固定報頭(fixed header)


    圖5-26 unsuback固定報頭報文

    5.11.2 可變報頭(variable header)

    只有兩字節的報文標識(報文標識爲unsub報文標識)

    圖5-27 unsuback消息報文

    5.12心跳請求 (PINGREQ)

    客戶端發送PINGREQ報文給服務端的。用於:
    1.在沒有任何其它控制報文從客戶端發給服務的時,告知服務端客戶端還活着。
    2.請求服務端發送 響應確認它還活着。
    3.使用網絡以確認網絡鏈接沒有斷開

    5.12.1 固定報頭(fixed header)


    圖5-28 pingreq固定報頭報文


    圖5-29 pingreq消息報文

    5.13心跳響應 (PINGRESP)

    5.13.1 固定報頭(fixed header)


    圖5-30 pingresp固定報頭報文


    圖5-31 pingresp消息報文

    5.14斷開鏈接 (DISCONNECT)

    5.14.1 固定報頭(fixed header)


    圖5-32 disconnect固定報頭報文


    圖5-33 disconnect消息報文

    抓包注意:用標準不加密MQTT能抓到便於查看的報文,加密報文解析時不便於理解

    創做不易,白嫖很差,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見!

    清風 | 文 【原創】

    若是本篇博客有任何錯誤,請批評指教,不勝感激 !

    相關文章
    相關標籤/搜索