中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

WebSocket協(xié)議深入探究

2018-07-20    來源:編程學習網(wǎng)

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

一、內(nèi)容概覽

WebSocket的出現(xiàn),使得瀏覽器具備了實時雙向通信的能力。本文由淺入深,介紹了WebSocket如何建立連接、交換數(shù)據(jù)的細節(jié),以及數(shù)據(jù)幀的格式。此外,還簡要介紹了針對WebSocket的安全攻擊,以及協(xié)議是如何抵御類似攻擊的。

二、什么是WebSocket

HTML5開始提供的一種瀏覽器與服務(wù)器進行全雙工通訊的網(wǎng)絡(luò)技術(shù),屬于應(yīng)用層協(xié)議。它基于TCP傳輸協(xié)議,并復(fù)用HTTP的握手通道。

對大部分web開發(fā)者來說,上面這段描述有點枯燥,其實只要記住幾點:

  1. WebSocket可以在瀏覽器里使用
  2. 支持雙向通信
  3. 使用很簡單

1、有哪些優(yōu)點

說到優(yōu)點,這里的對比參照物是HTTP協(xié)議,概括地說就是:支持雙向通信,更靈活,更高效,可擴展性更好。

  1. 支持雙向通信,實時性更強。
  2. 更好的二進制支持。
  3. 較少的控制開銷。連接創(chuàng)建后,ws客戶端、服務(wù)端進行數(shù)據(jù)交換時,協(xié)議控制的數(shù)據(jù)包頭部較小。在不包含頭部的情況下,服務(wù)端到客戶端的包頭只有2~10字節(jié)(取決于數(shù)據(jù)包長度),客戶端到服務(wù)端的的話,需要加上額外的4字節(jié)的掩碼。而HTTP協(xié)議每次通信都需要攜帶完整的頭部。
  4. 支持擴展。ws協(xié)議定義了擴展,用戶可以擴展協(xié)議,或者實現(xiàn)自定義的子協(xié)議。(比如支持自定義壓縮算法等)

對于后面兩點,沒有研究過WebSocket協(xié)議規(guī)范的同學可能理解起來不夠直觀,但不影響對WebSocket的學習和使用。

2、需要學習哪些東西

對網(wǎng)絡(luò)應(yīng)用層協(xié)議的學習來說,最重要的往往就是 連接建立過程 、 數(shù)據(jù)交換教程 。當然,數(shù)據(jù)的格式是逃不掉的,因為它直接決定了協(xié)議本身的能力。好的數(shù)據(jù)格式能讓協(xié)議更高效、擴展性更好。

下文主要圍繞下面幾點展開:

  1. 如何建立連接
  2. 如何交換數(shù)據(jù)
  3. 數(shù)據(jù)幀格式
  4. 如何維持連接

三、入門例子

在正式介紹協(xié)議細節(jié)前,先來看一個簡單的例子,有個直觀感受。例子包括了WebSocket服務(wù)端、WebSocket客戶端(網(wǎng)頁端)。完整代碼可以在 這里 找到。

這里服務(wù)端用了 ws 這個庫。相比大家熟悉的 socket.io , ws 實現(xiàn)更輕量,更適合學習的目的。

1、服務(wù)端

代碼如下,監(jiān)聽8080端口。當有新的連接請求到達時,打印日志,同時向客戶端發(fā)送消息。當收到到來自客戶端的消息時,同樣打印日志。

var app = require('express')();
var server = require('http').Server(app);
var WebSocket = require('ws');
var wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
    console.log('server: receive connection.');
    ws.on('message', function incoming(message) {
        console.log('server: received: %s', message);
    });
    ws.send('world');
});
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});
app.listen(3000);

2、客戶端

代碼如下,向8080端口發(fā)起WebSocket連接。連接建立后,打印日志,同時向服務(wù)端發(fā)送消息。接收到來自服務(wù)端的消息后,同樣打印日志。

<script>
  var ws = new WebSocket('ws://localhost:8080');
  ws.onopen = function () {
    console.log('ws onopen');
    ws.send('from client: hello');
  };
  ws.onmessage = function (e) {
    console.log('ws onmessage');
    console.log('from server: ' + e.data);
  };
