proxyが通らないよ!と言うtweetやら何やらが多く出回っていますが、それに関して。
結論から言うと、大抵の場合、通ります。
hybiでの仕様では、SPEC-02位からちゃんと記述がありますが、それ以前もchrome(chromium)では、ちゃんとproxyを考慮した作りになっていました。
パケットの流れとしては、以下の通り
ブラウザ->proxy
CONNECT hoge.com:80 HTTP/1.1
Host: hoge.com
Proxy-Connection: keep-alive
proxy->ブラウザ
HTTP/1.1 200 Connection established
ブラウザ->proxy->WebSocket Server
GET /fuga HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: hoge.com
Origin: http://hoge.com
Sec-WebSocket-Key1: 4 29 " 43b Q8 9 30 9
Sec-WebSocket-Key2: 3n 110913 6 25y
.?4.Q...
WebSocket Server->proxy->ブラウザ
HTTP/1.1 101 WebSocket Protocol Handshakeただ、proxyによっては通らないものがあるのも事実です。
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Location: ws://hoge.com/fuga
Sec-WebSocket-Origin: http://hoge.com
....Vz.3L ...r...
initial handshakeのGET methodについているbodyが原因です。(イケてない仕様だと思うのですが…)
見ての通り、initial handshake requestには、bodyに8byteのdata(Sec-WebSocket-Key3相当)が付加されていますが、ヘッダにContent-Length及びTransfer-Encodingは付いていません。
この場合、RFC2616に対して、明らかに不正なパケットとなります。(参照: http://www.studyinghttp.net/header#Content-Length)
また、Upgrade headerについての扱いをどう見るか、ですが、(参照: http://www.studyinghttp.net/header#Upgrade)
initial handshake時のrequest packetにおけるUpgrade headerについては、まだUpgradeされていないと考えるべきだと思っています。
つまり、
GET /fuga HTTP/1.1
Upgrade: WebSocket
は、まだWebSocket ProtocolにUpgradeされておらず、HTTPの仕様に縛られるべきだと思うのです。
その為、Content-Length headerすら付けず、bodyに、8byteのdataを付加するようなpacketは、httpdとしても、proxyとしても扱いに困ります。
(例えば、Upgrade: WebSocketが付いたpacketは絶対にWebSocket Handshakeだ、と仮定したとすると、httpdおよびproxyは、bodyの8byteを読めるまでしばらく待っている必要があります。この場合、、bodyを付加せずheaderだけ投げつければ簡単にDoSが可能となります。例え、httpdおよびproxyがpoll timeoutなどを設けていたとしても)
以上のような理由で、proxy、httpdの設定によっては、handshake packetが捨てられる場合があります。
また、Windows版のブラウザでは、initial handshake requestが2 packetに分割して投げられます。
(Chrome, Safari, FireFox 4βで確認済)
ブラウザ->WebSocket Server
GET /fuga HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: hoge.com
Origin: http://hoge.com
Sec-WebSocket-Key1: 4 29 " 43b Q8 9 30 9
Sec-WebSocket-Key2: 3n 110913 6 25y
ブラウザ->WebSocket Server
まず、ヘッダ部分が送信され、数msおいてbody部分が送信される形です。.?4.Q...
この場合は特に、headerにContent-Lengthが付いていないこと、methodがGETであることからproxyやhttpdでは、2 packet目の8byteのdataは、本来どのようなpacketなのか判断が付かないことになります。(捨てるのが普通でしょう)
実際は、proxyに対して、CONNECT、keep-aliveしているので、proxyはpass-throughしてくれて、ちゃんとWebSocket Serverまで届きますが。
と、言うことで、基本的にはproxy透過だよ~っと覚えていてもらえば良いかと思います。
このあたりはSPEC-03以降でちゃんと定義されていると思いますが、現状のご報告まで。
ではでは。
あぁ、追記として。
Safariには、proxy設定とWebSocketの利用に関してBUGが存在します。(一応、レポートは送付しましたが、最近のSafariでは直ってるのかしら?)
企業内のネットワークに参加しているNote PC(持ち運ぶPC)などではよく起こると思うのですが、
- そのPCでproxyを利用する設定になっている(自動設定スクリプトなどを含む)
- proxyの無い環境に持っていく。(自動設定スクリプトだと、proxyを利用しない状況になる)
- WebSocketを利用したsiteへ赴く
- ブラウザクラーッシュ
0 件のコメント:
コメントを投稿