今こそ知ってもらいたいSSL/TLSのお話

こんにちは。さくらインターネットのやまけんこと、山田健一です。

複数回にわたり、「SSL/TLSとは何なんだ? 今こそ知ってもらいたいSSL/TLSのお話」と言うことで、SSL/TLSに関するお話をさせていただいております。前回は、「SSL/TLSとは」という導入部分のお話をしました。今回は、その続きとしてTLS1.3と、それに関連してHTTP/2のお話をさせていただきます。

謝辞

第1回目の記事である SSL/TLSとは何なんだ? 今こそ知ってもらいたいSSL/TLSのお話 〜 1回目 〜 SSL/TLSとはにつきまして、はてなブックマークにおいて350以上のブックマークをありがとうございます。SSL/TLSへの関心の高さに正直驚きました。おかげさまで本シリーズ執筆の励み、ならびにプレッシャーを感じます。

また、私自身 マスタリングTCP/IP SSL/TLS編 や プロフェッショナルSSL/TLS 、各RFCを参考に執筆しておりますが、誤っている部分があれば、ご指摘ください。

TLS1.3とは

TLSについては前回お話しした通り、SSLをNetscape社からIETFへ移管するために、TLSワーキンググループが結成され、SSLからTLSへと引き継がれました。

その最新版となるのがTLS1.3です。2018年8月にRFC8446として発効されました。

TLS1.3については、バージョン表記だけで見るとマイナーバージョンアップのように感じますが、実際にはメジャーバージョンアップと言って良いほどに変更点が多々あります。

  • 古い対称暗号アルゴリズムや鍵交換、署名などが取り除かれ、結果として組み合わせの数が劇的に減った。
  • 0-RTTが追加され、一部セキュリティに注意する必要があるが、ハンドシェイクを削減できるようになった。
  • Server Hello中のChange Cipher Specの後続レコード以降のすべてのハンドシェイクが暗号化されるようになった

まだまだ違いはありますが、今までと大きく変わった部分になります。

古い対称暗号アルゴリズムや鍵交換、署名などが取り除かれ、結果として組み合わせの数が劇的に減った。

TLS1.2までについては、過去との互換性などの問題で、非常に多くの対称暗号アルゴリズム・鍵交換・署名をサポートしていました。

しかしながらコンピュータの進化により暗号方式として脆弱なものが多くなってきたため、TLS1.3では整理されました。

鍵交換(Kx)

使用可能なもの
  • DHE
  • ECDHE
  • PSK
使用できなくなった主なもの
  • DSS(DSA)
  • RSA
  • ECDSA
  • DH
  • ECDH

署名(Au)

使用可能なもの
  • RSA
  • ECDSA
  • EdDSA
  • PSK
使用できなくなった主なもの
  • DSS(DSA)

対称暗号アルゴリズム

使用可能なもの
  • AES GCM(ブロック暗号)
  • AES CCM(ブロック暗号)
  • ChaCha20 Poly1305(ストリーム暗号)
使用できなくなった主なもの
  • AES CBC(ブロック暗号)
  • Camellia GCM (ブロック暗号)
  • Camellia CBC (ブロック暗号)
  • ARIA GCM (ブロック暗号)
  • ARIA CBC (ブロック暗号)
  • SEED CBC (ブロック暗号)
  • RC4 (ストリーム暗号 TLS1.3で除外されたが、TLS1.2以下でもRFC7465にて廃止)

暗号スイート (ciphersuite)

  • TLS-AES256-GCM-SHA384
  • TLS-AES128-GCM-SHA256
  • TLS-CHACHA20-POLY1305-SHA256
  • TLS-AES128-CCM-SHA256
  • TLS-AES128-CCM-8-SHA256

ちょっとこう書くとツッコミが入りそうなのですが、

openssl ciphers -V -tls1_3 | grep TLSv1.3 をコンソールで叩いていただくと

0x13,0x02 – TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
0x13,0x03 – TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
0x13,0x01 – TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD

などと返ってくると思います。

openssl ciphers -V -tls1_3 | grep TLSv1.3の実行例

(余談ですが Ubuntu 18.04.3 LTS の OpenSSL 1.1.1c だと AES128-CCM , AES128-CCM-8 が出てこないようですね)

Kx=any Au=anyと書いてあるように、鍵交換と署名がanyですが、実際に使えるのは上記、鍵交換(Kx)署名(Au)のみです。

IANAの Transport Layer Security (TLS) Parameters を確認しても、下記のようになっています。

Value Description DTLS-OK Recommended Reference
0x13,0x01 TLS_AES_128_GCM_SHA256 Y Y [RFC8446]
0x13,0x02 TLS_AES_256_GCM_SHA384 Y Y [RFC8446]
0x13,0x03 TLS_CHACHA20_POLY1305_SHA256 Y Y [RFC8446]
0x13,0x04 TLS_AES_128_CCM_SHA256 Y Y [RFC8446]
0x13,0x05 TLS_AES_128_CCM_8_SHA256 Y N [RFC8446][IESG Action 2018-08-16]

TLS1.2までのciphersuiteに比べ、非常にすっきり書けるようになりました。

HTTP/2とは

HTTP/2 ( Hypertext Transfer Protocol version 2 ) とは、2015年2月にRFC7540として発効された Hypertext Transfer Protocol の新しいプロトコルです。

