今のうちに見直しておきたいnginx設定集 【セキュリティ編】

こんにちは、Cluexの高橋です。

先日EC2サーバーのOSを新しいものにしまして、その時にサーバーのテストを簡単に行ってくれるQualys SSL Labsで移行前のサーバーをテストしてみたところ、C判定が出てしまったので、nginxの設定も全体的に見直してみました。

     

イメージはこんな感じです f:id:cluex-developers:20160813190017p:plain    

テストしたのはこちら「Qualys SSL Labs」 www.ssllabs.com    

ということで今回はnginxの設定に関してセキュリティ関連でやっておくべき設定集をまとめました。      

nginxのバージョン情報を隠す

nginxのバーション情報を隠蔽します。

server {
  # ~~
  server_tokens off;
  # ~~
}

   

SSL通信に使用するプロトコルを指定する

SSLv2やSSLv3はダウングレード攻撃やPOODLEなどへの脆弱性があるのでTLSのみ許可します。

server {
  # ~~
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  # ~~
}

   

暗号化スイートの設定

SSLの暗号化にする暗号化スイートを明示的に指定し、クライアントサイドで指定した暗号化をしないようにすることで、通信をよりセキュアにすることができます。 ちなみにssl_ciphersの設定方法としては、「:」をデリミタとして使用し、「!」をプレフィックスでつけることで除外対象となります。  

詳細な暗号化スイートの設定内容はこちらのサイトを参考にさせていただきました。

Strong SSL Security on nginx - Raymii.org    

おすすめの設定がこちら。

server {
  # ~~
  ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
  # ~~
}

 

IE6/WinXP などにも対応したいと言う方にはこちらの設定がおすすめとのことですが、SSL3.0などを使用できない設定にしているので今回は特にIE6を気にする必要はないかと思います。

server {
  # ~~

  ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

  # ~~
}

   

サーバーの暗号化設定の優先

先ほどのサーバー側で指定した暗号化スイートを優先して使用するようにします。

server {
  # ~~
  ssl_prefer_server_ciphers on;
  # ~~
}

   

Http Strinct Transport Security(HSTS)ヘッダの追加

サーバーからStrict Transport Securityヘッダを返すことで常にHTTPSで通信を行うようにし、中間者攻撃を防ぎます。これを使用するには Nginxのngx_http_headers_moduleが必要になります。

add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';

developer.mozilla.org

   

ちなみにpreloadオプションを使用したい場合は、こちらでドメインを登録しておくと宜しいかと思います。

HSTS Preload List Submission

こちらに登録するには下記の要件を満たす必要があります。

Submission Requirements

If a site sends the preload directive in an HSTS header, it is considered be requesting inclusion in the preload list and may be submitted via the form on this site.

In order to be accepted to the HSTS preload list through this form, your site must satisfy the following set of requirements:

  1. Serve a valid certificate.

  2. Redirect from HTTP to HTTPS on the same host.

  3. Serve all subdomains over HTTPS.

 ・In particular, you must support HTTPS for the www subdomain if a DNS record for that subdomain exists.

  1. Serve an HSTS header on the base domain for HTTPS requests:

 ・The max-age must be at least eighteen weeks (10886400 seconds).

 ・The includeSubDomains directive must be specified.

 ・The preload directive must be specified.

If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (rather than the page it redirects to).      

preloadを指定する場合はこんな感じです。

add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;preload';

       

DH鍵交換時のKeyの強化

TLSプロトコルで採用されているDiffie-Hellman鍵交換は512bitもしくは1024bit以下のDHパラメータにおいてLogjam攻撃を受ける可能性があり、これを防ぐにはDHパラメータに2048bitのものを使用することが望ましいとされています。

   

Diffie-Hellman鍵交換による暗号化時にnginxのデフォルトでは1024ビットの鍵を使用しますが、Google ChromeMozilla Firefoxなどの主要なブラウザでは「最低でも」1024ビット以上のものを使用するよう推奨しており、できれば2048bitのものを独自生成して使用するのが好ましいかと思います。

  一般的なwebサイトでは2048bitもしくは4096bitでpemを作っておくといいようです。

   

まずはpemファイルの作成

$ cd /etc/ssl/certs
$ openssl dhparam -out dhparam.pem 4096

こちらがnginxのconfファイルに追加する内容。

server {
  # ~~
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
  # ~~
}

     

OCSPステープリング(OCSP Stapling)の設定

OCSP(Online Certificate Status Protocol)はSSL/TLS通信の時に証明書が失効していないかを確認するために使用されています。 通常はSSL通信を行う際はクライアント側がこのOSCPを使用してサーバー証明書の正当性を確認する必要がありますが、サーバー側で事前にこの処理を行うことでクライアント側で行う必要がなくなるのでHTTPS通信の開始を高速化できます。

 

具体的にはOCSPステープリングによってクライアント側ではなくサーバー側でOCSPによるサーバー署名書の確認を行い、その結果をクライアントへのレスポンスと一緒に送るようにすることで、これを実現しています。

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/cert/trustchain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s

ssl_staplingを使用するにはDNSリゾルバを resolverディレクティブにて指定する必要があります。googleのパブリックDNSサーバーが使用されることが多いようです。    

X-Frame-Options

レスポンスヘッダにX-Frame-Optionsを設定することでブラウザがiframeなどの内部に自身のサイトを表示を許可するかを設定できます。DENYもしくはSAMEORIGINを指定することで自分のサイトのコンテンツが他のサイトに埋め込まれないように設定でき、クリックジャッキング攻撃を防ぐことができます。

add_header X-Frame-Options SAMEORIGIN;

 

X-XSS-Protection

XSSに対するフィルタ機能を有効化

add_header X-XSS-Protection "1; mode=block";

 

X-Content-Type-Options

Content-Typeに一致しない処理は行わないようにさせることでXSSなどを防ぎます。

add_header X-Content-Type-Options nosniff;

これが設定されていない場合、例えば Content-type="text/plain" のファイルでも、その中にjavascriptのソースがあるとブラウザによって実行される可能性があります。

     

再度テストした結果は・・・

f:id:cluex-developers:20160813185943p:plain    

当時の設定では上記の幾つかはまだ設定していないものもあるのでA+の評価をとることができなかったので、今回あげたものも含めてさらにサーバー周りを強化していきたいなと思います。

     

ちなみにMozilla Foundationが公開しているwebサーバーのConfig Generatorがあるので、そちらで基本的な設定を確認できるので、気になる方はお使いになってみるいいかと思います。

Generate Mozilla Security Recommended Web Server Configuration Files

       

余談)Cluexではエンジニアの方を探しています!

 

See more at cluex.co.jp