stat.inkサーバ設定

stat.ink は HSTS Preloading に対応しています


※「TLS/SSL」とか書くのが面倒くさいので、以下、総称して(通りの良い)SSLと記載します。

常時SSL

利用者の方はお気づきだと思いますが、 stat.ink はいわゆる「常時SSL」で運用しています。

これは、ログインページ等のセキュリティ上重要なページだけでなく、関連する全ての通信をSSLで暗号化する運用です。

GoogleやTwitterなど、最近は常時SSLで運用することが多々ありますが、同様の状態であると言えます。

SSL通信のメリット

インターネットは性善説で成り立っている箇所が結構あって、悪意に対して無防備であるところがあります。

例えば、

  • 「stat.ink のサーバのIPアドレスは?」とブラウザが調べる時に、悪意によって嘘のIPアドレスを教えられる
  • 通信中に、悪意のある人がデータを書き換える
  • 他人の通信をのぞき見して、ログイン操作を迂回してなりすます(セッションハイジャック)

といったことができます。縁遠いように思えますが、どれも実際にそれなりに行われる攻撃です。
「データを書き換える」のは悪意があるかどうかはともかくとして「通信の最適化」とか呼ばれている通信キャリアによる画像の改変あたりで日常的に行われています。

のぞき見したり書き換えたりというのは、公衆Wi-Fiなどの信頼できない経路を通っていると可能性がぐんと跳ね上がります。

SSL通信を行うと、「通信先のサーバがほんものである」ことを確認できるので、

  • IPアドレスとして嘘のものを教えられても、通信先のサーバがニセモノであると見破れる
  • SSL通信は書き換えられない(書き換えるとエラーになる)
  • SSL通信はのぞき見しても情報を読み取れない

という風に防ぐことができる、という理屈です。

HTTP (HTTPSでない) のアクセス

stat.ink は常時SSL運用ですから、URLは「https://stat.ink/」になります。

みんながちゃんと https と入力してくれれば何も問題は無いのですが、実際にはまず入力されません。
すると、ブラウザは http:// を補完して http://stat.ink/ にアクセスするわけです。

stat.inkのサーバは、http でアクセスされた場合は「https でやり直してください(リダイレクト)」と応答します。
ブラウザはその指示に従ってもう一度アクセスしなおします。

ここまでは大した問題ではありません。ほんの一瞬、ほんの僅かな通信が増えるだけの話で、気にするほどのものでもありません。

さて、ここで、stat.ink のIPアドレスとして嘘の「203.0.113.1」を教えられたとします。(ホンモノのIPアドレスは現時点では 133.242.247.20 と 2401:2500:10a:1004::20 です)
ブラウザは 203.0.113.1 のサーバに「stat.ink のコンテンツちょーだい」と要求します。
ニセモノのサーバはもちろんホンモノの https サーバに誘導したりせず、例えばウィルスをばらまくような悪意のある行動を行うでしょう。
あるいは、にせもののログインフォームを表示して、stat.ink のユーザ情報を盗み見ようとするかもしれません。

HSTS

この問題への対応として、HSTS (HTTP Strict Transport Security) という仕組みがあります。

これは、正規のHTTPSサイトにアクセスした場合に「うちのサイトは常時SSL運用しているので、今後(ここにサーバ指定の時間が入る)までの間は http:// と入力されたとしても https:// としてアクセスして」という指示をサーバからブラウザに与える仕組みです。
「(ここにサーバ指定の時間が入る)」のあたりは、大体半年とか1年とかが指定されています。
最後のアクセスからその時間が経つまでの間は、ブラウザにうっかり https と入れ忘れても平気(仮にニセサイトに誘導されようとしたら証明書エラーになる)という安全対策が行われています。

stat.ink はもちろんこの HSTS を利用しています。

少し詳しい方は、stat.ink との通信を見てみると、実際の指定を見ることができます。

$ openssl s_client -connect stat.ink:443
CONNECTED(00000003)
《snip》

    Verify return code: 0 (ok)
---
《ここからブラウザのリクエスト》
HEAD / HTTP/1.1
Host: stat.ink
Connection: close

《ここからサーバのレスポンス》
HTTP/1.1 200 OK
Date: Sat, 25 Jun 2016 11:28:12 GMT
Connection: close
Server: h2o/2.1.0-beta1
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
x-xss-protection: 1;mode=block
x-content-type-options: nosniff
x-frame-options: DENY
x-ua-compatible: IE=Edge
strict-transport-security: max-age=31536000; includeSubdomains; preload 【←ここ。365日を指定】
cache-control: no-transform

HSTSの問題点

HSTSで「httpでのアクセスを行わない」ようにすることができました。

しかし、この仕組みには欠点があります。

一回通信したことがないと発動しないのです。

本当に一度もアクセスしたことのないブラウザは、https に書き換える必要があるのを知りませんから、 http でアクセスしようとします。
このタイミングで嘘の IP アドレスを教えられたなら……どうしようもありませんね。

HSTS Preloading

この「一度も通信したことがないと発動しない」問題ですが、これも解決策があります。
正直技術的にはどうかと思うのですが、ブラウザ屋さんがこう作っちゃったので当面はどうにかなるんでしょう、きっと。
個人的にはそのうち破綻すると思ってますが、まあそれはいいことにします。

その解決作は HSTS Preloading と呼ばれていて、ブラウザのソースコード上に「このサイトはhttpsでアクセスしなさい」と書いてしまうことで「最初からHTTPS」を実現します。

つまり、新規インストールした環境でブラウザにおもむろに「http://stat.ink/」と入力したとき、ブラウザはいきなり「このサイトhttpsでアクセスしなきゃならんサイトや!」となります。

stat.ink ドメインは、Chrome, Firefox, IE の HSTS Preloading リストに登録されているそうです(登録申請したのは私ですが)。
ここでいう IE は IE 11 と Edge のことみたいです。
Chrome (正確には Chromium) をベースにしている Opera のほか、Safari でも有効になると思いますが、現時点でどうなのかはわかりません。

Chrome(のベースのChromium)のこのソースファイルを検索してみると、stat.ink が含まれているのがわかると思います。
Firefox やその他のブラウザもこの Chromium 用のデータから生成しているそうなので、順に適用されます(されました)。

まとめ

  • stat.ink は常時SSL運用
  • 常時SSL運用のためにhttpからhttpsにリダイレクトさせる仕組みは悪意を防げないことがある
  • http://と書いてもhttps://でアクセスさせるための安全のための仕組み(HSTS)がある
  • HSTSでは初回アクセス時の悪意は防げない
  • これを解決するための HSTS Preloading という仕組みがある
  • stat.ink はこのリストに掲載されているので(対応ブラウザなら)最初から https で強制アクセスされる。素晴らしい。