Help us understand the problem. What is going on with this article?

Qualys SSL Server Test で A+評価&満点を取得する (nginx)

Qualys SSL Server Test: https://www.ssllabs.com/ssltest/

ssltest.png

追記

  • 2018-12-05 OpenSSL v1.1.1 および TLS v1.3 用の対応を追記。
  • 2019-04-04 TLS_AES_128_GCM_SHA256 無効化について追記。
  • 2019-08-31 CBC 暗号スイートの無効化について追記。

注意

A+ 評価はいいとしても、満点を取ろうとすると、対応ブラウザが少なくなったり、サーバ負荷が高くなったりします。
実運用では A もしくは A+ 評価を目指すまでに留め、満点は趣味でやってみるくらいでいいかと思います。

証明書取得時の注意

もし満点を達成しようとするのであれば、証明書の鍵長を 4096bit 以上にする必要があります。
鍵長が 4096bit 以上でなければ、 Key Exchange が 100 になりません。

参考: Let’s EncryptでSSL/TLS証明書のRSA鍵長を4096ビットにする方法 | Webセキュリティの小部屋

SSL 関係の設定 (アルファベット順)

# HSTS を有効にする。
# これを有効にすると、クライアントは、初回接続以降は「必ず」 https で接続してくるようになる。
# 有効にしないと A が評価の上限になり、有効にすることで A+ 評価になる。
# 「必ず」 https 接続になっていいかどうかはサービスによるので、設定には注意すること。
add_header Strict-Transport-Security 'max-age=31536000;' always;

# HSTS Preload に登録する場合は、サブドメインも全て https に対応させ、
# ヘッダに includeSubDomains と preload も含めるようにする。
# @see https://hstspreload.org/
#add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;

# OCSP Stapling に対応するため、ネームサーバを設定する必要がある。
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# 証明書に対応する公開鍵を指定。
# 自分自身の証明書~中間証明書~ルート証明書の一つ前 までの順に結合したファイルを指定する。
# COMODO の PositiveSSL ならば、送付される証明書に含まれる
# {your domain}.crt
# COMODORSADomainValidationSecureServerCA.crt
# COMODORSAAddTrustCA.crt
# の 3 つを、この順に結合する。
# 例)
# cat {your domain}.crt \
#   COMODORSADomainValidationSecureServerCA.crt \
#   COMODORSAAddTrustCA.crt \
#   > server.crt
#
# Let's Encrypt なら fullchain.pem を指定する。
ssl_certificate /path/to/fullchain.pem;

# 証明書に対応する秘密鍵を指定。
ssl_certificate_key /path/to/privkey.pem;

# RSA は WEAK と判定される。
ssl_ciphers 'HIGH !aNULL !eNULL !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED !RSA';

# Cipher Strength を 100 にするためには AES128 など 128bit 以下の暗号を除外する必要がある。
#ssl_ciphers 'HIGH !aNULL !eNULL !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED !RSA !AES128';

# OpenSSL v1.1.1 以上では !ARIA128 も追加で除外する必要がある。
# OpenSSL v1.1.1 以上で、かつ TLSv1.3 を有効にした場合、 /etc/ssl/openssl.cnf にも修正が必要 (後述) 。
#ssl_ciphers 'HIGH !aNULL !eNULL !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED !RSA !AES128 !ARIA128';

# 2019-08-31 時点、 CBC 暗号スイートが WEAK と判定される。 (ただしスコアに影響はでない)
# CBC を除外するには !SHA1 !SHA256 !SHA384 を追加する。
# なお GCM や CHACHA20 暗号スイートの中にも SHA* という名前を持つものがあるが、これらは除外されない。
# 参考: https://security.stackexchange.com/a/207812
# CBC が WEAK となった経緯: https://security.stackexchange.com/questions/210072/why-does-ssl-labs-now-consider-cbc-suites-weak
#ssl_ciphers 'HIGH !aNULL !eNULL !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED !RSA !AES128 !ARIA128 !SHA1 !SHA256 !SHA384';

# DHE 暗号方式のためのパラメータファイルを指定する。
# このファイルは `openssl dhparam 2048 -out dhparam.pem` コマンドで生成できる。
# 2048bit 以上が推奨されている。
# A 評価にするためには 2048bit 以上で作成する必要がある。
# Key Exchange を 100 にするためには 4096bit 以上で作成する必要がある。
ssl_dhparam /path/to/dhparam.pem;

# Key Exchange を 100 にするためには secp384r1 を指定することが必要。
# 指定しなくても A (A+) 評価は可能。
#ssl_ecdh_curve secp384r1;

# どの暗号化スイートを使うか、サーバ側が決定するようにする。
# クライアントが脆弱な暗号化スイートを使おうとすることを防ぐ。
ssl_prefer_server_ciphers on;

