Blogを開設して早いもので半年が経過しました。当サイトは開設時より全面SSL化をしてきました。開設当初は環境設定も試行錯誤の連続でしたが最近は大分落ち着いてきました。そこで外部のSSL評価を受けてみようと思いたち早速テストを受けたところ評価結果はなんとFでした(ショック!)これはいかんとネットで先人の情報を収集し設定を変更したところなんとかA+を獲得することができました。その顛末と情報収集の際に新たに知り得たnginxのSSL推奨設定を共有します。前提の環境はCentos7.2上のnginx。SSLサーバ証明書はlet’encryptから取得しています。尚、上記前提条件が不明の場合には、当サイト内のnginx導入記事、let’encrypt導入記事を参照ください。
目次
1.初回評価結果とSSL設定
(1)初回評価結果
以下はservertest1回目の評価結果です。…..Fです。
結果を良く見ると、緑の棒グラフのKeyExchange項目が0です。
Fの下2行目に桃色の背景で以下の指摘があります。
This server supports anonymous (insecure) suites (see below for details). Grade set to F
「匿名アクセスをサポートしているのでFグレードです」とのこと。
(2)SSL設定
以下はF評価を頂いた時のnginx.confファイル設定抜粋です。
1 2 3 4 5 6 7 8 9 10 |
server { listen 443; server_name gtrt7.com www.gtrt7.com; ssl on; ssl_certificate /etc/letsencrypt/live/gtrt7.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gtrt7.com/privkey.pem; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; add_header Strict-Transport-Security 'max-age=31536000;includeSubDomains;preload'; |
こちらのページ情報を参照したところ、どうも8行目のssl_ciphersの設定が原因と判明しました。ssl_ciphersではSSL/TSLで使用できる認証方式または禁止する認証方式(!)を設定できるようですが、上記設定では、禁止する認証方式に「!aNULL !eNull」等が無い為でした。上記設定のように使用できる認証方式と禁止する認証方式を書き連ねるのは大変なのでシンプルに以下の設定にしました。
1 |
ssl_ciphers='ECDH !aNULL !eNULL !SSLv2 !SSLv3'; |
2.変更後の評価結果
以下は2回目の評価結果です。
これだけでA+になりましたが、まだまだ設定した方が良いSSLの設定項目があるようです。
3.追加セキュリティ設定
認証方式「ECDH」で使用するDHキーを新たに指定します。nginxのデフォルトは1024バイトのDHキーを使用するようなので2048バイトのDHキーを新たに作成し設定します。
以下のようにDHキーを保存するディレクトリを/etc/nginx/sslに作成しそこに2048ビットのDHキーを作成します。
1 2 |
# mkdir /etc/nginx/ssl # openssl dhparam 2048 -out /etc/nginx/ssl/dhparam2048.pem |
これを以下のディレクティブとして追加します。
1 |
ssl_dhparam /etc/nginx/ssl/dhparam2048.pem; |
4.性能を考慮した追加設定
(1)SSLセッションキャッシュ
SSLセッションキャッシュを有効にすると2回目以降の接続に初回接続で使用したセッションを再利用するので性能向上が期待できます。以下のディレクティブで指定します。
1 |
ssl_session_cache shared:SSL:10m; |
(2)OCSP Staplingの設定
ブラウザがOCSサーバに証明書の有効性を確認しなくても済むように確認作業をサーバ側で行っておく設定です。以下のディレクティブで指定します。
1 |
ssl_stapling on; |
5.セキュリティヘッダの追加設定
SSLのセキュリティヘッダを元に評価してくれる「securityheaders.io」というサイトがあります。ここで当サイトを評価したところ「D」とのことでした。こちらの情報を参考に対策をしてみます。
(1)X-Content-Type-Optionsの設定
ブラウザがMIMEスニッフィングを行ってコンテンツタイプを判断するのをやめさせて強制的に宣言されたcontent-typeに基づいた動作を行わせるようにします。
以下のディレクティブで指定します。
1 |
add_header X-Content-Type-Options "nosniff" always; |
(2)X-Frame-Optionsの設定
サイトのページをフレーム内に表示することを許可するかどうかをブラウザに伝えます。以下に指定したSAMEORIGINは同一のドメインの場合だけページをフレーム内に表示できる設定です。以下のディレクティブで指定します。
1 |
add_header X-Frame-Options "SAMEORIGIN" always; |
(3)X-Xss-Protectionの設定
クロスサイトスクリプティングフィルタを有効に強制する設定です。以下のディレクティブで指定します。
1 |
add_header X-Xss-Protection "1"; |
(4)Content-Security-Policyの設定(参考)
ブラウザがロードする可能性のあるコンテンツのセキュリティーポリシーを定義します。以下の設定をすると自ドメインからのコンテンツ以外はロードできなくなります。以下のディレクティブで指定しますが、今回はしていしません。理由は、今後展開を予定しているGoogleアドセンスやAmazonアソシエイト等の外部ページを表示する際に設定が煩雑になるためです。ちなみにここまでを設定していれば評価Aが貰えるようです。
1 |
add_header Content-Security-Policy "default-src 'self'"; |
(5)セキュリティヘッダの評価結果
以上の追加ヘッダを設定した後の評価結果が以下です。評価は「D」から「B」に改善しました。
6.最終的なSSLの設定
以下はservertestでA評価、securityheaders.ioでB評価を頂いたnginx.confファイル設定の抜粋です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
server { listen 443 ssl http2; server_name gtrt7.com www.gtrt7.com; ssl on; ssl_certificate /etc/letsencrypt/live/gtrt7.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gtrt7.com/privkey.pem; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/ssl/dhparam2048.pem; # ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS; ssl_ciphers 'ECDH !aNULL !eNULL !SSLv2 !SSLv3'; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; add_header Strict-Transport-Security 'max-age=31536000;includeSubDomains;preload'; ssl_session_cache shared:SSL:10m; ssl_stapling on; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Xss-Protection "1"; |
2行目でhttp2でhttp2方式での接続をサポートします。
8行目が追加した2048ビットのDHキーの設定です。
9行目をコメントにし代わりに10行目で使用できる認証方式を指定しています。
14行目から15行目が性能を考慮した追加設定。
16行目から18行目が追加したセキュリティヘッダの設定です。
7.参考にさせて頂いたサイト
Let’s EncryptとNginx : セキュアなWebデプロイメントの現状
ありがとうございます。