2013-08-16 35 views
29

在1.3節的draft-ietf-hybi-thewebsocketprotocol-17「打開握手」,它描述Sec-WebSocket-Key如下:什麼是Sec-WebSocket-Key?

爲了證明握手被接收時,服務器必須採取的兩條信息和將它們結合起來,以形成響應。第一部分信息來自| Sec-WebSocket-Key |在客戶端的握手報頭字段:

Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 

對於該頭字段,服務器具有取的值(如存在於報頭字段,例如,base64編碼[RFC4648]版本減去開頭和結尾的空白) ,並以字符串形式將其與全局唯一標識符(GUID,[RFC4122])「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」連接起來,這不太可能被不理解WebSocket協議的網絡端點使用。然後在服務器的握手[FIPS.180-2.2002]中返回該串聯的SHA-1散列(160位),base64編碼(參見[RFC4648]的第4節)。

下面是我無法理解的事情:爲什麼不簡單地返回代碼101?如果正確使用Sec-WebSocket-Key是爲了安全,或者爲了證明他們可以處理websocket請求,那麼任何服務器都可以返回期望的密鑰,並假裝他們是WebSocket服務器。

回答

18

根據RFC 6455的WebSocket標準

first part

.. the server has to prove to the client that it received the 
client's WebSocket handshake, so that the server doesn't accept 
connections that are not WebSocket connections. This prevents an 
attacker from tricking a WebSocket server by sending it carefully 
crafted packets using XMLHttpRequest [XMLHttpRequest] or a form 
submission. 

... 
For this header field, the server has to take the value (as present 
in the header field, e.g., the base64-encoded [RFC4648] version minus 
any leading and trailing whitespace) and concatenate this with the 
Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA- 
95CA-C5AB0DC85B11" in string form, which is unlikely to be used by 
network endpoints that do not understand the WebSocket Protocol. 

second part

The |Sec-WebSocket-Key| header field is used in the WebSocket opening 
handshake. It is sent from the client to the server to provide part 
of the information used by the server to prove that it received a 
valid WebSocket opening handshake. This helps ensure that the server 
does not accept connections from non-WebSocket clients (e.g., HTTP 
clients) that are being abused to send data to unsuspecting WebSocket 
servers. 

所以,在標準中指定的GUID值,它是不可能(可能的話,以非常小的概率放置)不知道Websockets的服務器將會我使用它。它不提供任何安全性(安全的websockets - wss:// - 確實),它只是確保服務器理解websockets協議。

真的,正如你所說的,如果你知道websockets(這是要檢查的內容),你可以通過發送正確的響應,假裝是一個websocket服務器。但是,如果你不能正確行事(例如正確的表單框架),它將被視爲違反協議。其實,你可以寫一個不正確的websocket服務器,但是沒有太多用處。

而另一個目的是防止客戶意外地請求websockets升級不期望它(例如,通過手動添加相應的標題,然後希望別人)。 Sec-WebSocket-Key和其他相關頭文件禁止在瀏覽器中使用setRequestHeader方法進行設置。

+0

這是真的一些請求頭字段不能從XMLHttpRequest中的JavaScript修改,所以從瀏覽器的方式被阻止?但是如果有一個瀏覽器(可能是早期版本)可以修改Sec-websocket-key字段?或者如果請求是由程序發送來模擬瀏覽器,那麼您可以完全自行構建請求標頭,因此使Sec-WebSocket-Key無意義? – user2003548

+2

請重新閱讀我的答案。即使您編寫的服務器或客戶端將模擬正確的升級請求,您也會在知道Websockest協議*存在*的情況下故意這樣做。 Sec-WebSocket-Key用於過濾_unintended_請求。如果您擔心安全 - 請使用安全的網絡套接字。 –

+0

所以這個協議是基於ppl設計的,通常會使用它,如果面對一個惡意的軟件編寫器,它會像普通的http一樣搞砸了,我知道它是正確的嗎? – user2003548

1

我傾向於同意。

如果客戶端忽略了Sec-WebSocket-Accept頭的值,那麼重要性就不會改變。

爲什麼?因爲服務器沒有通過這種計算來證明任何事情(除了它有代碼來進行計算)。它唯一排除的僅僅是一個服務器,它只是回覆一個罐頭響應。

標題交換(例如,使用固定的'key'和'accept'值)已經足以排除任何意外的連接,這些連接至少不會成爲WebSocket服務器;如果它正在嘗試,那麼它做這個計算的要求不會阻礙它的成功。

的RFC聲稱:

」 ..服務器必須證明其收到的 客戶端的WebSocket的握手,讓服務器不接受未WebSocket連接 連接的客戶端。 「

和:

「這有助於確保服務器不會接受來自非的WebSocket客戶端的連接。」

無論這些說法毫無意義。服務器從來不是拒絕連接的服務器,因爲它是計算散列的那個,而不是檢查它的那個。

如果神奇的GUID不是固定的,而是客戶端和服務器之間的共享祕密,那麼這種交換會有所幫助。在這種情況下,交換將允許服務器向客戶證明它擁有共享的祕密而不會泄露它。

6

主要用於緩存清除。

想象一下,透過反向代理服務器觀看HTTP流量。如果它不瞭解WS,它可能會錯誤地緩存WS握手,並將無用的101回覆給下一個客戶端。

使用隨機數(密鑰)並要求基本的挑戰 - 響應而非特定於WS確保服務器真正理解這是WS握手,並反過來告訴客戶端服務器確實會在端口上偵聽。緩存反向代理永遠不會「錯誤地」實現散列邏輯。

相關問題