# ssl_protocols を絞ると、対応するブラウザが減る。
# https://ja.wikipedia.org/wiki/Template:%E3%82%A6%E3%82%A7%E3%83%96%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BTLS/SSL%E3%81%AE%E5%AF%BE%E5%BF%9C%E7%8A%B6%E6%B3%81%E3%81%AE%E5%A4%89%E5%8C%96
# A 評価にするなら TLSv1 以上に。(ほとんどの携帯電話が非対応に)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

# Protocol Support を 100 点にするなら TLSv1.2 のみに。 (IE10 以下や Android 4 以下などが非対応に)
# OpenSSL v1.1.1 以上であれば、 TLSv1.3 を追加しても良い。
#ssl_protocols TLSv1.2;

# Session resumption (caching) を有効にする。
ssl_session_cache shared:SSL:10m;

# OCSP Staplingを有効にする。
# OpenSSL のバージョンが古すぎると、 "ssl_stapling" ignored というエラーが出る。
# OpenSSL のバージョンをアップデートすること。
# 例えば CentOS 5 だとアップデートしきっても古いままなので、有効にはできない。
ssl_stapling on;
ssl_stapling_verify on;

# OCSP Stapling で使用する証明書。
# 中間証明書~ルート証明書の順に結合したファイルを指定する。
# COMODO の PositiveSSL ならば、送付される証明書に含まれる
# COMODORSADomainValidationSecureServerCA.crt
# COMODORSAAddTrustCA.crt
# AddTrustExternalCARoot.crt
# の 3 つを、この順に結合する。
# 例)
# cat COMODORSADomainValidationSecureServerCA.crt \
#   COMODORSAAddTrustCA.crt \
#   AddTrustExternalCARoot.crt \
#   > trusted.crt
#
# Let's Encrypt なら chain.pem を指定する。
ssl_trusted_certificate /path/to/chain.pem;

OpenSSL >= v1.1.1 かつ TLS v1.3 を有効にした状態で満点を取得する場合

OpenSSL v1.1.1 で TLS v1.3 を有効にすると

  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_GCM_SHA256

という暗号スイートが TLS v1.3 用に追加されます。
このうち TLS_AES_128_GCM_SHA256 は鍵長が 128bit であるため、 Cipher Strength のスコアが落ちます。

TLS_AES_128_GCM_SHA256 を無効化すればいいのですが、 nginx からでは TLS v1.3 用の暗号スイートを設定できません。
※ TLS v1.3 で使用される暗号スイートは、それ以外の暗号スイートと全く別に管理されるため、 ssl_ciphers で設定できません。
※ 2018-12-05 nginx v1.15.7 時点。

TLS v1.3 用の暗号スイートは openssl.cnf (通常 /etc/ssl/openssl.cnf にあるはず) を修正することで設定できます。

openssl.cnf を開き、最上部に以下の通り追記します。

openssl_conf = default_conf

[default_conf]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
ciphersuites = TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384

ciphersuites に TLS v1.3 で使用する暗号スイートを列挙します。
修正後、 nginx を再起動 (reload ではなく) することで適用されます。

参考: #1529 (Could not configure TLS1.3 ciphers in OpenSSL 1.1.1 pre4) – nginx

なおスコアには関係しませんが、 AES より ChaCha のほうがパフォーマンスが良いらしいので (未検証) 、 ChaCha を先に指定しています。

参考: #1445 (OpenSSL - ChaCha prioritized - Nginx enhancement) – nginx
参考: Use ChaCha only if prioritized by clnt by tmshort · Pull Request #4436 · openssl/openssl
参考: Do the ChaCha: better mobile performance with cryptography

TLS_AES_128_GCM_SHA256 無効化について

TLS_AES_128_GCM_SHA256 を無効化すると、 Qualys SSL Server Test で以下のようなエラーメッセージが表示されます。(2019-04-04 時点)

This server does not support the mandatory cipher suite TLS_AES_128_GCM_SHA256 for TLS 1.3. See RFC 8446 for details.

これは、 TLS v1.3 の仕様上 TLS_AES_128_GCM_SHA256 が必須であるためです。
しかし、 TLS_AES_128_GCM_SHA256 が有効だと Cipher Strength のスコアは落ちます。
このあたりは調整中らしいです。(See https://github.com/ssllabs/ssllabs-scan/issues/636#issuecomment-461727819)

仕様を正しく実装することのほうが重要かと思いますので、満点を目指すのはやはり趣味・実験・自己満足に収めたほうがいいかと思います。

ooxif
フリーランスエンジニア。 インフラ (AWS/国内クラウド系)、サーバサイド (Rails/NodeJS/PHP) 、クライアントサイド (React/Vue/jQuery) 、アプリ (iOS/Android) なフルスタック。 CTO 経験あり (1 社 6 年) 。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした