なぜあなたがウェブサイトをHTTPS化するとサイトが遅くなってユーザーが逃げていくのか

 完全に釣りタイトルですけど中身は真面目に書くよ。
 近年、ウェブサイトのHTTPS化が流行のようになっている。私の知る限り、Googleの各種サービスやTwitterFacebookなどが完全にHTTPSで通信を行うようになっている。HTTPS、つまりSSLによる通信の暗号化によって、ユーザにこれまでよりも安全なウェブサイトを提供できる。
 しかし、あなたが作っているサイトをふと思いつきでHTTPS化してしまうと、たぶん、これまでよりもサイトが遅くなる。ここでは、HTTPSで通信する場合の問題を解説する。

なぜ遅くなるのか

 HTTPで通信する場合、クライアントがサーバへと接続するためにはTCP/IPの3ウェイハンドシェイクという手順が必要になる。めんどくさいのでここでは詳しくは説明しないが、要するにクライアントがリクエストを投げる前にパケットを1往復させないといけないのである。パケットの往復にどれぐらい時間がかかるかはpingコマンドで簡単に確認できる。たとえば、ping www.kyoto-u.ac.jpとかコマンドを打つと、おそらくは京都にサーバがあるであろう京都大学のサイトにパケットが行って戻ってくる時間が計測できる。1往復で約30msぐらいだった。東京-京都間(500kmぐらい?)で30msということを覚えておきたい。
 30ms、つまり0.03秒であればそんなに大したことのない数字である。
 実は、HTTPSでは通信をはじめる前に必要なパケットのやり取りが3往復になる。3往復するとなると0.09秒、もうほとんど0.1秒待たされることになる。ちょっとそろそろ人間が知覚できるぐらいの時間になってきた。
 他にも悪いニュースがある。SSLの証明書にはOCSP(Online Certificate Status Protocol)という証明書を失効させるための仕組みがあるのだがこれが遅いのである。この仕組みを要約すると、証明書を受け取ったら実際に通信を始める前にOCSPレスポンダと呼ばれる失効情報を管理するサーバに対して、証明書が失効していないかどうかを確認する、というものである。別のサーバに問い合わせが発生するため、DNSで名前を解決したり、サーバにリクエストを飛ばしたり、といった手順が必要になり、通信の開始が遅れるわけである。安いSSL証明書を使うとOCSPレスポンダが海外にしかなかったりして悪影響が大きい。OCSPは最近のブラウザであればほぼ確実に対応している。
 なんでOCSPのような仕組みが必要なのか。証明書というのは技術的には公開鍵暗号の公開鍵側なので、対応する秘密鍵が漏れた場合には悪用を防ぐために失効させる仕組みがほしい、ということでこんな状況になっている。以前は失効した鍵のデータベース(Certification Revocation List)をダウンロードするという方式だったようだが、最近のブラウザは全部OCSPに移行したみたいだ。
 ここまでの説明を繰り返すと、HTTPSで通信を行うことになると、TCP/IPの分で1往復、SSLの分で2往復の遅れが発生し、OCSPチェックで2往復から4往復程度はパケットの往復が発生する。4往復、というのは、安い証明書だと中間証明書というものが入っており、中間証明書にもOCSPチェックが必要だからである。OCSPチェックで海外にリクエストが行く場合はこの往復は30msとかそんなかわいい数字ではなく、1往復で200msぐらいかかったりする。実際にはOCSPには300ms程度はかかるのがふつうみたいだ。
 という訳で、SSLを使うと通信が始まるまで、HTTPの場合と比べ、最低でも120ms程度の遅延が発生することを覚悟しないといけないのである。
 Googleでは0.4秒レスポンスが遅くなるとクエリ件数が0.6%程度減少するそうなので、うん、120ms程度だとそんなに気にするほどじゃないかな……。ただ、OCSPチェックで0.5秒とかかかると、ちょっと無視できない感じになってくる。

速くする方法はあるのか

 というわけで、SSLを使うと、レイテンシがある程度増えることは仕方がない。しかし、多少の対策は取り様がある。以下ではいくつかを解説する。
 1つめはSSL False Startと呼ばれるSSLの通信開始方式である。これはSSLで必要なパケットの往復回数を2回から1回に減らしてくれる。ただ、ブラウザ側がサポートしていないと使えない。Google Chromeではデフォルトで有効化されている。Firefoxでは実装されているがデフォルト設定では無効になっている。ユーザがGoogle Chromeを使っていることを祈るだけなので、対策とは呼べないが、有効ではある。
 2つめは、OCSPステープリングと呼ばれるTLSの拡張である。これは、OCSPレスポンダの返答をあらかじめサーバ側がキャッシュし、通信時に証明書と一緒にクライアントに送りつけることで、クライアントではOCSPのチェックを省略できる、というものである。証明書と一緒にホチキス留めしてしまうイメージなのでステープリングと言うのだろう。自分で自分の使ってる証明書が正しいと言ってるだけで安心できないのでは、と一瞬思ってしまうのだが、OCSPレスポンダの返答は改竄できないようになっているので、これでも大丈夫である。これを使うとOCSPチェックが省略できる。Apacheであれば2.4系列であれば対応している。Nginxはまだ安定版ではサポートしてないようだ。開発版ではサポートしている。OCSPステープリングは強力だが、1つの証明書に対してしかステープリングできない。このため、中間証明書が使われている場合、OSCPチェックを完全に省略できるわけではない。
 この他に有効な対策としてはKeepAliveの秒数や同時接続数の設定を見直すことが挙げられる。HTTPセッションを使いまわすことができたら、上記のぐちゃぐちゃとしたパケットの往復は全部すっ飛ばすことができるからである。ただし、初回接続時には効かない。

蛇足

 OCSP staplingについて調べると、たぶん上の方にCloudflareとGlobalSignの提携でSSLが速くなるよ〜、みたいな話がtechcrunchに載っていたがのが出てくるのだが、あの記事には間違いがいくつかある。というか、2つの話をごっちゃにしてしまって、結果として間違いが生じている。1つめはCloudflareがSSL経由でファイルをデリバリーする際にOCSP staplingを行うようにして高速に配信できるようになったよという話で、これにはGlobalSign側のシステムには何ら変更は生じていない。2つめはGlobalSignがCloudFlareを使ってOCSPサーバを世界中に配備したよという話で、こちらはOCSP staplingとは関係がない。(OCSP staplingを使うならばOCSPサーバは多少遅くても問題はない。いや、実際には中間証明書の問題があるから遅いと問題なんだけど。メジャーな中間証明書ってあんまり多くないはずなので比較的問題は少ない……はず……。)時系列が非常に近く、話も複雑なので仕方がないと思う。CloudFlareのブログ記事の冒頭OCSP staplingの話が載っていたので誰かが勘違いしたのだろう。
 調べていて最初は理屈が通らずに混乱したので、同じ道を通る人が減るようにここに書いておく。

参考URL

まとめ

  • サイトをSSL化すると初回の接続時に0.x秒程度の遅延が発生することになる。
  • Global SignSSL証明書を使うとOCSPサーバがCDNで世界中に配備されてるのでOCSPチェックがだいぶ速い。
    • でも個人で買うにはちょっと高いんだよね、GlobalSign……。
  • 初回接続時のことはあきらめて、Keep Aliveの設定とかを見直すのがいいかなと思う。
  • とりあえず、SSL使う場合はどんだけ遅くなるのかはあらかじめテストして確認したほうがよい。