こんにちわ、TenForward こと加藤です。
この記事は ファーストサーバ Advent Calendar 2016 7 日目の記事となります。
レンタルサーバに限らず、各種サーバでセキュリティのために SSL/TLS を使用する場合は、安全に暗号通信が行われる必要があるので、安全な設定をする必要があります。
SSL/TLS には色々なバージョンがありますが、プロトコル自体に含まれる脆弱性のため、最近では SSLv2 や SSLv3 は無効にする必要があります。
しかし、脆弱なバージョンを使わないだけでは、SSL/TLS を使った通信が安全になるわけではありません。どのような技術を使って暗号通信を行うのかが重要です。
SSL/TLS 関連の設定は、暗号関連技術の危殆化などにより、定期的に見直す必要があります。弊社においてもこれまで何度か見直しを行っています。最近も「暗号スイート」を中心に見直しをしたので、その際に検討や考慮したことを紹介したいと思います。
(注意:記事中でいくつか設定例を挙げていますが、あくまで一例として示しているだけで、特定のサービスがこのように設定されているということではありませんし、設定がセキュアであるというわけでもありません)
暗号スイート (Cipher Suite)
SSL/TLS は暗号通信のためのプロトコルですので、当然暗号技術が使われていますが、何か特定の暗号技術だけが使われているわけではありません。
その色々な部分で、色々な暗号やハッシュといった技術が組み合わされて使われており、最終的にクライアントとサーバが合意した方法で通信が行われます。その組み合わせを「暗号スイート」といいます。この組み合わせについては RFC で定義されています。
定義はバージョンによっていくつかありますが、例えば以下のように TLS 1.2 の RFC でも定義されています。
ここにあるように "Key Exchange"、"Cipher"、"Mac" の組み合わせで、暗合スイートが決まります。
つまり、暗号通信において重要な要素である、「相手を認証して鍵を交換する」(Key Exchange)、「データを暗号化する」(Cipher)、「改ざんを防止する」(Mac) のそれぞれでどのような技術を使うかを決めるわけですね。
各種サーバで SSL/TLS の設定を行う際には、このうちどの暗号スイートを使用するかを設定できます。各種サーバとも、デフォルト値が決まっていますが、脆弱な暗号やハッシュが使われてしまわないよう、明示的に設定するのが一般的になっています。
また、もちろんブラウザなどのクライアント側でもサポートする暗号スイートは決まっており、脆弱な暗号スイートは使わないようになっています。
実際の通信では、サーバとクライアントがネゴシエーションして、どの暗号スイートを使用するかを決めます。
レンタルサーバでサポートするブラウザの検討
では、暗合スイートとしてとにかく強固なものを選択すれば良いではないかと思われるかもしれませんが、そうではありません。
レンタルサーバのサーバにアクセスを行うユーザは、契約したお客様が直接行う場合もありますが、契約したお客様のサイトにアクセスにくる一般のかたかもしれません。全世界のインターネットユーザであると言っても過言ではないでしょう。
契約のお客様がどのようにお使いになるのか想定ができないので、サポートする環境を限定して、それ以外の環境からは使えません、とするわけにはいきません。
となると最新のPCやスマートフォンからのみアクセスされるわけではなく、ある程度年数の経った古い環境からアクセスが来ることを想定する必要があります。
古い環境だと、最新の技術をサポートしていない場合がありますので、ある程度古い環境でサポートされている暗号スイートをサポートする必要があります。
Zenlogic で設定する暗号スイートを考慮する場合は、以下のような環境を検討しました。
PC環境
PCからのアクセスの場合、どこまで古い環境を考慮するかによって、どのような暗号スイートをサポートすべきかの幅がかなり広がる可能性があります。
この幅は Windows と MacOS ではかなり違ってきます。
Windows
Windows の場合、考慮すべき一番古い環境は、今の時代だと Windows XP ではないでしょうか。すでにサポートが切れているとはいえ、StatCounter で調べると、少ないながらも、2016 年 11 月でも 3% 以上のシェアがあります。わずか 3% と言えども、それなりのアクセスが Windows XP から来ることを考慮する必要がありそうです。
Windows XP について考えるとき、ブラウザとしてどこまでサポートするかを考える必要があります。Windows XP 標準のブラウザは IE6 ですが、IE6 の標準設定では TLSv1 がオフ (SSLv2, v3のみオン) となっていたようです。さすがにそこまでをサポートする必要はないでしょう。
- Uset Agent Capabilities: IE 6 / XP (Qualys SSL Labs)
また Windows XP では IE8 までインストールができますので、Windows XP を考慮する場合は IE8 のサポート (もしくは設定を変更して TLSv1 を有効にした IE6) を考慮すればよさそうです。ただし、IE8 とはいえ、ライブラリの関係上、Windows XP に IE8 を入れても SNI をサポートしないなど、やはり現時点で使うには苦しい面もあります。
Vista になると IE7 を使っていても、TLS 1.0 まで使えますし、Vista のライブラリでは SNI もサポートできますので、なんとか使える範囲に入るでしょうか。
- User Agent Capabilities: IE 7 / Vista (Qualys SSL Labs)
MacOS
MacOS については現時点ではあまり検討する部分はありません。MacOS X 10.6 あたりの Safari 5 であっても、現時点で使える環境をサポートしています。
- User Agent Capabilities: Safari 5.1.9 / OS X 10.6.8 (Qualys SSL Labs)
モバイル
iOS
iOS 6.0.1 の Safari 6 でも TLS 1.2 までサポートしていますし、全く問題はないでしょう。iOS 6.0.1 は iPhone 3GS までサポートしますので、ここまで考慮すれば十分でしょう。
Android
今でも使われているかはわかりませんが、Android のかなり古いバージョンである 2.3 でも、最低限のセキュアな環境が保てます。ただし SNI はサポートされていませんので、実用になるかは謎です。
Android 4 まで行くと、そこそこ使える環境になりますので、Android も現時点ではあまり検討が必要な点はなさそうです。
ガラケー
ガラケーの場合、比較的古い環境を考慮する必要がありそうですが、ドコモの i-mode やソフトバンクでは、どのような暗号スイートをサポートしているのか、仕様では明らかではないようです。
au の EZweb に関しては「EZweb コンテンツ制作ガイド」(43ページ) にサポートする暗号スイートの記載があります。かなりしょぼいサポートしかありません。
とはいえ、まだまだレンタルサーバとしてはガラケーをサポートする必要はあるでしょうから、この EZweb の仕様をサポートすることを考慮すれば、他のキャリアもいけるのではないでしょうか。
また、これ以外にもレガシーなゲーム機などのブラウザからのアクセスを考慮すると、それなりの暗号スイートを選択する必要がありますが、これは一旦ガラケーの場合と同じと考えて、そちらをサポートすればいけるのではないかとしました。
サーバ側の設定
クライアント側の検討が済んだ所で、次はサーバ側の暗号スイートを考える必要があります。
サーバ側からの視点で考えると、ブラウザなどのクライアントを使って普通に SSL/TLS 通信を行う分には、ブラウザからわざわざ弱い暗号スイートを指定してくることはありませんので、サポートするブラウザを考慮すればサーバ側で特に考慮する点はないはずです。
しかし、悪意を持ってわざと弱い暗号スイートを使ってくるような場合を考えると、安全な暗号スイートでネゴシエーションが成立するよう、サーバ側で望ましい暗号スイートの順番を設定しておくのが良いでしょう。現在ではそのように設定するのが一般的になっていると思います。
例えば Apache HTTP Server では SSLHonorCipherOrder
という設定項目があり、これを on
にすると、クライアント側からのお伺いの順序でなく、サーバ側で設定された暗号スイートの順序が優先されます。
OpenSSL と暗号スイート
さて、それでは暗号スイートを設定していくことを考えます。
サーバ側の各種サーバで SSL/TLS のサポートを考えると、一般的には SSL/TLS 用のライブラリとしては OpenSSL を使用することになるでしょう (Windows でなければ)。
ここでややこしいのは、先程紹介した RFC で定義されている暗号スイートの名前と、OpenSSL で使う暗号スイートの名前が違うのです。
インストールされている OpenSSL で使える暗号スイートは以下のようなコマンドで調べられます。
$ openssl ciphers -v
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
:(略)
これは順に
- (OpenSSLでの)暗号スイートの名前
- プロトコルバージョン
- 鍵交換に使うアルゴリズム
- 認証に使うアルゴリズム
- データの暗号に使うアルゴリズム
- 検証に使うハッシュアルゴリズム
を表しています。これだけわかると RFC の暗号スイートと対比はできますが、一々照合するのは面倒ですね。この対比がコマンドかなにかでわかれば良いのですが、今のところ、この対応が載っているのは OpenSSL のマニュアルのみのようです。
- ciphersのCIPHER SUITE NAMESの項 (man ciphers でも調べられます)
また、同じマニュアルに載っていますが、OpenSSL では複数の暗号スイートをまとめて指定できる文字列が指定されています。
この OpenSSL の略称とその略称が指す実際の暗号スイートは OpenSSL のバージョンによってかなり変わっていますので、お使いの OpenSSL のバージョンを調べてから Web のマニュアルを参照するか、man ciphers
を実行するかで調べましょう。
この OpenSSL の Cipher を Apache だと SSLCipherSuite
に設定します。
# SSLv2 と SSLv3 は使わない
SSLProtocol all -SSLv2 -SSLv3
# CipherSuite として使うものを優先度の高い順に
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256
# サーバ側の CipherSuite の順序を強制する
SSLHonorCipherOrder On
(これは一例です)
PFS
ひとつだけ、今回検討していて改めて勉強になったものを少しご紹介。
スノーデン事件以来、「すべての暗号通信を保存してあること」に対する対策が話題になることがあるようです。「鍵交換」と「認証」に同じ鍵を使っていると、将来公開鍵暗号の秘密鍵が漏洩したり解読された場合、保存されている通信内容がすべてわかってしまいます。
これに対して
- 鍵交換と認証に別の鍵を使う
- 定期的に異なる鍵で鍵交換を行う
風にすると、通信内容が漏洩する可能性がかなり少なくなります。
もちろん、前述のようにレガシーな環境を考慮して暗号スイートを選んでますので、候補の中には上記は考慮されない暗号スイートがありますし、各ソフトウェアの作りや設定が原因で、必ずしも上記の条件を満たす暗号スイートの優先度が高くなるわけではないですが、新しいクライアント環境から接続された場合は、なるべくこの条件を満たすような暗号スイートが優先されるように設定を行うようにしました。
PFSについては以下が詳しいですのでご覧ください。
- TwitterのPerfect Forward Secrecy(PFS)対応 (自堕落な技術者の日記)
暗号スイートを設定する際に参考にする文書やサイト
どのようなクライアントからのアクセスを考慮し、どのように設定するのかは決まりましたが、これだけではどの暗号スイートを選択したらよいかがさっぱりわかりません。
このようなときに使える文書が IPA から出ています。
この文書には、要求仕様に応じて選択すべき暗号スイートが表形式で載っていますので、これを参考にしました (それ以外にも当文書に載ってるような知識は全部載っているので読むと良いでしょう)。
具体的には 3 章が「設定基準の概要」で要求仕様が定義されており、6 章が「暗号スイートの設定」となっており、そこには
- 高セキュリティ型の要求設定
- 推奨セキュリティ型の要求設定
- セキュリティ例外型の要求設定
という3つのパターンが示されています。
先に挙げたある程度レガシーな環境を考慮する場合は「セキュリティ例外型」が対象になりそうです。
と言ったものの、私も最初これを見ても何を設定すればよいのだ?となりました。ずっと色々と評価しているうちに理解できましたが。
そういう場合でも大丈夫です。@kjurさん の「HTTPS設定ファイル生成ツール」というサイトがあります。
- HTTPS設定ファイル生成ツール (この記事を書いている時点で 0.6(ベータ版))
いろいろなガイドラインをメニューで選択して、サーバソフトウェアを選択しすると、そのサーバソフトウェアの設定が生成されます。あとはそれをペタッとサーバの設定ファイルに貼り付ければ OK です。すばらしいですね。
オススメ設定から、前述の IPA のガイドラインのそれぞれの型に応じた設定、その他の色々な文書などによる設定が生成されます。もちろん、生成された設定をきちんと評価して問題がないことを確認した上で使用しています。
Web サーバ以外の設定
Web サーバの設定は前述の「HTTPS設定ファイル生成ツール」を使用して設定すれば要求を満たす設定ができそうなことがわかりました。
ただ、SSL/TLS を使用するのは Web サーバだけではありません。他のプロトコルのサーバの設定で行った検討も一部紹介しておきます。
postfix
まずは SMTP サーバの postfix です。
postfix で暗号スイートを設定する箇所は smtpd_tls_ciphers と smtpd_tls_mandatory_ciphers です。前者は "will use with opportunistic TLS encryption"、後者は "will use with mandatory TLS encryption" とあります。
"opportunistic" の設定 smtpd_tls_ciphers
は SMTP サーバに接続する際、必ずしも暗号化が必要でないケース、つまり 25 番ポートや 587 番ポートで STARTTLS を使って TLS 通信に入っていく際に使います。"mandatory" の設定 smtpd_tls_mandatory_ciphers
はかならず SSL/TLS を使う場合、つまり SMTPS で通信を行う場合の設定です。
このふたつで強度の差はつけず、同じにすることにしました。
この設定は postfix では、high
、medium
、low
、export
、null
という文字列を設定したいレヴェルに応じて設定します。この文字列を設定した場合にどのような暗号スイートが設定されるかは、postfix 内で定義されています。
この postfix が行っている定義を、例えば high
の場合 tls_high_cipherlist という設定を使って変更できます。しかし、postfix の文書には "You are strongly encouraged to not change this setting." とありましたので、こちらは変更しないように設定を行うように考えました。
postfix には、使いたくない暗号スイート指定する smtpd_tls_exclude_ciphers という設定がありますので、smtpd_tls_ciphers
と smtpd_tls_mandatory_ciphers
には high
を設定しながら、除外する暗号スイートを設定することにしました。
ちなみに high
などの、postfix の暗号スイートは src/global/mail_params.h
中で定義されています。関連するところだけ抜き出します (postfix 2.10.10 のコードです。バージョンによって定義は違います)。
#ifdef USE_TLS
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
#define PREFER_aNULL "aNULL:-aNULL:"
#else
#define PREFER_aNULL ""
#endif
#else
#define PREFER_aNULL ""
#endif
#define DEF_TLS_HIGH_CLIST PREFER_aNULL "ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH"
#define DEF_TLS_MEDIUM_CLIST PREFER_aNULL "ALL:!EXPORT:!LOW:+RC4:@STRENGTH"
#define DEF_TLS_LOW_CLIST PREFER_aNULL "ALL:!EXPORT:+RC4:@STRENGTH"
"@STRENGTH" が指定されているので、かならず暗号キーの長さ順に並んでしまいます。設定したい順には並ばないことがあるのですが、そこは目をつぶることにしました。
例えば high
という設定を行いつつ、"RC4" は不要だなと思ったら、
smtpd_tls_ciphers = high
smtpd_tls_exclude_ciphers = "!RC4"
というように設定すれば良いですね。
例示した定義は、postfix のバージョンによって変わっていますので、そこはお使いの postfix のバージョンのものをご覧ください。
dovecot
次は POP3/IMAP4 サーバの dovecot です。
postfix の検討が済めば、dovecot は簡単です。ユーザがメールの送信と受信に使うソフトウェアは同じですから、postfix と dovecot で違う暗号スイートを設定すると何かとマズいでしょう。
というわけで dovecot では postfix で設定する暗号スイートと同じにすれば良いだろうと考えました。postfix の方は前述のようにソースでどのような設定がされるのかを確認し、exclude に入れた暗号スイートの設定を "!" で足していけば OK です。
ssl_protocols = !SSLv2 !SSLv3
ssl_cipher_list = aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH:!RC4
ssl_prefer_server_ciphers = yes
ssl_options = no_compression
(一例です)
その他のソフトウェア
色々書いていたら長くなってきました。弊社サービスでは他にも SSL/TLS を使用するソフトウェアが使われていますが、ひとつひとつ書いていると長くなるのでこの辺にしておきます。
これまでに紹介したソフトウェアでも当てはまることですが、色々見て気づいたことをメモしておきますね。色々なソフトウェアでの SSL/TLS の設定を調査・検討していると、
- バージョンによって使える SSL/TLS のバージョンや設定できるオプションにかなり差があった
- バージョンのよってデフォルトの設定もかなり異なっていた
SSL/TLS を取り巻く環境が比較的変化してきているので、実装もそれに応じて進化しているのでしょうね。
例えばディストリビューション標準のパッケージを使う場合で、少し古いバージョンをあえて使う場合は、設定はそのバージョンのドキュメントを参照するなど、注意が必要です。
設定後の確認
さて、暗号スイートやその他の SSL/TLS 関連の設定をしたと言っても、それがちゃんと設定されており、期待通りの動きをしているかを確認しなければいけません。
Web サーバの場合は Qualys SSL Labs の SSL Server Test が使えます。
ホスト名を入れて Submit すると、暗号スイートの確認だけでなく、これまでに問題になった各種脆弱性に関してもチェックをしてくれて、Rating を出してくれます。さらには、各種 OS/ブラウザ環境で、SSL/TLS のどのバージョンと暗号スイートで接続されるかを一覧してくれます。
先にサポートする環境を考えましたが、このテストでそれが満たされているかどうかもチェックできるわけです。ありがたいサービスです。
しかし、このサービスは Web サーバの設定にしか使えません。さらに、デバッグ用途の場合、頻繁に利用したりするのもためらわれますね。公開のサービスであるところも少し気になる所です。
そういう場合に使えるソフトウェアがありましたので使用しました。
シェルスクリプトで書かれた SSL/TLS のチェックツールです。内部的には専用にビルドされた openssl コマンドを駆使して色々なチェックをしています。
先に紹介した SSL Server Test と同じようなテストを "ftp,smtp,pop3,imap,xmpp,telnet,ldap" に対しても行えます。https に関しては SSL Server Test のように OS/ブラウザ環境ごとにどのように接続されるのかまで表示してくれます。
オプションを指定すれば一部のテストだけでも実行できます。
実際に使う場合は Github上のリポジトリ からソースを持ってきても良いでしょう。
testssl.sh の実行
https のテストは簡単です。
$ ./testssl.sh www.example.com
のようにやれば OK です。ポートを指定する場合は www.example.com:443
みたいに指定します。
メールや FTP などの https 以外の場合も同様ですが、STARTSSL の場合は
$ ./testssl.sh -t ftp ftp.example.com:21
と -t
オプションでプロトコルを指定します。
他に、-E
オプションを指定すると、SSL/TLSの各バージョンごとに、どのような CipherSuite で繋げられるかをチェックしてくれます。
$ ./testssl.sh -E www.example.com
: (snip)
Testing all locally available ciphers per protocol against the server, ordered by encryption strength
Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits Cipher Suite Name (RFC)
---------------------------------------------------------------------------------------------------------------------------
SSLv2
SSLv3
TLS 1
xc014 ECDHE-RSA-AES256-SHA ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
x35 AES256-SHA RSA AES 256 TLS_RSA_WITH_AES_256_CBC_SHA
xc013 ECDHE-RSA-AES128-SHA ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
x2f AES128-SHA RSA AES 128 TLS_RSA_WITH_AES_128_CBC_SHA
x0a DES-CBC3-SHA RSA 3DES 168 TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS 1.1
xc014 ECDHE-RSA-AES256-SHA ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
x35 AES256-SHA RSA AES 256 TLS_RSA_WITH_AES_256_CBC_SHA
xc013 ECDHE-RSA-AES128-SHA ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
x2f AES128-SHA RSA AES 128 TLS_RSA_WITH_AES_128_CBC_SHA
x0a DES-CBC3-SHA RSA 3DES 168 TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS 1.2
xc030 ECDHE-RSA-AES256-GCM-SHA384 ECDH 256 AESGCM 256 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
xc028 ECDHE-RSA-AES256-SHA384 ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
xc014 ECDHE-RSA-AES256-SHA ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
x9d AES256-GCM-SHA384 RSA AESGCM 256 TLS_RSA_WITH_AES_256_GCM_SHA384
x3d AES256-SHA256 RSA AES 256 TLS_RSA_WITH_AES_256_CBC_SHA256
x35 AES256-SHA RSA AES 256 TLS_RSA_WITH_AES_256_CBC_SHA
xc02f ECDHE-RSA-AES128-GCM-SHA256 ECDH 256 AESGCM 128 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
xc027 ECDHE-RSA-AES128-SHA256 ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
xc013 ECDHE-RSA-AES128-SHA ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
x9c AES128-GCM-SHA256 RSA AESGCM 128 TLS_RSA_WITH_AES_128_GCM_SHA256
x3c AES128-SHA256 RSA AES 128 TLS_RSA_WITH_AES_128_CBC_SHA256
x2f AES128-SHA RSA AES 128 TLS_RSA_WITH_AES_128_CBC_SHA
x0a DES-CBC3-SHA RSA 3DES 168 TLS_RSA_WITH_3DES_EDE_CBC_SHA
: (snip)
CipherSuite のチェックをしている時は重宝しますね。あと、ローカルで使える CipherSuite を全部順番にチェックしてくれる -e
オプションも使いました。
最後に
この記事、当初はテストに便利だった testssl.sh を紹介しようと思って書き始めたのですが、思った以上に壮大な記事になってしまって、途中で書くのが面倒になってきました。
何か間違っていることを見つけたら優しく指摘してくださいね。
参考
- Documentation (OpenSSL)
- SSL/TLS暗号設定ガイドライン~安全なウェブサイトのために(暗号設定対策編) (IPA)
- 理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話 (けんごのお屋敷)
- 自堕落な技術者の日記