SSL リクエストは HTTP スニッファでいつも見えるとは限らない
Charles Web ProxyやFiddlerなどのHTTPスニッファはHTTPリクエストはもちろんHTTPSリクエストも中身は見えないながらもリクエスト自身は表示する、と思っていた。そうではないといことが今日分かった。
HTTPSでは、クライアント(ブラウザ)とサーバーがハンドシェイク(暗号鍵の交換)をしたあとは暗号で通信が行われる。暗号鍵の交換はリクエスト毎に行われるわけではなく、複数のリクエストに渡って同じ暗号鍵が使われる。Charles やFiddlerなどのプロキシ方式のHTTPスニッファは暗号化された中身を見ることができないので(なりすましもできるが、ここでは話の簡単のため触れない)、外側だけを見てHTTPSリクエストを判断しないといけない。外側、というのは暗号化されたSSLデータを運ぶ層、すなわちTCPということになる。
ここで問題なのは、一つのHTTPもしくはHTTPSリクエストは通常複数のTCPパケットに分割されるということである。一つのHTTP(S)リクエストがいくつのTCPパケットに分割されるかは、リクエストのサイズに依存していてリクエスト毎に違う。
一つのリクエストにいくつのTCPパケットを必要するかという情報は、リクエストのサイズという形でHTTP(S)リクエストのヘッダに格納してある。
普通のHTTPリクエストであれば、HTTPスニッファはデータの中身を読むことができるので、HTTPヘッダからリクエストサイズを取り出して、リクエストの終わりを判断することができる。
ところが、この技は内容が暗号化されているHTTPSでは使えない。例えば、連続する10個のTCPパケットが流れてきた場合、これが一つのHTTPSリクエストなのか二つのリクエストなのか、仮に二つとしても10個のパケットが二つのリクエストにどう割り振られているかというようなことは、パケットの中身が暗号化されているためHTTPスニッファには判断する術がない。HTTPスニッファにできるのは、せいぜいSSLのハンドシェイクを見張って(これは平文で行われる)それが一つのHTTPSリクエストの始まりだと判断するぐらいである。
Charles ProxyやFiddlerが実際にやっているのもこの程度のことらしく、HTTPSをこれらのスニッファで監視すると、あるSSLサーバーに対する最初のリクエストは表示するものの、そのリクエストは、実際には完了しているにも関わらず、決して完了とは表示されない。また、同じサーバーへの二度目のHTTPSリクエストは、スニッファには最初のリクエストの続きと認識されてしまうので、スニッファに表示されることはない。このようにして、実際には完了しているHTTPSリクエストが、スニッファには表示されないということが起こる。
HTTPSリクエストが起こっているかどうかを確実に知るためには、FireFoxのLive HTTP headersのようなブラウザープラグインタイプのスニッファを使う必要がある。このタイプのスニッファはブラウザが暗号を解読した後のデータを読むために、SSLにまつわる以上のような問題が起こることはない。
ここまで書いてきて思い出したが、あるパケットが「最後」のパケットとだと知らせるための方法がTCPにはちゃんと用意してある。HTTPSがリクエストの終わりにこの「最終パケット」を使えば、スニッファにもリクエストの終わりが判別できたのだが、実際にはそういう風にはなっていない。
クライアントとサーバーが最初に交換した暗号鍵を使い続ける限り両者間の通信は終わりでない、というのがリクエスト毎に最終パケットを使わない理由のようにも思えるが、確かなことは分からない。
Erlang ノードの相互接続
2つの Erlang ノードが互いに見えているのかどうかすら分からなかったときに、役にたったサイト。
Interconnecting Erlang Nodes | ejabberd
RAID10 構築
1. HDD のインストール
HDD は Maxtor Diamond Max SATA II/300 500GB (7200rpm, 16MB cache) x 4。
マザーボードは Gigabyte P35-DS3R。RAID 機能付きのマザーボードだが、マザーボードの RAID は使わない。
このマザーボードには SATA コントローラが2つ (Intel ICH9R と Gigabyte SATA2 chip)付いている。2つのコントローラに2つずつ HDD を接続する。IDE と違ってつなぐポートによるパフォーマンスの違いはないので、素直に SATAII0/1 (ICH9R) と GSATAII0/1 (Gigabyte SATA2) につないだ。
2. BIOS 設定
HDD をつないでPCを起動、Del キーを押して BIOS 画面に行く。
初期設定では SATA HDD は IDE 互換モードで動作するようになっている。これだと SATA の新しい機能(NCQ やホットスワップ)が使えず、パフォーマンスも落ちるので、BIOS で ACHI モードに切り替える。この設定は Integrated Peripherals メニューの下にある。コントローラが2つあるので、設定を変更する箇所も2つ。SATA RAID/AHCI Mode と Onboard SATA/IDE Ctrl Mode。どちらも ACHI に設定する。
ここで注意。ACHI は比較的新しい規格なので、最近のOSでないとサポートしていない。Windows だと Vista 以降。Linux はディストリビューションによっては Install CD がサポートしてない、つまりまったくインストールできない場合がある。Gentoo 2007.0 の minimum installer はエラーが出てだめだった。IDE 互換モードにすればインストールできるのだが、せっかくの新機能を無駄にしたくない。Gentoo はあきらめることにして、Ubuntu 7.10 にしたらうまくいった。
3. パーティション作成
RAID に組む前に、パーティションを切る必要がある。今回は以下のようにした。
Device Size Id System Note
/dev/sd?1 128MB fd Linux raid /boot RAID1 (active 2, backup 2)
/dev/sd?2 4GB fd Linux raid ルートパーティション RAID10
/dev/sd?3 4GB fd Linux raid ルートパーティションのバックアップ RAID10
/dev/sd?4 残り fd Linux raid 論理パーティションのための Extended partition
/dev/sd?5 4GB fd Linux raid swap RAID1 (active 2)
/dev/sd?6 残り fd Linux raid LVM2 で使用。RAID10
HDD が4台あるので、デバイスは /dev/sda, /dev/sdb, /dev/sdc, /dev/sdd の4つがある。
/boot のために /dev/sd?1 4つを RAID1 に組んだ。2つはアクティブ、残りの2つはスペアになる。
/dev/sd?2 はルートパーティション用。4GB のパーティション4つを RAID10 にするので、8GB の RAID デバイスとして見える。
/dev/sd?3 はルートパーティションのバックアップ用。sd?2 と同じく 4GB パーティションを RAID10 で、8GB の RAID デバイスになる。
/dev/sd?5 はスワップ。カーネル自身がスワップのストライピングをするので RAID0 にする必要はない。そこで、4つの 4GB パーティションを2つずつの RAID1 構成にして、両方をスワップとして指定した。
/dev/sd?6 は残りの領域すべて、およそ 450GB。LVM2 として、後で適当に割り振って使う。4つのパーティションを RAID10 にするので、900GB の RAID デバイスとして見える。
パーティションを作るのに Ubuntu installer の Partition Manager を使ったら、変更をセーブするときに「ルートパーティションが割り当てられていません」という警告が出て変更ができなかった。ルートには、RAID デバイスを当てるので、ここで物理パーティションにルートを割り当てたくない。が、それでは Partition Manager を終わることができないので、一時的に /dev/sda1 をルートということにした。
これでパーティションができたので、RAID の構成に進む。
4. RAID ディスク作成
Ubuntu Installer の Partition Manager からでも RAID の構成はできるが、RAID10 はサポートしてないので、それは手作業でやる必要がある。コマンドを調べるのが面倒だったので、RAID1 の構成は Partition Manager を使った。
RAID10 のパーティションについては、以下のような手順で RAID デバイスを作成する。
# mknod /dev/md3 b 9 3
最初に、デバイスファイルを作成する。9 はマジックナンバー。3 はデバイスファイルの番号と一致させる。
# madam --create /dev/md3 -v --raid-devices=4 --level=raid10 /dev/sda2 /dev/sdc2 /dev/sdd2 /dev/sdb2
これで RAID デバイスが /dev/md3 として作られ、パーティションの同期が直ちに始まる。同期の進行状況については /proc/mdstat を cat かエディタで見ると分かる。4GB の同期はすぐに終わったが、450GB の同期には2時間以上かかった。
RAID10 にしたい他のパーティションに対しても同様に mknod と mdadm を実行する。
5. LVM パーティションの作成
参考 http://www.gentoo.org/doc/en/lvm2.xml
LVM2 dm-mod モジュールをロードする。
# modprobe dm-mod
物理ボリューム(今の場合は RAID デバイス)を LVM2 に登録する。
# pvcreate /dev/md5
vg という名前でボリュームグループを作る
# vgcreate vg /dev/md5
論理ボリュームを作る
# lvcreate -L10G -nusr vg
# lvcreate -L5G -nhome vg
# lvcreate -L5G -nopt vg
# lvcreate -L20G -nvar vg
# lvcreate -L10G -ntmp vg
作った論理ボリュームは、例えば /dev/vg/usr としてアクセスできる。
6. OS のインストール (Ubuntu 7.10 Server AMD64)
RAID10 の設定が終わったら Ubuntu のインストールメニューに戻り、再び Partition Manager を起動する。RAID デバイス(/dev/md?) と LVM ボリューム(/dev/vg/*)が選択肢に現れているので、それらに適当なパーティションを作る。スワップを除いて ext3 を選択する。パーティションごとに適当なマウントポイントを設定する。
Partition Manager での設定が終わったら、インストーラの指示どおりにインストールを続ける。RAID の設定には無関係なので、以下省略。
Garmin Edge 305 のリセット方法
Garmin Edge 305 が、どのボタンを押してもうんともすんとも言わなくなったときは、以下の方法でリセットする。
- Lap ボタンと mode ボタンを同時押しして5秒待つ
- いったんボタンを離して電源ボタンを押す。
Second Annual Silicon Valley Ruby Conference
Second Annual Silicon Valley Ruby Conference に参加した。2日間、朝から夕方までほぼノンストップでプレゼンを聞くというマラソンイベントで、かなり消耗した。参加者は 200 - 300 人で、この手のイベントとしては盛況だったのではないか。
以下は、いくつか面白かった点。
Ruby on Rails が盛り上がる
13 のプレゼンのうち 10 が、直接間接的に Rails についてのものだった。Ruby が US でポピュラーになった経緯を考えるとこれは驚くことではない。
プレゼンの中でも、Blain Cook による、商用ウェブサイトに Rails を採用した SNS サイト (http://twitter.com/) の技術的な発表(というか、苦労話)が聴衆の注目を浴びていた。
8台の Sun 上で 160 の Rails プロセスを走らせ、600 request/sec のリクエストを処理しているそうだ。Rails の本当のスケーラビリティについては、なかなか具体的な数字が見つからないので、これは参考になった。
驚いたのは、開発を初めて1年余りのこのサイト、今年の初めに開発陣が総入れ替えになったらしい(と言っても、2人抜けて3人入っただけだが)。「RoRでなければ、これだけ短期間に新開発陣が立ち上がることはできなかった」とは Blain Cook の弁。確かに、これが Java や PHP を使ったウェブアプリだったらどうなったか。
アンチ Ruby on Rails もある
Ruby on Rails 万歳!で終始するかと思われたコンファレンスだったが、意外にも Ruby on Rails に真っ向から(?) 対抗するウェブフレームワーク "Merb" の発表があった。開発者の Ezra Zygmuntowicz の発表だったが、彼曰く、
- Rails はスレッドセーフではないので、一つのプロセスが一度に一つのリクエストしか処理できないから遅い。
- 新しい Rails のリリースごとに、パフォーマンスが 10-20% ずつ遅くなっている。
- Rails コミュニティは「コードが成熟しないうちの最適化は行わない」と言っているが、もう成熟してるんじゃないの?
- Rails は互換性に縛られて、身動きが取れなくなりつつある。
ということで、自ら軽量フレームワークを作ることにしたそうだ。実際に、Rails を使って Hello World を出力する場合と、Mongrel の request handler で直接 Hello World を出力する場合のパフォーマンス比較デモがあったが、後者の方が10倍近く速かった。
「本当は Rails が遅いだけなのに、Ruby が遅いという認識が広がっているのは残念だ。」という発表者の発言を聞いて、何となく嬉しくなってしまったのはなぜだろう?
ともかく、Ruby ベースのフレームワークの選択肢ができるのは、使う側としてはありがたいことだ。
VM
VM については、JRuby と rubinius の発表があった。
発表者の によれば JRuby のパフォーマンスは、コンパイル後なら ruby 1.8.5 よりも速いらしい。ruby 1.9 との比較はなかったが、どっちが速いのだろう?
Ruby から Java Swing を使ってダイアログを表示するデモがあった。Swing のクラスをまるで普通の Ruby のクラスのように使っている。こういうことができるのは、ちょっと面白そうかもしれない。
rubinius は「Ruby で書けるところは C で書かない」をマントラとする Ruby インタープリタ実装プロジェクト。パフォーマンスはどうするんだろうと真っ先に思ったが、Evan Phoenix の答えは「パフォーマンスの低下は VM の改善で補う」だった。かなり野心的だ。
VM のインストラクションセットは YARV と違うのかと質問したら、ほとんど同じだとのこと。互換性も考慮していると言っていたので、この先大きく違ってくることもないのだろう。
Vista ファーストインプレッション
Vista を使い始めて1週間。最初の感想。
- バックグラウンドでやたらと何やらやっていて、HDDアクセスが止まるひまがない。
- そのおかげで遅い。
- アプリケーションの互換問題が、致命的でないにせよ、ちらほらと。
- システム変更に関する警告ダイアログが頻繁に出てきて鬱陶しい。
- Windows Aero のありがたみが今イチ良くわからない。
というわけで、今すぐ Vista に乗り換える必要はないと個人的には思う。