今やサーバ証明書なんてLet’s Encryptあたりを使用すればフリーだしHTTP/2だとかApp Transport Securityだとかでなにかと必要になってくるSSL/TLS関連の設定。
よく見る注意事項としてSSLv2, SSLv3の無効化、弱いアルゴリズム(RC4など)を使用しないなどがありますが、じゃあ結局Cipher Suiteは何を指定したらいいんだよ!って思うんです。
Nginxだと ssl_ciphers、Apacheだと SSLCipherSuite の項目です。
"HIGH" なんて指定しても「どこがHIGHなの?」という雑な設定になるし、そこから脆弱なものを除外していくのも大変すぎます。
試しにどのCipher Suiteが設定されるかの確認。
$ openssl ciphers -v 'HIGH'
そこで2017年1月現在でのブラウザやその手のクライアントで大体サポートされてるECDH(楕円曲線ディフィー・ヘルマン鍵共有)をベースに指定して簡潔に書こうということです。
ここではECDHにはEphemeral ECDH(動的生成する一時的なECDH)という "EECDH" (※1)を指定します。
※1. openssl 1.0.2以降だと "EECDH" "ECDHE" どちらでも指定できますがCentOS 7でもopenssl 1.0.1eが使われていたので下位互換ということで "EECDH" です。
$ openssl ciphers -v 'EECDH' ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1 ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 ECDHE-RSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=RSA Enc=3DES(168) Mac=SHA1 ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=3DES(168) Mac=SHA1 ECDHE-RSA-NULL-SHA SSLv3 Kx=ECDH Au=RSA Enc=None Mac=SHA1 ECDHE-ECDSA-NULL-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=None Mac=SHA1
この一覧で特に使用したいのがEnc=AESGCM、逆に使用するべきでないEnc=RC4, None。これらをまとめて指定するために以下のようにします。
$ openssl ciphers -v 'EECDH+AESGCM:EECDH+AES256' ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
すっきりですね。優先順位(※2)もTLSv1.2 Enc=AESGCM(256)が上に来るので強度も申し分ないです。
'EECDH:!RC4:!NULL' ではなく 'EECDH+AESGCM:EECDH+AES256' としたのはAESGCMを先にもってこないと優先順位が変わって一部のブラウザで “接続エラー INADEQUATE_SECURITY” (※3)がでるためです。
また、下位互換のためのTLSv1 ECDHE-RSA(ECDSA)-AES256-SHAがあるので相当ダメなクライアント以外は問題がでません。
ついでに言うなら鍵生成時のRSA・ECDSAどちらでも対応できます。
※2. ssl_prefer_server_ciphers (SSLHonorCipherOrder) on でCipher Suiteの優先順位を指定している場合です。
※3. HTTP/2の場合はTLSv1.2を使用する必要がある (HTTP/2 over TLS/1.2)。
と、ここで終わってもいいのですが今のところAES128+SHA256で十分な強度ですし、パフォーマンスを考慮するならAES128を上に持ってくる方がほんの少し(数%~10%)だけ速いので以下のようにすれば良いと思います。
github.com を見てみるとAES128の優先順位を高くしてますしね。
$ openssl ciphers -v 'EECDH+AESGCM+AES128:EECDH+AESGCM:EECDH+AES128:EECDH+AES256' ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
最終的にあまり短くなったとは言えませんがNginxの設定は以下のようにしています。
server { listen 443 ssl http2; ssl on; ssl_prefer_server_ciphers on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers EECDH+AESGCM+AES128:EECDH+AESGCM:EECDH+AES128:EECDH+AES256; ... }