</script>

3、運行結(jié)果

可分別查看服務(wù)端、客戶端的日志,這里不展開。

服務(wù)端輸出:

server: receive connection.
server: received hello

客戶端輸出:

client: ws connection is open
client: received world

四、如何建立連接

前面提到,WebSocket復(fù)用了HTTP的握手通道。具體指的是,客戶端通過HTTP請求與WebSocket服務(wù)端協(xié)商升級協(xié)議。協(xié)議升級完成后,后續(xù)的數(shù)據(jù)交換則遵照WebSocket的協(xié)議。

1、客戶端:申請協(xié)議升級

首先,客戶端發(fā)起協(xié)議升級請求?梢钥吹,采用的是標準的HTTP報文格式,且只支持 GET 方法。

GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==

重點請求首部意義如下:

  • Connection: Upgrade :表示要升級協(xié)議
  • Upgrade: websocket :表示要升級到websocket協(xié)議。
  • Sec-WebSocket-Version: 13 :表示websocket的版本。如果服務(wù)端不支持該版本,需要返回一個 Sec-WebSocket-Version header,里面包含服務(wù)端支持的版本號。
  • Sec-WebSocket-Key :與后面服務(wù)端響應(yīng)首部的 Sec-WebSocket-Accept 是配套的,提供基本的防護,比如惡意的連接,或者無意的連接。

注意,上面請求省略了部分非重點請求首部。由于是標準的HTTP請求,類似Host、Origin、Cookie等請求首部會照常發(fā)送。在握手階段,可以通過相關(guān)請求首部進行 安全限制、權(quán)限校驗等。

2、服務(wù)端:響應(yīng)協(xié)議升級

服務(wù)端返回內(nèi)容如下,狀態(tài)代碼 101 表示協(xié)議切換。到此完成協(xié)議升級,后續(xù)的數(shù)據(jù)交互都按照新的協(xié)議來。

HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

備注:每個header都以 \r\n 結(jié)尾,并且最后一行加上一個額外的空行 \r\n 。此外,服務(wù)端回應(yīng)的HTTP狀態(tài)碼只能在握手階段使用。過了握手階段后,就只能采用特定的錯誤碼。

3、Sec-WebSocket-Accept的計算

Sec-WebSocket-Accept 根據(jù)客戶端請求首部的 Sec-WebSocket-Key 計算出來。

計算公式為:

  1. 將 Sec-WebSocket-Key 跟 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接。
  2. 通過SHA1計算出摘要,并轉(zhuǎn)成base64字符串。

偽代碼如下:

