インストール直後のnginxからSSL評価A+とセキュリティ強化を行う手順メモ

# これは何？
* インストール後のnginxに証明書を導入し、SSLのレポートでA+を取るまでの設定メモ
* HTTPS化を簡単に実施する設定メモでもある

# 前提事項
* 証明書を発行するためにドメインを所有していること
* 証明書発行には、証明書無料発行サービスであるLet's Encryptを利用する
* nginxのバージョンは、```1.10.1```を利用する

# 手順

## nginxの初期設定編

**インストールと起動確認**

```
$ sudo yum install -y nginx
$ sudo systemctl start nginx.service
```

※ 場合によっては、Firewalldの設定も実施すること
参考：http://urashita.com/archives/963

```xml:/etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="http"/>  <!-- 起動確認のために開けておく、後で閉じること -->
  <service name="https"/> <!-- あとで利用するので開いておく -->
  <service name="ssh"/>
</zone>
```

上記実施後、下記コマンドで、firewalldの変更を適用する。

```
$ sudo firewall-cmd --reload
```


**TLS(HTTPS)の設定を行う**

nginxの設定ファイルを開いて、```38```行目あたりのHTTPの設定をコメントアウトして、```44```行目あたりのHTTPSの設定を有効化する。

```nginx:/etc/nginx/nginx.conf
　　# 60行目付近にある httpsの設定を有効化する
    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
        # ...
        # 以下略
    }
```

## 証明書の導入編

**Let's Encrpytを利用した証明書の発行**
Let's Encryptのツールを導入する。

```
$ sudo yum install epel-release
$ sudo yum install certbot
```

次に、ツールを利用して証明書を発行する。
あらかじめ、所有しているドメイン名をDNSのAレコードなどを利用してIPと紐付けておく必要がある。

```
$ certbot certonly
```

手順に沿って、ドメイン名、メールアドレスなどを入力する。
nginxのwebrootを求められるので、デフォルトでは、```/usr/share/nginx/html```などWebから参照可能なパスを指定して下さい。
（このようにする理由は、https://letsencrypt.jp/technology/ 参照）

**証明書の発行確認**

実行後、下記フォルダに証明書のシンボリックリンクが作られる。
サーバから設定する際には、シンボリックリンクのパスを利用する。
実ファイルは、``/etc/letsencrypt/archive/ドメイン名/`` 配下に格納される。（参照：https://letsencrypt.jp/usage/）

```
/etc/letsencrypt/live/ドメイン名/cert.pem <--サーバ証明書（公開鍵）
/etc/letsencrypt/live/ドメイン名/chain.pem <-- 中間証明書
/etc/letsencrypt/live/ドメイン名/fullchain.pem <-- サーバ証明書と中間証明書が結合されたファイル
/etc/letsencrypt/live/ドメイン名/privkey.pem <-- 秘密鍵
```

**証明書をnginxに設定**
下記に先ほど取得した証明書を設定する。

```nginx:/etc/nginx/nginx.conf
   server {
    # 中略
    ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;
   }
```

**証明書の導入を確認**

サーバを再起動し、sslで接続できることを確認する。

```
$ sudo systemctl start nginx.service
```

## セキュリティ強化編

### IPAセキュリティチェックリストに基づく設定

まず、IPAの[セキュリティ実装 チェックリスト](https://www.ipa.go.jp/security/vuln/websecurity.html)をベースにWebサーバ側で対策できることを対応する。

#### 4-(iii) HTTPS通信で利用するCookieにはsecure属性を加える。

```
proxy_cookie_path / "/; secure; HttpOnly";
```

↑は併せて、```5-(ix) Cookie情報の漏えい対策として、発行するCookieにHttpOnly属性を加え、TRACEメソッドを無効化する。```も実施済み。
なお、TRACEメソッドは、nginxでは、デフォルト無効である模様。

#### 5-(viii) HTTPレスポンスヘッダのContent-Typeフィールドに文字コード（charset）の指定を行う。
必要に応じた文字コードを設定する。今回は、UTF-8とする。

```
 charset UTF-8;
```

#### 5-(x) クロスサイト・スクリプティングの潜在的な脆弱性対策として有効なブラウザの機能を有効にするレスポンスヘッダを返す。

**X-XSS-Protection**

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

**Content Security Policy**
許可する先を一概に特定できないので、下記を参考に設定する。
http://qiita.com/hideji2/items/1421f9bff2a97a5e5794#content-security-policy

#### 9-(i)-a HTTPレスポンスヘッダに、X-Frame-Optionsヘッダフィールドを出力し、他ドメインのサイトからのframe要素やiframe要素による読み込みを制限する。

```
add_header X-Frame-Options SAMEORIGIN;
```

### OWASPのWebシステム／Webアプリケーションセキュリティ要件定義書に基づく設定

OAWSP による[Webシステム／Webアプリケーションセキュリティ要件定義書](https://github.com/ueno1000/secreq/blob/master/OWASPWebApplicationSecurityRequirements2.0.pdf) をベースにWebサーバ側で対策できることを対応する。
なお、IPAのチェックリストと重複したものははずす。

#### 6.3 安全な暗号化通信を使用すること

* TLS1.0以上を使用し、SSL2.0、3.0を無効化すること

```
ssl_protocols TLSv1.2;
```

* 安全な暗号スイートを利用すること

```
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:DH+AES256:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS;
```

#### 9.1 エラーメッセージに詳細な内容を表示しないこと

Webサーバのバージョンを表示させないようにする。

```
server_tokens off;
```

## SSL評価A+編

### 評価の方法

無料でSSL評価を実施してもらえるサイトがあるので、利用する。
ここのサイトでの評価で「A+」などと評価してくれる。
https://www.ssllabs.com/ssltest/

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

参考 https://esham.io/2016/01/ocsp-stapling

```
wget -O /etc/nginx/cert/trustchain.crt "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem"
```

```
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
```

### X-Content-Type-Options

```
add_header X-Content-Type-Options nosniff;
```

### DH鍵交換時のKeyの強化
```
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
```

## 参考資料

* http://qiita.com/sak_2/items/ff835b669c0a7e110b09
* http://qiita.com/d6rkaiz/items/9f4ebad83b3437a0d2ea
* http://qiita.com/syou007/items/3e2d410bbe65a364b603
* http://qiita.com/ww24/items/9fa19594b4e3a8eb9b6f
* http://qiita.com/hideji2/items/1421f9bff2a97a5e5794
* http://qiita.com/kuni-nakaji/items/5118b23bf2ea44fed96e
* http://cluex-developers.hateblo.jp/entry/secure-nginx-setting-for-2016