Help us understand the problem. What is going on with this article?

WebサーバのHTTPS化において、SSL/TLS周りの各種設定はどう選択するべきか(2016年度版)

More than 1 year has passed since last update.

公開HTTPSサーバを立てるときに悩む点の一つが、SSL/TLS周りの設定です。

  • SSL/TLSや暗号周りの知識がないと適切な設定を選ぶのは難しい
    • そもそも設定が何を意味しているのか読み取れない
  • 「推奨される設定」が各種サイトでいくつも、微妙に違うものが紹介されていて、どれが良いのか選べない

とりわけ暗号が関連する選択肢は呪文めいていて、専門知識を持たないWebエンジニアにとっては、なかなか難しいものがあると思います。
筆者もSSL/TLSの専門家ではありません。
専門家でないなりに極力信頼できそうなソースや実例を参考にしつつ、まとめました。もともとは自分用調査資料集のような記事です。

すごく長くなってしまいました(若干力尽きている)。

TL;DR

  • MozillaのTLS設定ガイドをひな形にして設定する。Config Generatorもある
    • とりあえず従っていれば酷いことにはならない
    • 現代的な多くのサイトでは "Modern" と "Intermediate" の中間的な設定がされている、気がする
  • SSL Server Testsを活用する
    • 自サイトの設定確認
    • 他のサイトの結果も参考に
  • 近年1登場した技術にも目を向ける
    • 例えば、OCSP StaplingやChaCha20-Poly1305

事前知識

SSL/TLSはTCP上に暗号化された通信路を作るプロトコルです。その通信路の上をHTTP通信するプロトコルを指してHTTPSと呼びます。

SSL/TLSは歴史あるプロトコルなため、幾度ものバージョンアップ・プロトコルの機能拡張を経てきました。またそもそも後述する暗号スイートなど、複数のパラメータから通信方式を柔軟に選ぶことができるプロトコル設計になっています。

したがって、適切なパラメータでクライアントとSSL/TLS通信をするには、多少の知識が必要になります。

この記事では、サーバ側の観点から、決めなければならない主要なパラメータをいくつかに大別します。

  • SSL/TLSのバージョンをどうするべきか
  • 暗号スイートをどうするべきか
  • その他の設定についてどう扱うべきか

これらについて、順次検討していきます。

SSL/TLSのバージョン

現在考慮しなければならないプロトコルバージョンは、SSL3.0 / TLS1.0 / TLS1.1 / TLS1.2の4種類です。さらにTLS1.3(仮称?)が現在策定中で、おそらく来年以降に少しずつ広まっていくと思われます。

一般に、プロトコルバージョンが新しいほど安全で、かつ暗号スイートも新しいものが選択できます。しかし古いクライアントは古いプロトコルバージョンしかサポートしていないため、サーバがどのバージョンまでを許容するかは、セキュアさと互換性のトレードオフがあります。

暗号スイート

SSL/TLS上で使用される暗号技術の組のことを暗号スイートと呼びます。
より具体的には 鍵交換-認証-共通鍵暗号-メッセージ認証符号の各アルゴリズムの組み合わせを定めるものです。

利用できる暗号スイートはプロトコルバージョンなどの制約を受けます。例えばOpenSSLで利用可能な暗号スイートを確認すると、沢山の種類が出て2きます(とても多いのでheadで省略しました)。

$ openssl ciphers RSA -v | head -5
AES256-GCM-SHA384       TLSv1.2 Kx=RSA      Au=RSA  Enc=AESGCM(256) Mac=AEAD
AES256-SHA256           TLSv1.2 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA256
AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
CAMELLIA256-SHA         SSLv3 Kx=RSA      Au=RSA  Enc=Camellia(256) Mac=SHA1
DES-CBC3-MD5            SSLv2 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=MD5 

SSL/TLSのバージョンと選択できる暗号スイートには制約があります。例えばAES256-GCM-SHA384はTLS1.2でしか利用できません。