>toBase64( sha1( Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )

驗證下前面的返回結(jié)果:

const crypto = require('crypto');
const magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const secWebSocketKey = 'w4v7O6xFTi36lq3RNcgctw==';
let secWebSocketAccept = crypto.createHash('sha1')
    .update(secWebSocketKey + magic)
    .digest('base64');
console.log(secWebSocketAccept);
// Oy4NRAQ13jhfONC7bP8dTKb4PTU=

五、數(shù)據(jù)幀格式

客戶端、服務(wù)端數(shù)據(jù)的交換,離不開數(shù)據(jù)幀格式的定義。因此,在實際講解數(shù)據(jù)交換之前,我們先來看下WebSocket的數(shù)據(jù)幀格式。

WebSocket客戶端、服務(wù)端通信的最小單位是幀(frame),由1個或多個幀組成一條完整的消息(message)。

  1. 發(fā)送端:將消息切割成多個幀,并發(fā)送給服務(wù)端;
  2. 接收端:接收消息幀,并將關(guān)聯(lián)的幀重新組裝成完整的消息;

本節(jié)的重點,就是講解 數(shù)據(jù)幀 的格式。詳細定義可參考 RFC6455 5.2節(jié) 。

1、數(shù)據(jù)幀格式概覽

下面給出了WebSocket數(shù)據(jù)幀的統(tǒng)一格式。熟悉TCP/IP協(xié)議的同學對這樣的圖應(yīng)該不陌生。

  1. 從左到右,單位是比特。比如 FIN 、 RSV1 各占據(jù)1比特, opcode 占據(jù)4比特。
  2. 內(nèi)容包括了標識、操作代碼、掩碼、數(shù)據(jù)、數(shù)據(jù)長度等。(下一小節(jié)會展開)
0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+

2、數(shù)據(jù)幀格式詳解

針對前面的格式概覽圖,這里逐個字段進行講解,如有不清楚之處,可參考協(xié)議規(guī)范,或留言交流。

FIN:1個比特。

如果是1,表示這是消息(message)的最后一個分片(fragment),如果是0,表示不是是消息(message)的最后一個分片(fragment)。

RSV1, RSV2, RSV3:各占1個比特。

一般情況下全為0。當客戶端、服務(wù)端協(xié)商采用WebSocket擴展時,這三個標志位可以非0,且值的含義由擴展進行定義。如果出現(xiàn)非零的值,且并沒有采用WebSocket擴展,連接出錯。

Opcode: 4個比特。

操作代碼,Opcode的值決定了應(yīng)該如何解析后續(xù)的數(shù)據(jù)載荷(data payload)。如果操作代碼是不認識的,那么接收端應(yīng)該斷開連接(fail the connection)?蛇x的操作代碼如下:

  • %x0:表示一個延續(xù)幀。當Opcode為0時,表示本次數(shù)據(jù)傳輸采用了數(shù)據(jù)分片,當前收到的數(shù)據(jù)幀為其中一個數(shù)據(jù)分片。
  • %x1:表示這是一個文本幀(frame)
  • %x2:表示這是一個二進制幀(frame)
  • %x3-7:保留的操作代碼,用于后續(xù)定義的非控制幀。
  • %x8:表示連接斷開。
  • %x8:表示這是一個ping操作。
  • %xA:表示這是一個pong操作。
  • %xB-F:保留的操作代碼,用于后續(xù)定義的控制幀。

Mask: 1個比特。

表示是否要對數(shù)據(jù)載荷進行掩碼操作。從客戶端向服務(wù)端發(fā)送數(shù)據(jù)時,需要對數(shù)據(jù)進行掩碼操作;從服務(wù)端向客戶端發(fā)送數(shù)據(jù)時,不需要對數(shù)據(jù)進行掩碼操作。

如果服務(wù)端接收到的數(shù)據(jù)沒有進行過掩碼操作,服務(wù)端需要斷開連接。

如果Mask是1,那么在Masking-key中會定義一個掩碼鍵(masking key),并用這個掩碼鍵來對數(shù)據(jù)載荷進行反掩碼。所有客戶端發(fā)送到服務(wù)端的數(shù)據(jù)幀,Mask都是1。

掩碼的算法、用途在下一小節(jié)講解。

Payload length:數(shù)據(jù)載荷的長度,單位是字節(jié)。為7位,或7+16位,或1+64位。

假設(shè)數(shù)Payload length === x,如果

  • x為0~126:數(shù)據(jù)的長度為x字節(jié)。
  • x為126:后續(xù)2個字節(jié)代表一個16位的無符號整數(shù),該無符號整數(shù)的值為數(shù)據(jù)的長度。
  • x為127:后續(xù)8個字節(jié)代表一個64位的無符號整數(shù)(最高位為0),該無符號整數(shù)的值為數(shù)據(jù)的長度。

此外,如果payload length占用了多個字節(jié)的話,payload length的二進制表達采用網(wǎng)絡(luò)序(big endian,重要的位在前)。

Masking-key:0或4字節(jié)(32位)

所有從客戶端傳送到服務(wù)端的數(shù)據(jù)幀,數(shù)據(jù)載荷都進行了掩碼操作,Mask為1,且攜帶了4字節(jié)的Masking-key。如果Mask為0,則沒有Masking-key。

備注:載荷數(shù)據(jù)的長度,不包括mask key的長度。

Payload data:(x+y) 字節(jié)

載荷數(shù)據(jù):包括了擴展數(shù)據(jù)、應(yīng)用數(shù)據(jù)。其中,擴展數(shù)據(jù)x字節(jié),應(yīng)用數(shù)據(jù)y字節(jié)。

擴展數(shù)據(jù):如果沒有協(xié)商使用擴展的話,擴展數(shù)據(jù)數(shù)據(jù)為0字節(jié)。所有的擴展都必須聲明擴展數(shù)據(jù)的長度,或者可以如何計算出擴展數(shù)據(jù)的長度。此外,擴展如何使用必須在握手階段就協(xié)商好。如果擴展數(shù)據(jù)存在,那么載荷數(shù)據(jù)長度必須將擴展數(shù)據(jù)的長度包含在內(nèi)。

應(yīng)用數(shù)據(jù):任意的應(yīng)用數(shù)據(jù),在擴展數(shù)據(jù)之后(如果存在擴展數(shù)據(jù)),占據(jù)了數(shù)據(jù)幀剩余的位置。載荷數(shù)據(jù)長度 減去 擴展數(shù)據(jù)長度,就得到應(yīng)用數(shù)據(jù)的長度。

3、掩碼算法

掩碼鍵(Masking-key)是由客戶端挑選出來的32位的隨機數(shù)。掩碼操作不會影響數(shù)據(jù)載荷的長度。掩碼、反掩碼操作都采用如下算法:

首先,假設(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。

j = i MOD 4

六、數(shù)據(jù)傳遞

一旦WebSocket客戶端、服務(wù)端建立連接后,后續(xù)的操作都是基于數(shù)據(jù)幀的傳遞。

WebSocket根據(jù) opcode 來區(qū)分操作的類型。比如 0x8 表示斷開連接, 0x0 - 0x2 表示數(shù)據(jù)交互。

1、數(shù)據(jù)分片

WebSocket的每條消息可能被切分成多個數(shù)據(jù)幀。當WebSocket的接收方收到一個數(shù)據(jù)幀時,會根據(jù) FIN 的值來判斷,是否已經(jīng)收到消息的最后一個數(shù)據(jù)幀。

FIN=1表示當前數(shù)據(jù)幀為消息的最后一個數(shù)據(jù)幀,此時接收方已經(jīng)收到完整的消息,可以對消息進行處理。FIN=0,則接收方還需要繼續(xù)監(jiān)聽接收其余的數(shù)據(jù)幀。

此外, opcode 在數(shù)據(jù)交換的場景下,表示的是數(shù)據(jù)的類型。 0x01 表示文本, 0x02 表示二進制。而 0x00 比較特殊,表示延續(xù)幀(continuation frame),顧名思義,就是完整消息對應(yīng)的數(shù)據(jù)幀還沒接收完。

2、數(shù)據(jù)分片例子

直接看例子更形象些。下面例子來自 MDN ,可以很好地演示數(shù)據(jù)的分片?蛻舳讼蚍⻊(wù)端兩次發(fā)送消息,服務(wù)端收到消息后回應(yīng)客戶端,這里主要看客戶端往服務(wù)端發(fā)送的消息。

第一條消息

FIN=1, 表示是當前消息的最后一個數(shù)據(jù)幀。服務(wù)端收到當前數(shù)據(jù)幀后,可以處理消息。opcode=0x1,表示客戶端發(fā)送的是文本類型。

第二條消息

  1. FIN=0,opcode=0x1,表示發(fā)送的是文本類型,且消息還沒發(fā)送完成,還有后續(xù)的數(shù)據(jù)幀。
  2. FIN=0,opcode=0x0,表示消息還沒發(fā)送完成,還有后續(xù)的數(shù)據(jù)幀,當前的數(shù)據(jù)幀需要接在上一條數(shù)據(jù)幀之后。
  3. FIN=1,opcode=0x0,表示消息已經(jīng)發(fā)送完成,沒有后續(xù)的數(shù)據(jù)幀,當前的數(shù)據(jù)幀需要接在上一條數(shù)據(jù)幀之后。服務(wù)端可以將關(guān)聯(lián)的數(shù)據(jù)幀組裝成完整的消息。
Client: FIN=1, opcode=0x1, msg="hello"
Server: (process complete message immediately) Hi.
Client: FIN=0, opcode=0x1, msg="and a"
Server: (listening, new message containing text started)
Client: FIN=0, opcode=0x0, msg="happy new"
Server: (listening, payload concatenated to previous message)
Client: FIN=1, opcode=0x0, msg="year!"
Server: (process complete message) Happy new year to you too!

七、連接保持+心跳

WebSocket為了保持客戶端、服務(wù)端的實時雙向通信,需要確保客戶端、服務(wù)端之間的TCP通道保持連接沒有斷開。然而,對于長時間沒有數(shù)據(jù)往來的連接,如果依舊長時間保持著,可能會浪費包括的連接資源。

但不排除有些場景,客戶端、服務(wù)端雖然長時間沒有數(shù)據(jù)往來,但仍需要保持連接。這個時候,可以采用心跳來實現(xiàn)。

  • 發(fā)送方->接收方:ping
  • 接收方->發(fā)送方:pong

ping、pong的操作,對應(yīng)的是WebSocket的兩個控制幀, opcode 分別是 0x9 、 0xA 。

舉例,WebSocket服務(wù)端向客戶端發(fā)送ping,只需要如下代碼(采用 ws 模塊)

ws.ping('', false, true);

八、Sec-WebSocket-Key/Accept的作用

前面提到了, Sec-WebSocket-Key/Sec-WebSocket-Accept 在主要作用在于提供基礎(chǔ)的防護,減少惡意連接、意外連接。

作用大致歸納如下:

  1. 避免服務(wù)端收到非法的websocket連接(比如http客戶端不小心請求連接websocket服務(wù),此時服務(wù)端可以直接拒絕連接)
  2. 確保服務(wù)端理解websocket連接。因為ws握手階段采用的是http協(xié)議,因此可能ws連接是被一個http服務(wù)器處理并返回的,此時客戶端可以通過Sec-WebSocket-Key來確保服務(wù)端認識ws協(xié)議。(并非百分百保險,比如總是存在那么些無聊的http服務(wù)器,光處理Sec-WebSocket-Key,但并沒有實現(xiàn)ws協(xié)議。。。)
  3. 用瀏覽器里發(fā)起ajax請求,設(shè)置header時,Sec-WebSocket-Key以及其他相關(guān)的header是被禁止的。這樣可以避免客戶端發(fā)送ajax請求時,意外請求協(xié)議升級(websocket upgrade)
  4. 可以防止反向代理(不理解ws協(xié)議)返回錯誤的數(shù)據(jù)。比如反向代理前后收到兩次ws連接的升級請求,反向代理把第一次請求的返回給cache住,然后第二次請求到來時直接把cache住的請求給返回(無意義的返回)。
  5. Sec-WebSocket-Key主要目的并不是確保數(shù)據(jù)的安全性,因為Sec-WebSocket-Key、Sec-WebSocket-Accept的轉(zhuǎn)換計算公式是公開的,而且非常簡單,最主要的作用是預(yù)防一些常見的意外情況(非故意的)。

強調(diào):Sec-WebSocket-Key/Sec-WebSocket-Accept 的換算,只能帶來基本的保障,但連接是否安全、數(shù)據(jù)是否安全、客戶端/服務(wù)端是否合法的 ws客戶端、ws服務(wù)端,其實并沒有實際性的保證。

九、數(shù)據(jù)掩碼的作用

WebSocket協(xié)議中,數(shù)據(jù)掩碼的作用是增強協(xié)議的安全性。但數(shù)據(jù)掩碼并不是為了保護數(shù)據(jù)本身,因為算法本身是公開的,運算也不復(fù)雜。除了加密通道本身,似乎沒有太多有效的保護通信安全的辦法。

那么為什么還要引入掩碼計算呢,除了增加計算機器的運算量外似乎并沒有太多的收益(這也是不少同學疑惑的點)。

答案還是兩個字: 安全 。但并不是為了防止數(shù)據(jù)泄密,而是為了防止早期版本的協(xié)議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題。

1、代理緩存污染攻擊

下面摘自2010年關(guān)于安全的一段講話。其中提到了代理服務(wù)器在協(xié)議實現(xià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ù)器(簡稱“邪惡服務(wù)器”)、攻擊者偽造的資源(簡稱“邪惡資源”)
  • 受害者、受害者想要訪問的資源(簡稱“正義資源”)
  • 受害者實際想要訪問的服務(wù)器(簡稱“正義服務(wù)器”)
  • 中間代理服務(wù)器

攻擊步驟一:

  1. 攻擊者 瀏覽器 向 邪惡服務(wù)器 發(fā)起WebSocket連接。根據(jù)前文,首先是一個協(xié)議升級請求。
  2. 協(xié)議升級請求 實際到達 代理服務(wù)器 。
  3. 代理服務(wù)器 將協(xié)議升級請求轉(zhuǎn)發(fā)到 邪惡服務(wù)器 。
  4. 邪惡服務(wù)器 同意連接, 代理服務(wù)器 將響應(yīng)轉(zhuǎn)發(fā)給 攻擊者 。

由于 upgrade 的實現(xiàn)上有缺陷, 代理服務(wù)器 以為之前轉(zhuǎn)發(fā)的是普通的HTTP消息。因此,當 協(xié)議服務(wù)器 同意連接, 代理服務(wù)器 以為本次會話已經(jīng)結(jié)束。

攻擊步驟二:

  1. 攻擊者 在之前建立的連接上,通過WebSocket的接口向 邪惡服務(wù)器 發(fā)送數(shù)據(jù),且數(shù)據(jù)是精心構(gòu)造的HTTP格式的文本。其中包含了 正義資源 的地址,以及一個偽造的host(指向 正義服務(wù)器 )。(見后面報文)
  2. 請求到達 代理服務(wù)器 。雖然復(fù)用了之前的TCP連接,但 代理服務(wù)器 以為是新的HTTP請求。
  3. 代理服務(wù)器邪惡服務(wù)器 請求 邪惡資源 。
  4. 邪惡服務(wù)器 返回 邪惡資源代理服務(wù)器 緩存住 邪惡資源 (url是對的,但host是 正義服務(wù)器 的地址)。

到這里,受害者可以登場了:

  1. 受害者 通過 代理服務(wù)器 訪問 正義服務(wù)器正義資源 。
  2. 代理服務(wù)器 檢查該資源的url、host,發(fā)現(xiàn)本地有一份緩存(偽造的)。
  3. 代理服務(wù)器邪惡資源 返回給 受害者 。
  4. 受害者 卒。

附:前面提到的精心構(gòu)造的“HTTP請求報文”。

Client → Server:
POST /path/of/attackers/choice HTTP/1.1 Host: host-of-attackers-choice.com Sec-WebSocket-Key: <connection-key>
Server → Client:
HTTP/1.1 200 OK
Sec-WebSocket-Accept: <connection-key>

2、當前解決方案

最初的提案是對數(shù)據(jù)進行加密處理;诎踩⑿实目紤],最終采用了折中的方案:對數(shù)據(jù)載荷進行掩碼處理。

需要注意的是,這里只是限制了瀏覽器對數(shù)據(jù)載荷進行掩碼處理,但是壞人完全可以實現(xiàn)自己的WebSocket客戶端、服務(wù)端,不按規(guī)則來,攻擊可以照常進行。

但是對瀏覽器加上這個限制后,可以大大增加攻擊的難度,以及攻擊的影響范圍。如果沒有這個限制,只需要在網(wǎng)上放個釣魚網(wǎng)站騙人去訪問,一下子就可以在短時間內(nèi)展開大范圍的攻擊。

十、寫在后面

WebSocket可寫的東西還挺多,比如WebSocket擴展。客戶端、服務(wù)端之間是如何協(xié)商、使用擴展的。WebSocket擴展可以給協(xié)議本身增加很多能力和想象空間,比如數(shù)據(jù)的壓縮、加密,以及多路復(fù)用等。

篇幅所限,這里先不展開,感興趣的同學可以留言交流。文章如有錯漏,敬請指出。

 

來自:http://www.infoq.com/cn/articles/deep-in-websocket-protocol

 

標簽: http服務(wù)器 安全 代理服務(wù)器 代碼 服務(wù)器 開發(fā)者 權(quán)限 通信 網(wǎng)絡(luò)

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:新思路設(shè)計可視化大型微服務(wù)監(jiān)控系統(tǒng)

下一篇:10秒鐘,讓你的方法變?yōu)镽PC服務(wù)