詳しい仕組みにつきましては、当さくらのナレッジに 普及が進む「HTTP/2」の仕組みとメリットとは という松島浩道さんが書かれた記事がありますので、そちらを参照いただきたいと思いますが、本記事ではTLSとの関係性の部分について掘り下げて紹介したいと思います。

HTTP/2では過去のHTTP1.1や1.0と互換を保つため、使用するデフォルトのポート番号もHTTPの場合は 80番 HTTPSの場合は 443番 で変化はありません。また、コネクションを貼る際には h2 ( HTTP/2 over TLS )と h2c (HTTP/2 over TCP)という識別子が定義されています。h2についてはTLS上の拡張を使い、コネクションを貼ります。h2cについては従来どおりのhttpの通信をベースに、サーバクライアント間のやりとり中に HTTP/2 へ切り替えます。またH2Directといい、h2cでもhttp接続直後に PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n の 24 bytesを送信することでHTTP1.1から切り替えることもできます。

しかしながら、現状のブラウザでは h2 は多くのブラウザでサポートされていますが、h2cのサポートはほぼされていないため、HTTP/2を使うためには事実上、TLS通信を伴う h2 でなければ利用できません。これにはHTTP/2の前身となったSPDYの存在が関係します。

SPDYとは

googleが2009年11月に発表したHTTP1.1をベースに高速化を目指したプロトコルで、最終バージョンは Draft 3.1 です。SPDYはTCPとHTTPの間に新しいプロトコルレイヤを導入することで速度を向上させるものです。中間レイヤに存在することで、HTTPそのものは何も変更せず、サーバクライアント間の接続を改善させました。

具体的には、複数のHTTPリクエストとレスポンスを1つのSPDYセッションにてやり取りすることにより、ブラウザが必要とする接続がサーバごとに1つで済むことになります。

今までのHTTP1.1では、コネクション数を2にすることを推奨 ( RFC2616 ) していましたので、単一のHTMLだけのサイトであれば気になりません。しかし、CSSファイルやJavaScript、画像など、1つのHTMLから読み込まれるファイルが多いと、最大2個づつしか同時にダウンロードできません(ブラウザが仕様通りに実装していれば)。また、接続毎にTCPセッションを張るため、都度 TCP three-way handshaking から始めます。そのためオーバーロードな部分が増えます。

SPDYでは、単一のTCPセッション上にて複数のHTTPリクエストを処理しますので、都度 TCP three-way handshakingをする必要もなくなります。そのため、TCP の利用効率が改善するため、サーバ負荷も下がります。

このSPDYセッションでやり取りするためのハンドシェイクを行うのが、TLSのNPN拡張によるものでした。

NPN拡張

NPN ( Next Protocol Negotiation ) 拡張とは、2011年7月にGoogleが提唱したもので、NextProtocolという新しいハンドシェイクを使い、サーバからは対応するプロトコルリストを提示し、クライアント側が使用するプロトコルを選びます。またこのやりとりも暗号化され、メッセージの内容からどのプロトコルを選択したかを推測されないよう、パディングを使って実際の拡張の長さを隠蔽します。

下図にてサーバ、クライアント間のTLS並びにNPN拡張(赤字で記載)のやり取りの様子を紹介します。

GoogleはこのNPN拡張とSPDYをIETFにて標準化を目指しました。SPDYについては、Google Chromeだけではなく、FirefoxやSafari、Internet Explorer 11(ただしWindows8.1以降)においてもサポートされ、サーバ側もApacheにmod_spdyモジュールが提供されたりnginxでサポートされるなど、SPDYは大きな成功を収めます。ブラウザ、サーバ、ひいてはその間の通信効率と様々な環境でパフォーマンスの改善が見られました。そして、SPDYを発展させ、本来SPDY/4となる物が現在のHTTP/2となりました。

しかし、NPN拡張についてはそのまま標準化されることなく、別の拡張に置き換えられました。それがALPN拡張です。( RFC7301 )

ALPN拡張

ALPN (Application Layer Protocol Negotiation ) 拡張はNPN拡張を置き換えるものとなり、NPN拡張同様TLSの拡張となります。しかしながらNPN拡張と異なるのは、サーバからは対応するプロトコルリストを提示し、クライアント側が使用するプロトコルを選ぶのではなく、クライアント側が自ら対応するプロトコルリストを平文で送り、サーバ側が受け取ったリストから決定するという方法になりました。平文でやりとりするため、途中のネットワーク機器が中身を見て、その情報に基づいてトラフィック制御ができるようになっています。2014年7月には RFC7301 として発効されました。

下図にてサーバ、クライアント間のTLS並びにALPN拡張(赤字で記載)のやり取りの様子を紹介します。

現在ではNPN拡張はALPN拡張に置き換えられ、2016年にはNPNを開発したGoogleでさえ、ChromeからNPN拡張を取り払ってしまいました。そのため、HTTP/2を使うためには実質ALPN拡張が必須となります。

おわりに

今回は、最新のプロトコルである、TLS1.3並びに、HTTP/2におけるTLS拡張についてをご紹介しました。

次回は SSL/TLSとは何なんだ? 今こそ知ってもらいたいSSL/TLSのお話 〜 3回目 〜 2019年版 Webサーバへの設定について ということで、読み物でというよりかは、実際のサーバへの設定はどのような内容が良いのか、実践的な内容でご紹介させていただきます。