クライアントとの通信に利用する暗号スイートは、クライアントとサーバが提示したリストによって定まります。したがってサーバ側で決めるべきなのは

  • サーバがサポートする暗号スイート一覧
  • 暗号スイートの優先順位

になります。多くの設定例でサーバ側の優先順位を使って暗号スイートを定めることになっているので、どの暗号スイートを選ぶかだけでなく、順序も重要です。

オンラインスキャナ

オンラインでサーバのSSL/TLS設定を確認してくれるサイトはいくつもあります。

とりわけQualys SSL Labsのオンラインスキャンは、不適切な設定の発見や、各クライアントでどの暗号スイートが選択されるか等の情報も提示されるので、非常に高機能です。ちなみに、同サイトではクライアント別のデータベースが整備されており、SSL/TLSのサポート範囲なども確認できます。こちらも非常に有用です。

スキャナは自サーバの設定確認に役立ちますが、有名なサイトに向けてみることで各サイトの設定をのぞき見る用途にも使えます。さまざまなサイトの設定を見てみると、参考になるかもしれません。

検討箇所

SSL/TLSにおける設定選択は、こうすることが絶対に正しいというよりも、トレードオフから妥当な選択を導き出すという色合いが強いように思います。

いくつか検討するべきトピックについて、調べました。

TLSバージョンサポート範囲は?

SSL/TLSは時代とともに改良が続けられていく一方で、古いバージョンには問題が見つかり非推奨・廃止になっていくという歴史をたどっています。近年においても:

  • SSL3.0にPOODLE攻撃3が発見された(2014年)
  • TLS1.0にBEAST攻撃が発見された(2011年)。特定の条件下(CBCモード利用時)での危険性4が指摘された

こんな具合で、徐々に古いプロトコルは危険になっていっています。SSL3.0はほとんどの環境で廃止されており、TLS1.0は厳しく見て黄色信号5という程度の状況のようです。

暗号スイート的な観点としては、新しいTLSのほうが選択肢が増えます。特にTLS1.2ではAES-GCMやSHA-2が利用できるようになっています。
したがって、セキュリティ的な観点だけで言えば、最新のTLS 1.2だけを使いたい6ところです。

しかし、幅広い接続性を保っておきたいサーバの場合は、特に4.x系までのAndroidが(デフォルトで)TLS1.0までしか対応していない7という点がネックになり、TLS1.0の廃止は難しいかもしれません。

鍵交換アルゴリズムには何を選ぶべきか?

実質的な選択肢としては、 ECDH / ECDHE / DH / DHE / RSAがあります(追記: コメント欄のご指摘を反映し、ECDHとDHを削除しました)。
これらのうち、Perfect Forward Secrecy(PFS)8を満たすために、ECDHE/DHEを暗号スイートリストに含めて、優先させるほうがよさそうです。

特にクライアントがiOS9以降の場合は、今後ATSで要求される暗号スイートを提供せねばならず、ECDHEは対応が必須9のようです。

レガシーなクライアントとの通信を考慮する場合のみ、RSAによる鍵交換を選択肢に入れることになると思います。具体的にはAndroid2系やWindowsXPです10

認証方式はどうするか

実質的な選択肢はRSA or ECDSAです(DSAはほとんど普及しておらず、TLS1.3でも削除されそうです)。サーバ証明書を作る時に選ぶことになります。

  • ほとんどのサイトはRSA証明書を使っています
  • ECDSA証明書は一部のサイトで利用されています。RSAと同等以上の強度でも性能が良いという報告11があるようです
    • 例えばFacebookはECDSAを採用しているようです
    • 利用する認証局・サービスによってECDSAは選べないことがあるようです。例えばシマンテックのサーバ証明書ラインナップだと、特定のものしか楕円曲線証明書をサポートしていない

鍵長としては、RSAだと2048ビット、ECDSAではsecp256r1が最もよく使われる12ようです。

