2015年3月20日
NginxでHTTPS : ゼロから始めてSSLの評価をA+にするまで Part 1
(2015-02-01)by Julian Simioni
本記事は、原著者の許諾のもとに翻訳・掲載しております。
数年前、Webは全体的に暗号化されていませんでした。HTTPSはWebページの最も重要な部分だけのために確保されていました。暗号化が必要なのは大切なユーザデータだけで、Webページの公開される部分は暗号化せずに送ってもいいということで意見が一致していました。
しかし、 今は 状況 が 違います 。現在では、どんなWebトラフィックでも暗号化されていないのは良くないということが分かっているので、Webサイトを運営する誰もがコンテンツに関係なく強固なHTTPSを設定しなければなりません。
お恥ずかしい話ですが、私自身のWebサイトは2年近くも全くHTTPSをサポートしていませんでした ^(1) 。
Eric Mill の 今すぐ無料でHTTPSに切り替えよう という素晴らしい記事が最終的に私に喝を入れてくれました。私は休暇中、HTTPSをセットアップして Qualys SSL Report で A+ を獲得できるように設定を微調整することに時間を費やしました。
かなりの研究が必要でしたが、ほぼ最適な設定が決まったので、Nginx上でそれを実現した方法を共有したいと思います。実際の構成に加えて、安全な設定における全てのコンポーネントの動作と、なぜその設定が最適なのかについて説明します。
この記事はパート1です。ここでは基礎を紹介し、証明書をセットアップしていきます。
パート2 では、Nginxの設定をもっと説明し、特にciphersuiteのセットアップについて見ていきます。
初期設定: 自己署名証明書を使用
HTTPSを有効にするだけなら要求されるものはほとんどありませんが、サーバに暗号化鍵と証明書ファイルを設定する必要があります。OpenSSLがインストールされたマシンであれば、両方とも素早く簡単に作成できます。
このような自己署名証明書は真の安全を保証するものではありませんが ^(2) 、本物の証明書を生成する前に一度セットアップしてみたら、大まかなプロセスを理解できるでしょう。そうすれば、早い段階でできるだけ多くの問題を解決できるので、やってみる価値はあります。
自己署名証明書の生成に関しては 既に あまりにも 多くの チュートリアル があるので、ここでは詳細を省きます。次のような簡単なコマンドで十分でしょう。
mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
openssl req -new -x509 -sha256 -newkey rsa:2048 -days 365 -nodes -out /etc/nginx/ssl/nginx.pem -keyout /etc/nginx/ssl/nginx.key
基本的なSSL ^(3) 向けのNginxの設定部分も簡単です。以下の設定をnginxファイルに追加します。
server {
# [...]
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/nginx.pem;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
# [...]
}
(上記のコードスニペットは両方とも前述のリンク先 Linode認証ガイド からの応用です。最高のチュートリアルの1つです)
これで有効な証明書が用意できたので、Nginxを再起動すればサイトがHTTPS経由でロードされるようになります。ただ、証明書は自己署名なのでおそらく厄介な警告が出るでしょう。そこで、完全な証明書を使ってやってみる前に、重要な機能に関していくつか初期チェックを行います。
OpenSSLの最新バージョンを確認
OpenSSL ライブラリは、ほとんどどこにでもあるSSLとTLSライブラリのようなもので、Nginxを含むほぼ全てのWebサーバで使用されています。OpenSSLのバージョンが古い場合、セキュリティの脆弱性が いくつも あるかもしれません。
中でも最悪なのは、もちろん Heartbleed です。 Webサーバの秘密鍵を含む あらゆる種類のデータが漏えいしてしまう恐れがあります。Heartbleedは2014年4月に初めて公表されましたが、多くのWebサイトは 脆弱なまま です。そんなWebサイトにしてはいけません。
OpenSSLのWebサイトで最新の安定したバージョンを確認して、自分のサイトでその最新バージョンが使われているか確認してください。
$ openssl version
OpenSSL 1.0.1k 8 Jan 2015
2048ビットおよびSHA256の署名による証明書の作成を確認
自己署名証明書はコストやダウンタイムを発生させずに簡単に再生成できるので、この段階で証明書の設定の問題を解決しておく方がいいと思います。無料のStartSSLの証明書ですら取り消すのに 3,000円近くかかる ため、間違えると後でもっとコストと時間がかかります。
証明書を設定する際に最も重要なのが、どのハッシュアルゴリズムを使ってフィンガープリントを生成するかということです。つい最近まで、ほとんどの証明書は SHA1 を使って署名されていました。しかし Google や Microsoft といった企業や多くの[セキュリティ研究者] (https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html)が今や、SHA1の利用を速やかにやめるよう強く推奨しています。コンピュータの処理能力が進化するにつれて、SHA1は危険なレベルにまで安全性が下がってきています。今後新たに発行される証明書は、SHA1ではなく SHA256 で署名されなければなりません。
現時点においては、SHA1に対する実際の攻撃が行われたという事例は報告されていません。しかしChromeや Firefox でも早々に、SHA1で署名された証明書については警告またはエラーが出されるようになります。要するに、今後はSHA256以外のハッシュ関数で新しい証明書を生成してはいけないのです。
RSA暗号の鍵のサイズについても同様です。現在、RSAでは2048ビット鍵が 最適 ^(4) となっています。現在の環境は、十分にパワフルなコンピュータネットワークがあれば、1024ビットでの証明書でも 解読できる レベルに達しています。そしてSHA1に対する対応と同じように、ブラウザ側はこれ以上1024ビット鍵が使われることを防ごうとしています。例えばMozillaは、2014年9月にリリースされたFirefox32では、信頼される証明書リストから1024ビットの認証局鍵を 除きました 。
先ほど紹介したコマンドを使って自己署名証明書を生成すれば、SHA256と2048ビットRSA鍵に対応しているはずです。次のコマンドを使えば確認できます。
openssl x509 -in /etc/nginx/ssl/nginx.pem -text -noout | grep "Signature\|Public-Key"
# Should give the following output:
# Signature Algorithm: sha256WithRSAEncryption
# Public-Key: (2048 bit)
# Signature Algorithm: sha256WithRSAEncryption
(ServerFaultで見つけた こちら の回答を応用しました)
万が一、 sha1WithRSAEncryption
や (1024 bit)
という結果が出てきた場合は最初に戻ってもう一度正しい設定を確認し、再度証明書を生成してください。
コンテンツの混在に関する警告を確認
この段階では、たとえ初期リクエストがHTTPS経由になっていても、JavaScriptやCSS、画像といったWebサイト上のリソースはまだHTTP経由でロードされている可能性が非常に高くなっています。
コンテンツの混在を示す警告の例(Firefox版)
これまでは、ログインページやフォームの送信といったWebサイトの重要な部分だけにHTTPSを使うだけで十分とみなされていましたが、今や状況は変わりました。現在のブラウザは、より危険性を増した様々なコンテンツの混在(つまり、JavaScriptとCSSファイルのこと)を ブロックする ようになりました。
これはユーザにとって、大変優れたセキュリティ面での利点となります。なぜならこうしたコンテンツが混在したファイルは、通信されている間に修正を加えられ、結果 深刻な被害 をもたらす可能性があるからです。大切なユーザ情報が盗まれたり、システムにマルウェアをしかけられたり、といったことが起こりうるのです。
コンテンツの混在に対する警告を修正する方法は各Webサイトのコードによって様々ですが、たいていの場合リンクの頭を http://
から https://
に変更するような単純なものです。他のサーバからリソースをロードするようなリンクについても同様です。万が一サーバがHTTPSをまだサポートしていない場合、そのサーバからのリソースは完全に取り除くか、可能であれば自分でホストする必要があります。
どうしてもHTTPとHTTPS双方をサポートする必要がある場合、 protocol-relative URL といった方法もありますが、お勧めできるものではありません。
実践:認証局署名の証明書利用
基本的な課題がクリアできたところで、ブラウザが信頼していると実際に認識できる証明書を生成してみましょう。この作業はいくつかの理由によってはちょっとした長さのプロセスになります。まずは事前に必要とされる事項を確認しましょう。
- 認証局(CA)のアカウント
webmaster@yourdomain.com
、またはpostmaster@yourdomain.com
、またはドメインのDNSエントリにあるSOAレコードにリストされているメールアドレスのいずれか、へのアクセス- 証明書リクエスト(CSR)ファイル
上記の1はおそらく、普通のWebページ用にアカウントを取得するよりは少し面倒な手続きとなるでしょうが、なんとかなるはずです。セキュリティ上の懸念を考慮しているので仕方がないことです。まだどの認証局を使うか決めていなければ、 StartSSL が良いでしょう。機能も優れていますし無料です。有料サービスを選ぶならば Verisign か Comodo があります。 GoDaddyはお勧めできません 。
上記の2は、それぞれのDNSセットアップの状況に応じてやり方が大きく異なるので、ここでは詳細には触れません。DNSが適切に設定されていないと、DNSエントリに変更を反映するのに数時間かかることもありますので、すぐ作業に取り掛かってください。
しかし私のように、 FastMail で自分のドメインを使ってメールを管理している場合は、FastMailが既に全てのセットアップを行ってくれています。もしFastMailを使って いない のでしたら、実に素晴らしいサービスなのでぜひ使用することをお勧めします。
1と2のステップを完了したらCSRを作成できます。このファイルには、証明書を必要とするドメインやオプションなどの詳細が記述されています。認証局の中には、ブラウザで秘密鍵やCSRを生成する”手助け”をしてくれるものもあります。既に秘密鍵の生成は済んでいるので、認証局の手助けは断ります。セキュリティ違反となる恐れがあるため、必要ありません。
次のコマンドを使うと、優れたCSRが生成されます。
openssl req -new -sha256 -key /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/yourwebsite.com.csr
認証局のWebページにあるCSR用のフォームに生成した内容を貼り付けると、証明書が返送されます。返送された証明書は、 /etc/nginx/ssl/yourwebsite.com.crt
のような、自分のサーバ上の安全な場所に格納しておきましょう。
もしStartSSLを使うことになった場合は、この記事の上の方にリンクを貼ってあるErik Millの チュートリアル を参照してください。全ての手順を完璧に網羅してくれています。
自己署名証明書の時と同じように、最初に、認証局からした新しい鍵とCRTファイルをNginxに設定するだけで機能するはずです ^(5) 。おめでとうございます! これであなたのWebサーバは有効な証明書を取得し、TLSを使えるようになりました。
もし今すぐWebサイトでSSL Labsのテストを実施したら、以下のような結果が表示されるでしょう。
悪くはありませんが、Nginxのデフォルトの設定ではCの評価までしか獲得できません。これは、ぎりぎり合格といったレベルです。次回、A+の評価を得るためにはNginxにどのような設定が必要なのか見ていきましょう。お楽しみに!
-
私のサーバはその間ずっと、HTTPSやポート443へのリクエストに対してレスポンスを返すことさえしませんでした。 ↩
-
私がSSLと言う場合に 実際に指しているのは TLSです。SSLとTLSは、どちらも同じ歴史的背景を共有しています。TLSは新バージョンの名前であるというだけです。SSLのバージョンは全て、今では時代遅れになってしまいましたが、名前だけは残っているのです。 ↩
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa