Tornadoでは簡単にSSLサーバを構築できるということで、指定できるオプション等について調べるついでにSSL Server TestでA+を取れるように頑張りました。現在の評価はSSL Server Test: ama.ne.jpで見ることができます。
(2016-11-05) もうこのサイトのバックエンドはTornadoではありません。上記のサーバーテストはA+を返すかもしれませんし、返さないかもしれません。
なお、A+を獲得するには、適切な暗号スイートの指定はもちろんのこと、Strict-Transport-Security
レスポンスヘッダが必要です。
SSLサーバの設定
さて、ama.ne.jpは今のところ以下のようなHTTPServerで動作しています。
server = HTTPServer(app, ssl_options={
"certfile": options.ssl_crt,
"keyfile": options.ssl_key,
"ssl_version": ssl.PROTOCOL_TLSv1_2,
"ciphers": "EECDH+HIGH+AES!SHA:" +
"!ADH:!RC4:!MD5:!aNULL:!eNULL:!SSLv2:!LOW:!EXP:!PSK:!SRP:!DSS:!KRB5",
})
ここでは、Tornadoのnetutil.pyを元に、おそらくHTTPServerにssl_options
として与えられるであろうと思われるオプションについて書いていきます。
定数やオプションなどの情報はPythonのsslモジュールやopensslのciphersに詳しいです。
ssl_version
使用するSSL/TLSのバージョンを指定します。PROTOCOL_TLSv1_2
でTLS1.2のみを使用できる状態になります。
TLS1.0について
TLS1.0にはBEAST攻撃に対する脆弱性があります。ただし、古いブラウザをサポートしなければならない地獄のような状況下なら有効にしなければならないかもしれません。PROTOCOL_SSLv23 | OP_NO_SSLv2 | OP_NO_SSLv3
で、TLS1.0、TLS1.1、TLS1.2を使用できる状態になります。
ciphers
oepnsslの記法に倣って使用する暗号スイートを指定します。
暗号スイート指定で用いる記号
:
は暗号スイート指定の区切りです。- プレフィクス
+
でその暗号スイートを追加します。ただし、1つの暗号スイート指定内で接続されて用いられた場合はAND条件を指します。 - プレフィクス
-
でその暗号スイートを取り除きます。ただし、1つの暗号スイート指定内で接続されて用いられた場合はNAND条件を指します。また、これより後ろの暗号スイート指定で再び追加可能です。 - プレフィクス
!
でその暗号スイートを使用しません。これより後ろの暗号スイート指定でも追加することはできません。
今回指定した暗号リスト
FS(Forward secrecy)を満たすECDHE-RSAのうち、鍵長の大きなものを指定しました。一応後ろで、弱いものや使わないものを取り除いています。
certfile
自身の公開鍵の格納場所を指定します。CA証明書を含んでいてもかまいません。CA証明書を含む場合は、必ず上から
- 自身の証明書
- 中間CA証明書
- より上位の中間CA証明書 ...
のように、より下位の証明書から順に並べます。ルート証明書は各ブラウザが持っているはずです。
keyfile
自身の秘密鍵の格納場所を指定します。
cert_reqs
証明書の妥当性チェックを行うかを指定します。サーバー側には必要ないので特に指定しません。
ca_certs
(2016-05-29) 証明書の妥当性チェックに使うCA証明書を指定します。サーバー側には必要ないので特に指定しません。
Strict-Transport-Securityヘッダの設定
HTTP Strict Transport Security(HSTS)は、「次からウチのサイトとはHTTPSで通信してくれ」というメッセージを伝える機能です。
幸いTornadoの*Handlerにはset_default_headers
メソッドが用意されているので、以下のようなクラスを作ってアプリケーション内の各ハンドラで継承して使うとよいでしょう。
class HstsRequestHandler(RequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def set_default_headers(self):
self._headers.add("Strict-Transport-Security",
"max-age=31536000;includeSubdomains;preload")
なお、HSTS preload listに登録するには、長いmax-age
(1年=31536000秒くらい?)やincludeSubDomains
およびpreload
の設定が必要です。
(2016-02-25) ChromeのHSTS preload listにama.ne.jpが入ったようです。
終わりに
自己満足しか得るものがない努力だった。