共通鍵はどれを?

事実上、AESがデファクトスタンダードです。最近のx86サーバであればAES-NIが有効化されているはずで、対応するOpenSSLなどの暗号ライブラリを使うことで効率よく暗号処理ができます。

AESの暗号利用モードとして、TLS1.2からAES-GCMが追加されました。
それ以前から導入されていたCBCモードに比して、一般にGCMモードのほうが高速13かつ安全14ではないかとされています。TLS1.2環境ではAES-GCMは積極的に使うべきなようです。

レガシーな暗号の扱い

多くの設定例では、暗号スイートリストにAES-GCMのようなモダンなクライアント用の暗号スイートと、より優先度が低い形で(リストの下の方に)レガシーな暗号をサポートするようになっています。

互換性のための典型的なものとしては、最低水準のものとして3DESやRC4を未だに有効化している例が挙げられます。

  • google.comやfacebook.comであっても、 DES-CBC3-SHA(SSLv3時代からの暗号スイートです)をサポートしている
  • facebook.comはRC4-SHAをサポートしている。RC4はもはや安全ではなく、使用するべきではないとされている(参考: https://tools.ietf.org/html/rfc7465

もちろん、これらはあくまで最大限の互換性を保つためのギリギリの配慮だと見ることができるため、多くのサーバではここまでレガシーな暗号スイートをサポートする必要はないかもしれません。

幅広いクライアントに対応するための暗号スイートの有名例としては、Mozillaの設定例のうち"Intermediate compatibility" / "Old backward compatibility" が挙げられます。
- https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
- https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility

AESの鍵長をどうするべきか

SSL/TLSにおいて、AESの鍵長は128/256のどちらかを選べます。これをどちらにするかで暗号スイート選択の方針が変わります。

有名サイトの多くはAES-128を優先している

google.com や facebook.com は、AES128-GCMを優先しています。
これにはいくつかの理由がありそうです。

理論的背景としては、Security Strength15による理由が考えられそうです。
NISTの評価によると、

Security Strength 共通鍵暗号 RSA ECC
112 3TDEA 2048 224-255
128 AES-128 3072 256
256 AES-256 15360 512+

世の中の多くのサーバでは、サーバ証明書にRSA-2048を使用しています。security strength的に釣り合うのはAESでいうと128が近く、256は過剰です。

また、AES-128のほうがバランスが良い選択であるという議論もあります。Mozillaのセキュリティ専門家であるBrian Smith氏の視点です:

Conversely, it isn't clear that AES-256 offers any significant security
advantage over AES-128, though it is clearly slower, even on my
AES-NI-equipped Core i7 processor. First, AES-128 has held up pretty well
so that it might just be "good enough" in general. Secondly, as I already
pointed out in my proposal, some research has shown that AES-256 doesn't
seem to offer much more security than what we understand AES-128 to offer.
See http://www.schneier.com/blog/archives/2009/07/new_attack_on_a.html and
https://cryptolux.org/FAQ_on_the_attacks. Thirdly, when non-constant-time
implementations are used, AES-256 seems to offer more opportunity for
timing attacks than AES-128 does, due to more rounds and larger inputs.
http://www.mail-archive.com/dev-tech-crypto@lists.mozilla.org/msg11302.html

要約すると、AES-128は十分に安全で、かつAES-256よりも明らかに効率が良い(たとえAES-NIが有効な環境であっても同様)。しかも、鍵長が長いからといって、AES-256のほうが安全だとは必ずしも言えない、という議論です。
数年前(2014年)の話題であることに留意する必要はありそうです。

Mozillaの設定例では、クライアントの想定によって異なる

https://wiki.mozilla.org/Security/Server_Side_TLS では、設定例ごとにどちらを優先するかが異なります。

  • Modern compatibilityでは256優先
  • Intermediate compatibilityでは128優先

クライアント環境でAES-NIなどの高速化命令が使えると想定するかどうか、が判断の分かれ目になっているようにも読めます。

それ以外の技術的選択肢

SSL/TLSは、規格に関連した周辺技術も発達しています。
ここでは、どれもある面で有用だと言われていますが、未だ普及途上にある技術について軽くまとめました。

TLS Session Cache / TLS Session Ticket

TLS接続の、特に最初の接続はCPUコストをそれなりに使います。ハンドシェイク時の公開鍵暗号周りの処理が重いとされています。この負荷を軽減するために、TLSには一度セッションを使いまわす仕組み(セッション再開: session resumption)があります。セッション再開によってサーバの負荷が大幅に下がるだけでなく、接続のレイテンシ短縮にもつながります。

セッション再開はサーバサイドに状態を保存することでも実現できます(普通のセッションキャッシュ)。おそらく導入しない理由はあまりなく、単に有効化すればいいだけのようです。

ただし、キャッシュの期限には注意が必要です。RFC4346に以下のような記述があります。

An upper limit of 24 hours is suggested for
session ID lifetimes, since an attacker who obtains a master_secret
may be able to impersonate the compromised party until the
corresponding session ID is retired.

要するに、あんまり長くしすぎるのはセキュリティ上のリスクになるので24時間以下にしておけ、ということのようです。実際には24時間でも長すぎてキャッシュとしての有効性が低いことも多いかもしれません16

TLS Session TicketはTLS Session Cacheとは異なり、暗号化されたセッションの状態をクライアントサイドに保持させる仕組みです。この仕組みだと、複数のサーバにまたがる形でセッションの再開ができるようになります。

参考:
TLSセッション再開 (session resumption) のしくみ
細かすぎて伝わらないSSL/TLS

とても有用な技術……なのですが

  • iOSが非対応
  • サーバに秘密鍵を持たせる必要がある。かつ、この鍵は定期的に再生成してローリングしていかなければならない(同じ鍵を使い続けるのはセキュアでない)

という欠点というか制限があるので、選択的に用いられる局面が多い気がします。

OCSP Stapling

サーバから送られてきたサーバ証明書が失効していないか(現在も有効なままであるか)は、クライアントがOCSPと呼ばれるプロトコルで認証局へ問い合わせることで確認されるのが標準的です。しかしながら問い合わせには通信というオーバヘッドが発生する上に、しばしば失敗すると言われています。

OCSP Staplingは「サーバがOCSPレスポンスをキャッシュする」ことで、クライアントと認証局間の通信によるオーバヘッドを削減する技術です。性能的な改善だけではなく、認証局にクライアントの情報が流出しないという意味でプライバシーを保護する効果17があるとされます。

  • サーバが認証局へと通信できるようにしなければならない
  • そもそもクライアントによってはOCSPを使っていない(e.g. Chrome18

といった側面はあるものの、有効にするメリットはありそうです。

参考:
【翻訳】Firefox における OCSP Stapling
【翻訳】証明書失効確認の改善: OCSP Must-Staple と Short-lived 証明書
我々はどのようにして安全なHTTPS通信を提供すれば良いか

HTTP2

HTTP2について書かれた記事は他にもたくさんあるため、HTTP2の特徴には触れません。
SSL/TLSの観点からは次の点が大切かなと思います。

  • インターネット環境でHTTP2を利用するためには、SSL/TLSによる暗号通信が事実上必須になっている
  • サーバ側は、単にSSL/TLS通信ができるというだけでなく、ALPN拡張にも対応している必要がある

特に後者は忘れられやすいです。悩ましいことに、有力なLinuxディストリビューションであっても付属のOpenSSLがALPN対応していないことがあるので注意が必要です。具体的にはRed Hat Enterprise Linuxとそのクローン(CentOS, Scientific Linux...)に標準添付されているOpenSSLは1.0.1系なため、ALPN対応していません。

参考:
EC2+nginxでhttp2対応できたとおもったらできてなかった話。(解決します)
nginxをHTTP/2対応にする方法(Chrome 51以降でも有効にする)

まとめ

  • SSL/TLSの設定項目のトレードオフを中心に調査しました
  • 記事に書いた内容は、主に2016年末ごろに調べたものです。既に古くなっている箇所があるかもしれません

  1. 近年と言いつつ、そんなに新しくもなかったりします…… 

  2. とても紛らわしいことに、OpenSSLの暗号スイート記法は、RSAなどの表示を省略します。例えばAES256-SHA256RSA-RSA-AES256-SHA256のことです。RFCの規格表記はTLS_RSA_WITH_AES_256_CBC_SHA256となるので、もうちょっと分かりやすい気がします。さらに共通鍵暗号にAES-GCMを使う場合はAES256-GCMなどと書き、AES-CBCの場合は単にAES256という具合に書きます。これらの対応関係については例えば→のサイトにまとめられています( https://testssl.sh/openssl-rfc.mappping.html ) 

  3. https://www.ipa.go.jp/security/announce/20141017-ssl.html 

  4. これの影響があったのか、TLS1.3 draftではCBCモードが廃止される方向性のようです。 

  5. SSL Pulseでは黄色扱い。セキュリティ専門家からすると、黄色信号なのだろうか、程度の認識。 

  6. ちなみに、TLS1.1が使えるが1.2は利用できないというクライアントはだいぶ珍しい19ようです。 

  7. https://developer.android.com/about/versions/android-5.0-changes.html#ssl 

  8. ある段階でサーバ証明書の秘密鍵が漏洩しても、それ以前の通信の解読に影響しない性質のこと、らしいです。TLSセッションごとに一時鍵を作ってそれを使うので、通信解読のためには結局一時鍵を解読しなければならない、らしい。参考: https://www.cryptrec.go.jp/symposium/20150320_cryptrec-og.pdf 

  9. https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW57 

  10. https://wiki.mozilla.org/Security/Server_Side_TLS#DHE_and_ECDHE_support 

  11. https://www.symantec.com/content/ja/jp/enterprise/white_papers/wp_forward_secrecy_report.pdf 

  12. 楕円曲線暗号ではビット長だけでなく曲線というパラメータもあるようです。最もよく使われるのがsecp256r1(NIST P-256)のようです。OpenSSLではprime256v1の名前で扱われています。なお、とても紛らわしいことに、secp256k1という似て非なるものもあるようです。 

  13. 例えば、AES-NI環境でのIntelの測定を参照: https://software.intel.com/en-us/articles/improving-openssl-performance 

  14. CBCモードに関して、前述のBEAST攻撃のような攻撃例が発生している点からも、安全性に疑問の声があるようです: http://www.jnsa.org/seminar/pki-day/2016/data/1-3_ootsu_.pdf 

  15. 異なる暗号方式をセキュリティビットという単位で評価したもの。たぶんそれを破るために必要そうな計算量、という理解でよさそう。SSL/TLSのような複数の暗号を組み合わせるプロトコルでは、全体の強度は最も弱い箇所の強度に等しくなる。 

  16. 例えばNginxのssl_session_timeoutはデフォルトが5分になっています。典型的なWebサイトを想定するなら、その程度でも十分なのでしょう: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout 

  17. 例えば、AppleはOCSP Staplingのプライバシー面での効果に着目している節があるように見えます。参考: What's New in Security(WWDCのセッションです) 

  18. https://scotthelme.co.uk/certificate-revocation-google-chrome/ 

  19. 例えばIPAのSSL/TLS暗号設定ガイドラインによると、"実装に関しては、規格化された年が TLS1.2 とあまり変わらなかったため、TLS1.1と TLS1.2 は同時に実装されるケースも多く〜"とある 

saka1_p
dwango
Born in the net, Connected by the net.
https://dwango.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした