NginxでのSSL設定(もうちょっと詳しく)

公開日: : 最終更新日:2014/09/06 サーバ ,

単に、

とするだけではなくて…というエントリ。
ちなみにRHEL系を想定して書いている。

nginxの確認

nginxをmakeするときに「–with-openssl=」オプションを使わずにsslに対応してあることを確認しておく。

次にopensslのバージョン確認。

※ 「xxxxxxx」はPlatform名。
バージョンが1.0.1i以上であることを確認しておく。

もしopensslのバージョンが1.0.1i未満なら、

と、実行してバージョンアップしておく。

もし、「–with-openssl=」オプション付きでnginxをmakeしてある場合は、新しいバージョンのopensslのソースを準備してnginxを作成し直すこと。

暗号化スイートの設定

対応する暗号化スイートは、ssl_ciphersディレクティブで設定するが、ネット上の多くの情報はこれらの記載がないものが多い。
つまりは、クライアントサイドが指定した暗号化スイートで暗号化していることになる。
安全なSSL接続を目指すなら、サーバサイドで指定した暗号化スイートで通信を暗号化するほうが望ましい。
ということで、まずは世の中のデ・ファクト・スタンダードはどうなっているのか調べてみたが、MozillaがMozilla Web siteに使用する、HTTPSの推奨設定が一番多くのサイトでの引用元になっているようだ。

ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK

と、一般的な用途として上記が記載されている。

ちなみに、上記の記載の仕方だが、

  • 優先順位順に記載する
  • 複数指定時のデリミタは「:」(コロン)を利用する
  • プレフィクスに「!」(エクスクラメーション)を指定した場合は除外対象の指定になる

というルールに従って記述されている。

実際には接続される環境(端末含む)を考えて、設定するのが良い。
例えばXPのIE6とか、すでにサポート外の環境を外すならRC4使っている幾つかは切ってOKなのだが、世の中にはそんな環境もまだ残っているようなので、そのあたりも入れておくのが無難とか。
今回は上記の推奨設定を利用しようと思う。
ちなみに、ECDHEとかDHEとか、それぞれの暗号化スイートの説明は長くなるので省略。
気になる人、知らない人は別途調べて下さいw

ということで、今回のssl_ciphersディレクティブの指定は以下のようにした。

SSL/TLSプロトコルの指定

SSL/TLSプロトコル(暗号化方式)の指定は、ssl_protocolsディレクティブで指定する。
幾つか指定できるプロトコルはあるが、SSLv2プロトコルは古いバージョンで定義されたプロトコルで現在は非推奨なので外すのが鉄板。
またSSLv3も主要な機能が不足していて、事実上すべてのクライアントがTLS1.0のサポートに変わっている。
そのため、余程の理由がない限りはSSLv3もサポートするべきではない。
このあたりの情報は、

のリンク先PDF資料に記載がある。
ここでも、古い環境であるIE6.0のデフォルトの設定では厄介なことに「TLS 1.0を使用する」が選択されていなかったりするので、SSLv3は入れておく必要がある…とか、接続される環境を考える必要がある。

ということで、今回のssl_protocolsディレクティブの指定は以下のようにした。

サーバ側指定の暗号化プロトコルの優先設定

ここまで暗号化スイートと暗号化方式の指定を、それぞれssl_ciphers、ssl_protocolsディレクティブで指定したが、これらが優先して機能しなくては意味がない。
nginxではssl_prefer_server_ciphersというディレクティブで、サーバ指定の暗号化スイートが優先されるように設定する。

ということで、以下のように設定した。

DH鍵交換に使用するパラメータファイル

次に、暗号化スイートの設定内で指定したものにDH(Diffie-Hellman)鍵交換を含む暗号化スイート(DHE-RSA-AES128-GCM-SHA256とか)を指定した場合、鍵交換において使用されるパラメータファイルを作成し、指定しなくてはならない。
今回は幾つか指定しているので、このファイルを作成する必要がある。
ここでも環境を想定しないとならない。
例えば JDK6では鍵長が1024bitまでしかサポートされていないとか。
これら環境から接続がある場合は1024bit長でパラメータファイルを作成する。
作成方法は以下のようにopensslコマンドで作成する。

ということで、今回はセキュリティレベルは落ちるものの1024bitで鍵ファイルを以下のように作成した。

作成には、少々時間がかかるかも知れない。
このあたりは出力されているメッセージの通り。

TLS Session Ticket対応

サーバとクライアント間の暗号化に必要な通信処理はCPUやネットワークに対して負荷の高い処理であることは言わなくてもわかるだろう。
なのでSSL通信は比較的遅くなりがちではある。
TLS Session Ticketに対応していない通信の場合、この暗号化に必要な通信処理が完了した後の次回以降の通信では、クライアントがSession IDをサーバに渡し、サーバ側ではSession IDをキーにして一致したSessionをステート管理しながら使い回すことで処理回数を減らすようなセッションキャッシュや、場合によっては初めから必要な通信処理をやり直す必要がある。
TLS Session Ticketに対応した場合、Session Ticketを発行するための鍵をサーバとクライアント間で共有しておき、この鍵で作成したTicketでステート管理を行う。
つまりステートをクライアント側に渡すことでサーバ側でステート管理をしないし、サーバが受け取ったTicketで以前のSessionを見つけ出すことができれば、一致したSessionを利用するため負荷の高い処理を省略することができる。
負荷が下がるのであれば入れない、対応しない手は無い。

ということで、今回は以下のように設定した。

上記のそれぞれのディレクティブについては、このセクションの最初の文章にあるような、SSL/TLSセッションのハンドシェイクや仕組みが理解出来ていれば、それぞれが何を指定しているかは、nginxを知らなくとも何となくわかると思う。

以下に順番に説明していく。
ssl_session_ticket_keyでは、Ticket発行の際に利用されるクライアントとサーバとの間で交換される鍵を指定する。
これは以下の様に、opensslコマンドで48Byte長のランダムデータでを作成する。

ssl_session_cacheとssl_session_timeoutディレクティブではセッションキャッシュする方法やTimeout値を指定する。
このあたりはNginxのチューニングの際には見直しを掛けている人も多いはず。
チューニングについては、このあたりを参照のこと。
ディレクティブのドキュメントはここのあたり。

ちなみに、ちょうどこの記事を下書きしているチョット前にAWSがELBでこのあたりもサポートした。

確認

ということで、ここまでの設定を以下にまとめてみる。

上記をnginxのserver設定に追記し、nginxを再起動する。

確認は同じサーバで実行しても良いが、今回は設定したサーバ外から設定を確認することにする。
まずは、対応しているciphersの確認。
便利なツールでcipherscanというのがある。
これを利用する準備を行う。

単なるBash ScriptなのでGitでcloneするだけで利用可能。
cloneに時間がかかるのはopensslも内包しているから。

で、実際に確認してみる。

nginxのssl_ciphersディレクティブで指定した暗号化スイートが表示されていることを確認する。
このcipherscanコマンドは、総当りでopensslコマンドを発行して確認しているので、自身の管理していない外部サイトに対して実行する場合は注意すること。
次に、TLS Session Ticketについても上記のcipherscanコマンドで確認できる。

ちなみにopensslコマンドでTLS Session Ticketの確認をする場合は以下のようにする。

上記のように実行して何も表示されない場合は、TLS Session Ticketに対応出来ていないので設定を見直す。

Adレクタングル[忍者ADMAX]

関連記事

nginx_logo

ngx_pagespeed対応版nginxパッケージの作成(RHEL系)

インストールされているミドルウェアやアプリケーションはパッケージ化されていると、管理上において非常に

記事を読む

no image

dstat+td-agent+ElasticSearch+Graphite+Grafana on Amazon Linux

タイトルが異様に長いけど、業務でタイトルのようなパフォーマンス監視環境を作った。 難易度はそんなに

記事を読む

nginx_logo

NginxでのOCSP Stapling対応設定

意外にハマったのでメモ。 OCSPとは OCSP(Online Certificate Stat

記事を読む

aws_logo._V400518270_

AWSでRoute 53をPrivate DNSとしてVPC内で使ってみた

Amazon Web Services(AWS)のRoute 53がVPC内でのPrivate Ho

記事を読む

RabbitMQ.sh-600x600

EC2上のRabbitMQをMulti-AZで冗長化

うーん。。。ハマった。 多分、もっとErlangのこと把握できていればよかったのだろうけど。

記事を読む

コメントを残す

Adレクタングル[忍者ADMAX]

RabbitMQ.sh-600x600
EC2上のRabbitMQをMulti-AZで冗長化

うーん。。。ハマった。 多分、もっとErlangのこと把握できていれ

aws_logo._V400518270_
AWSでRoute 53をPrivate DNSとしてVPC内で使ってみた

Amazon Web Services(AWS)のRoute 53がV

nginx_logo
NginxでのSSL設定(もうちょっと詳しく)

単に、 とするだけではなくて…というエントリ。 ちなみにRHEL系を

→もっと見る

  • Author:
    hiro
    Work:
    インフラエンジニア
    Brief History:
    新卒後、ソフトハウスにて受託開発を中心に開発エンジニアを始める。
    数年前から現在はITインフラが専門。
PAGE TOP ↑