WebSocket协议理解-数据包格式解析
WebSocket 的誕生
做客戶端開(kāi)發(fā)時(shí),接觸最多的應(yīng)用層網(wǎng)絡(luò)協(xié)議,就是 HTTP 協(xié)議,而今天介紹的 WebSocket,下層和 HTTP 一樣也是基于 TCP 協(xié)議,這是一種輕量級(jí)網(wǎng)絡(luò)通信協(xié)議,也屬于應(yīng)用層協(xié)議。
WebSocket 與 HTTP/2 一樣,其實(shí)都是為了解決 HTTP/1.1 的一些缺陷而誕生的,而 WebSocket 針對(duì)的就是「請(qǐng)求-應(yīng)答」這種"半雙工"的模式的通信缺陷。
「請(qǐng)求-應(yīng)答」是"半雙工"的通信模式,數(shù)據(jù)的傳輸必須經(jīng)過(guò)一次請(qǐng)求應(yīng)答,這個(gè)完整的通信過(guò)程,通信的同一時(shí)刻數(shù)據(jù)只能在一個(gè)方向上傳遞。它最大的問(wèn)題在于,HTTP 是一種被動(dòng)的通信模式,服務(wù)端必須等待客戶端請(qǐng)求才可以返回?cái)?shù)據(jù),無(wú)法主動(dòng)向客戶端發(fā)送數(shù)據(jù)。
這也導(dǎo)致在 WebSocket 出現(xiàn)之前,一些對(duì)實(shí)時(shí)性有要求的服務(wù),通常是基于輪詢(Polling)這種簡(jiǎn)單的模式來(lái)實(shí)現(xiàn)。輪詢就是由客戶端定時(shí)發(fā)起請(qǐng)求,如果服務(wù)端有需要傳遞的數(shù)據(jù),可以借助這個(gè)請(qǐng)求去響應(yīng)數(shù)據(jù)。輪詢的缺點(diǎn)也非常明顯,大量空閑的時(shí)間,其實(shí)是在反復(fù)發(fā)送無(wú)效的請(qǐng)求,這顯然是一種資源的損耗。
雖然在之后的 HTTP/2、HTTP/3 中,針對(duì)這種半雙工的缺陷新增了 Stream、Server Push 等特性,但是「請(qǐng)求-應(yīng)答」依然是 HTTP 協(xié)議主要的通信方式。
WebSocket 協(xié)議是由 HTML5 規(guī)范定義的,原本是為了瀏覽器而設(shè)計(jì)的,可以避免同源的限制,瀏覽器可以與任意服務(wù)端通信,現(xiàn)代瀏覽器基本上都已經(jīng)支持 WebSocket。
雖然 WebSocket 原本是被定義在 HTML5 中,但它也適用于移動(dòng)端,盡管移動(dòng)端也可以直接通過(guò) Socket 與服務(wù)端通信,但借助 WebSocket,可以利用 80(HTTP) 或 443(HTTPS)端口通信,有效的避免一些防火墻的攔截。
WebSocket 是真正意義上的全雙工模式,也就是我們俗稱的「長(zhǎng)連接」。當(dāng)完成握手連接后,客戶端和服務(wù)端均可以主動(dòng)的發(fā)起請(qǐng)求,回復(fù)響應(yīng),并且兩邊的傳輸都是相互獨(dú)立的。
一、WebSocket 的特點(diǎn)
WebSocket 的數(shù)據(jù)傳輸,是基于 TCP 協(xié)議,但是在傳輸之前,還有一個(gè)握手的過(guò)程,雙方確認(rèn)過(guò)眼神,才能夠正式的傳輸數(shù)據(jù)。
WebSocket 的握手過(guò)程,符合其 "Web" 的特性,是利用 HTTP 本身的 "協(xié)議升級(jí)" 來(lái)實(shí)現(xiàn)。
在建立連接前,客戶端還需要知道服務(wù)端的地址,WebSocket 并沒(méi)有另辟蹊徑,而是沿用了 HTTP 的 URL 格式,但協(xié)議標(biāo)識(shí)符變成了 "ws" 或者 "wss",分別表示明文和加密的 WebSocket 協(xié)議,這一點(diǎn)和 HTTP 與 HTTPS 的關(guān)系類似。
1 ws://cxmydev.com/some/path 2 ws://cxmydev.com:8080/some/path 3 wss://cxmydev.com:443?uid=xxx
WebSocket連接url舉例
二、由http/https---->WebSocket的切換瀏覽器調(diào)試模式可見(jiàn)
--------------------------------------------------------------------------------
Websocket的世界
通信協(xié)議格式是WebSocket格式,服務(wù)器端采用Tcp Socket方式接收數(shù)據(jù),進(jìn)行解析,協(xié)議格式如下:
首先我們需要知道數(shù)據(jù)在物理層,數(shù)據(jù)鏈路層是以二進(jìn)制進(jìn)行傳遞的,而在應(yīng)用層是以16進(jìn)制字節(jié)流進(jìn)行傳輸?shù)摹?/p>
第一個(gè)字節(jié):
FIN:1位,用于描述消息是否結(jié)束,如果為1則該消息為消息尾部,如果為零則還有后續(xù)數(shù)據(jù)包;
RSV1,RSV2,RSV3:各1位,用于擴(kuò)展定義的,如果沒(méi)有擴(kuò)展約定的情況則必須為0
OPCODE:4位,用于表示消息接收類型,如果接收到未知的opcode,接收端必須關(guān)閉連接。長(zhǎng)連接探活包就是這里標(biāo)識(shí)的。
OPCODE定義的范圍:
0x0表示附加數(shù)據(jù)幀
0x1表示文本數(shù)據(jù)幀
0x2表示二進(jìn)制數(shù)據(jù)幀
0x3-7暫時(shí)無(wú)定義,為以后的非控制幀保留
0x8表示連接關(guān)閉
0x9表示ping
0xA表示pong
0xB-F暫時(shí)無(wú)定義,為以后的控制幀保留
第二個(gè)字節(jié)以及以后字節(jié):
或者
MASK:1位,用于標(biāo)識(shí)PayloadData是否經(jīng)過(guò)掩碼處理,客戶端發(fā)出的數(shù)據(jù)幀需要進(jìn)行掩碼處理,所以此位是1。數(shù)據(jù)需要解碼。
Payload length === x,如果
如果x值在0-125,則是payload的真實(shí)長(zhǎng)度。
如果x值是126,則后面2個(gè)字節(jié)形成的16位無(wú)符號(hào)整型數(shù)的值是payload的真實(shí)長(zhǎng)度。
如果x值是127,則后面8個(gè)字節(jié)形成的64位無(wú)符號(hào)整型數(shù)的值是payload的真實(shí)長(zhǎng)度。
此外,如果payload length占用了多個(gè)字節(jié)的話,payload length的二進(jìn)制表達(dá)采用網(wǎng)絡(luò)序(big endian,重要的位在前)。
舉例抓到客戶端返回包:
上圖是客戶端發(fā)送給服務(wù)端的數(shù)據(jù)包,其中PayloadData的長(zhǎng)度為二進(jìn)制:01111110——>十進(jìn)制:126;如果值是126,則后面2個(gè)字節(jié)形成的16位無(wú)符號(hào)整型數(shù)的值是payload的真實(shí)長(zhǎng)度。也就是圈紅的十六進(jìn)制:00C1——>十進(jìn)制:193 byte。所以PayloadData的真實(shí)數(shù)據(jù)長(zhǎng)度是193 bytes;
根據(jù)我們的分析,客戶端到服務(wù)端數(shù)據(jù)包的websocket幀圖應(yīng)該為:
舉例抓到服務(wù)端返回包:========================================================
可以發(fā)現(xiàn)服務(wù)器發(fā)送給客戶端的數(shù)據(jù)包中第二個(gè)字節(jié)中MASK位為0,這說(shuō)明服務(wù)器發(fā)送的數(shù)據(jù)幀未經(jīng)過(guò)掩碼處理,這個(gè)我們從客戶端和服務(wù)端的數(shù)據(jù)包截圖中也可以發(fā)現(xiàn),客戶端的數(shù)據(jù)被加密處理,而服務(wù)端的數(shù)據(jù)則沒(méi)有。(如果服務(wù)器收到客戶端發(fā)送的未經(jīng)掩碼處理的數(shù)據(jù)包,則會(huì)自動(dòng)斷開(kāi)連接;反之,如果客戶端收到了服務(wù)端發(fā)送的經(jīng)過(guò)掩碼處理的數(shù)據(jù)包,也會(huì)自動(dòng)斷開(kāi)連接)。
根據(jù)我們的分析,服務(wù)端到客戶端數(shù)據(jù)包的websocket幀圖應(yīng)該為:
====保活數(shù)據(jù)包ping/pong + TCP-ACK===============
-------------------------------------------------------------------------------------------------------------------------------------------
詳細(xì)分析:
WebSocket的ping包總長(zhǎng)度2個(gè)字節(jié);
WebSocket的Pong包總長(zhǎng)度6個(gè)字節(jié),包括4個(gè)字節(jié)的
而一個(gè)ping包WireShark抓包的Length總長(zhǎng)度為56個(gè)字節(jié)。其中WebSocket包長(zhǎng)度2字節(jié);TCP頭20字節(jié);IP頭20字節(jié);以太網(wǎng)幀長(zhǎng)度14個(gè)字節(jié);
TCP頭20字節(jié):
IPV4頭20字節(jié):
以太網(wǎng)幀頭14字節(jié):
目的/源MAC地址共計(jì)12字節(jié),類型2字節(jié)。共計(jì)14字節(jié)。
TCP ACK 確認(rèn)包:
Seq每次+2 說(shuō)明WebSocket的2字節(jié)ping數(shù)據(jù)包發(fā)送成功,Ack每次+6說(shuō)明成功接收了WebSocket的6字節(jié)Pong回復(fù)包。
捕獲WebSocket包
關(guān)于掩碼:
=======客戶端加密和服務(wù)端數(shù)據(jù)不加密,抓包區(qū)別明顯==========
看客戶端有掩碼的數(shù)據(jù) 服務(wù)端無(wú)掩碼的數(shù)據(jù)
掩碼算法了解
掩碼鍵(Masking-key)是由客戶端挑選出來(lái)的32位的隨機(jī)數(shù)。掩碼操作不會(huì)影響數(shù)據(jù)載荷的長(zhǎng)度。掩碼、反掩碼操作都采用如下算法:
首先,假設(shè):
original-octet-i:為原始數(shù)據(jù)的第i字節(jié)。
transformed-octet-i:為轉(zhuǎn)換后的數(shù)據(jù)的第i字節(jié)。
j:為i mod 4的結(jié)果。
masking-key-octet-j:為mask key第j字節(jié)。
算法描述為: original-octet-i 與 masking-key-octet-j 異或后,得到 transformed-octet-i。
掩碼的誕生---------
WebSocket協(xié)議中,數(shù)據(jù)掩碼的作用是增強(qiáng)協(xié)議的安全性。但數(shù)據(jù)掩碼并不是為了保護(hù)數(shù)據(jù)本身,因?yàn)樗惴ū旧硎枪_(kāi)的,運(yùn)算也不復(fù)雜。除了加密通道本身,似乎沒(méi)有太多有效的保護(hù)通信安全的辦法。
那么為什么還要引入掩碼計(jì)算呢,除了增加計(jì)算機(jī)器的運(yùn)算量外似乎并沒(méi)有太多的收益(這也是不少同學(xué)疑惑的點(diǎn))。
答案還是兩個(gè)字:安全。但并不是為了防止數(shù)據(jù)泄密,而是為了防止早期版本的協(xié)議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問(wèn)題。
1、代理緩存污染攻擊
下面摘自2010年關(guān)于安全的一段講話。其中提到了代理服務(wù)器在協(xié)議實(shí)現(xiàn)上的缺陷可能導(dǎo)致的安全問(wèn)題。猛擊出處。
“We show, empirically, that the current version of the WebSocket consent mechanism is vulnerable to proxy cache poisoning attacks. Even though the WebSocket handshake is based on HTTP, which should be understood by most network intermediaries, the handshake uses the esoteric “Upgrade” mechanism of HTTP [5]. In our experiment, we find that many proxies do not implement the Upgrade mechanism properly, which causes the handshake to succeed even though subsequent traffic over the socket will be misinterpreted by the proxy.”
[TALKING] Huang, L-S., Chen, E., Barth, A., Rescorla, E., and C.
Jackson, "Talking to Yourself for Fun and Profit", 2010,
在正式描述攻擊步驟之前,我們假設(shè)有如下參與者:
攻擊者、攻擊者自己控制的服務(wù)器(簡(jiǎn)稱“邪惡服務(wù)器”)、攻擊者偽造的資源(簡(jiǎn)稱“邪惡資源”)
受害者、受害者想要訪問(wèn)的資源(簡(jiǎn)稱“正義資源”)
受害者實(shí)際想要訪問(wèn)的服務(wù)器(簡(jiǎn)稱“正義服務(wù)器”)
中間代理服務(wù)器
攻擊步驟一:
攻擊者瀏覽器 向 邪惡服務(wù)器 發(fā)起WebSocket連接。根據(jù)前文,首先是一個(gè)協(xié)議升級(jí)請(qǐng)求。
協(xié)議升級(jí)請(qǐng)求 實(shí)際到達(dá) 代理服務(wù)器。
代理服務(wù)器 將協(xié)議升級(jí)請(qǐng)求轉(zhuǎn)發(fā)到 邪惡服務(wù)器。
邪惡服務(wù)器 同意連接,代理服務(wù)器 將響應(yīng)轉(zhuǎn)發(fā)給 攻擊者。
由于 upgrade 的實(shí)現(xiàn)上有缺陷,代理服務(wù)器以為之前轉(zhuǎn)發(fā)的是普通的HTTP消息。因此,當(dāng)協(xié)議服務(wù)器同意連接,代理服務(wù)器以為本次會(huì)話已經(jīng)結(jié)束。
攻擊步驟二:
攻擊者 在之前建立的連接上,通過(guò)WebSocket的接口向 邪惡服務(wù)器 發(fā)送數(shù)據(jù),且數(shù)據(jù)是精心構(gòu)造的HTTP格式的文本。其中包含了 正義資源 的地址,以及一個(gè)偽造的host(指向正義服務(wù)器)。(見(jiàn)后面報(bào)文)
請(qǐng)求到達(dá) 代理服務(wù)器 。雖然復(fù)用了之前的TCP連接,但 代理服務(wù)器 以為是新的HTTP請(qǐng)求。
代理服務(wù)器 向 邪惡服務(wù)器 請(qǐng)求 邪惡資源。
邪惡服務(wù)器 返回 邪惡資源。代理服務(wù)器 緩存住 邪惡資源(url是對(duì)的,但host是 正義服務(wù)器 的地址)。
到這里,受害者可以登場(chǎng)了:
受害者 通過(guò) 代理服務(wù)器 訪問(wèn) 正義服務(wù)器 的 正義資源。
代理服務(wù)器 檢查該資源的url、host,發(fā)現(xiàn)本地有一份緩存(偽造的)。
代理服務(wù)器 將 邪惡資源 返回給 受害者。
受害者 卒!
附:前面提到的精心構(gòu)造的“HTTP請(qǐng)求報(bào)文”。
2、當(dāng)前解決方案
最初的提案是對(duì)數(shù)據(jù)進(jìn)行加密處理。基于安全、效率的考慮,最終采用了折中的方案:對(duì)數(shù)據(jù)載荷進(jìn)行掩碼處理。
需要注意的是,這里只是限制了瀏覽器對(duì)數(shù)據(jù)載荷進(jìn)行掩碼處理,但是壞人完全可以實(shí)現(xiàn)自己的WebSocket客戶端、服務(wù)端,不按規(guī)則來(lái),攻擊可以照常進(jìn)行。
但是對(duì)瀏覽器加上這個(gè)限制后,可以大大增加攻擊的難度,以及攻擊的影響范圍。如果沒(méi)有這個(gè)限制,只需要在網(wǎng)上放個(gè)釣魚網(wǎng)站騙人去訪問(wèn),一下子就可以在短時(shí)間內(nèi)展開(kāi)大范圍的攻擊。
總結(jié):
WebSocket 是一個(gè)獨(dú)立的基于 TCP 的協(xié)議,它與 HTTP 之間的唯一關(guān)系就是它的握手請(qǐng)求可以作為一個(gè)升級(jí)請(qǐng)求(Upgrade request)經(jīng)由 HTTP 服務(wù)器解釋。再嚴(yán)謹(jǐn)一點(diǎn):WebSocket是一個(gè)網(wǎng)絡(luò)通訊協(xié)議, 只要理解上面的數(shù)據(jù)幀格式和握手流程, 都可以完成基于websokect的即時(shí)通訊。
-------請(qǐng)關(guān)注原著,感謝!-------------------------
博客園 https://www.cnblogs.com/plokmju/p/okhttp_weisocket.html
CSDN https://blog.csdn.net/u014252478/article/details/84380643
CSDN https://blog.csdn.net/xiongping_/article/details/47746953
搜狐 https://www.sohu.com/a/227600866_472869
總結(jié)
以上是生活随笔為你收集整理的WebSocket协议理解-数据包格式解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 寻求神谕的词语:谈海日寒诗集《空山集》
- 下一篇: 天融信防火墙NGFW4000,无法进入w