光の速さのWEBサーバー(nginx)をlet's encryptでSSL化及びHTTP/2化。ついでにセキュリティ評価をA＋にする。

# 前回のおさらい
* インフラ
	* さくらのVPS(v4) SSD 1G
	* CentOS7.2 (OS)
* ミドルウェア
	* nginx　1.8.0 
	* php7.0-fpm (アプリケーション） 
	* MariaDB(SQL) 5.5.44
* フロントエンド
	* Wordpress 4.4.1

　前回の記事の通り、Ansibleであっという間に以上の構成のwebサーバーを組むことができました。今回の記事ではこれらを無料で証明書を発行するwebサービス、let's encryptを使ってSSL/TLS化しちゃいます。そして、ついでにSSLの評価計測サイトであるQualys SSL Reportのセキュリティ評価でA＋をもらっちゃいます。

※ SSL/TLS化についてのメリット/デメリットについては下記にまとめられてました。参考までに。

[常時SSL化とは？Webサイトの常時SSL化の効果と注意点](http://knowledge.sakura.ad.jp/beginner/3879/)

# 前提条件
　今回はWEBサーバの構築が完了し、ドメインを取得してDNSの設定が完了しているということを前提にさせていただきます。

　ドメインの正引き逆引きが完了し、TCP port 80で正常にWEBサイトにアクセスできているものとします。

# GitHub

　今回用いたnginxの設定ファイルをGitに公開しています。

* [sak-2/example_nginx.conf](https://github.com/sak-2/example_nginx.conf)

# Let's encryptって？
* 公式サイト　[https://letsencrypt.org/](https://letsencrypt.org/)
* 日本語ポータル　[https://letsencrypt.jp/](https://letsencrypt.jp/)

日本語ポータルからの引用
> Let's Encrypt は、認証局（CA）として「SSL/TLSサーバ証明書」を無料で発行するとともに、証明書の発行・インストール・更新のプロセスを自動化することにより、TLS や HTTPS（TLSプロトコルによって提供されるセキュアな接続の上でのHTTP通信）を普及させることを目的としているプロジェクトです。

> Let's Encrypt の「SSL/TLSサーバ証明書」は、独自ドメインの所有者であれば、誰でも簡単に、無料で取得することができ、商用サイトでの使用も可能です。

ということで、誰でも無料でSSL/TLSサーバ証明書を取得して、ウェブサイトをHTTPS化することができるというツールです。現在は公開ベータプログラム（Public Beta Program）となっています。

# HTTP/2って？
　2015年に16年ぶりにアップデートしたHTTPの最新ver.のプロトコルです。HTTP/2は部分的にGoogleが提案したSPDY（スピーディ）と呼ばれるプロトコルをベースとしていて、このプロトコルから継承した形でリリースされたものです。HTTP/2によって、複数のリクエストを同時に処理することができます。これによって、データ接続はより高速で簡単になると言われています。

技術文書はこちら
* [RFC7540](https://tools.ietf.org/rfc/rfc7540.txt)
* [RFC7541](https://tools.ietf.org/rfc/rfc7541.txt)


# let's encryptのインストール
それではさっそくインストールしていきましょう。

sshでさくらVPSに接続します。

任意のディレクトリで以下を実行して、クライアントをダウンロードします。
> $ git clone https://github.com/letsencrypt/letsencrypt

つづいて、
> $ cd letsencrypt/

> $ ./letsencrypt-auto --help

とすると、Let's Encrypt クライアントソフトウェアの実行環境が整い、正常に実行できた場合には、Let's Encrypt のヘルプが表示されます。

# let's encryptクライアントの実行

> $ ./letsencrypt-auto certonly -a standalone --webroot -w (nginxのルートフォルダ) -d　(ドメイン名) -d www.(ドメイン名)

と実行します。
しばらくすると、TUIでメールアドレスの入力が求められますので、入力します。ここでは、一応、ドメインのwhois情報に記載されているメールアドレスにしました。

続いて、利用規約に同意します。
> Agree

しばらくすると、Congratulations！と表示され、証明書の取得が完了します。下のような図が表示されれば成功です。

![スクリーンショット 2016-01-14 22.45.32.png](https://qiita-image-store.s3.amazonaws.com/0/71907/0c1302bc-f554-f4b1-a8fa-5fcaf0e4abe5.png)


取得した証明書等の 実体は、下記の場所に保存されます。
※ Nは取得した回数

* サーバ証明書（公開鍵）
 * 実体 :/etc/letsencrypt/archive/ドメイン名/certN.pem
 * シンボリックリンク : /etc/letsencrypt/live/ドメイン名/cert.pem
* 中間証明書
 * 実体 : /etc/letsencrypt/archive/ドメイン名/chainN.pem
 * シンボリックリンク : /etc/letsencrypt/live/ドメイン名/chain.pem
* サーバ証明書と中間証明書が結合されたファイル
 * 実体 : /etc/letsencrypt/archive/ドメイン名/fullchainN.pem
 * シンボリックリンク : /etc/letsencrypt/live/ドメイン名/fullchain.pem
* 秘密鍵
 * 実体 : /etc/letsencrypt/archive/ドメイン名/privkeyN.pem
 * シンボリックリンク : /etc/letsencrypt/live/ドメイン名/privkey.pem

# 証明書の自動取得
Let's encryptは証明書の発行機関が３ヶ月と短いので、自動更新することが推奨されています。そこでcronに自動更新するスクリプトを追加しておきましょう。

> $ su root

> $ crontab -e

以下を追記します。
> 00 05 01 * * /usr/local/letsencrypt/letsencrypt-auto certonly --webroot -w <<nginxのルートフォルダ>> -d <<ドメイン名>> -d www.<<ドメイン名>> --renew-by-default && /bin/systemctl restart nginx

これで毎月1日の5:00に自動で証明書が更新されるようになりました。

# Port 443の開放
　CentOS7.2なので、firewalldコマンドにてSSL/TLSで用いるPort443を開放します。

設定前の状態を確認する
> $ firewall-cmd --list-all

アクセス許可
> $ firewall-cmd --permanent --add-service=https

設定を有効化するためにreloadする
> $ firewall-cmd --reload

設定後の状態を確認する
> $ firewall-cmd --list-all 

これで結果に
`ports: 443/tcp`
と追加されていればOKです。

# nginxのアップデート
　HTTP/2に対応しているのはnginx1.9.5以降となります。現行は1.8.0がインストールされているので、アップデートする必要があります。yumでアップデートしちゃいましょう。

nginx用のリポジトリ作成
> $ vi /etc/yum.repo.d/nginx.repo


``` yum.repo.d:nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/rhel/$releasever/$basearch/
gpgcheck=0
enabled=1
```

yumで更新
> yum update

version確認
> nginx -v
2016/01/19現在、1.9.9が最新。


# nginxの設定ファイルの書き換え
　さて、それではnginxのconfファイルを書き換えていきましょう。confのserver部分を書き換えていきます。一つずつ設定値の確認をしてみましょう。

# Port443 をlistenにして、SSLとHTTP2に対応させる

　HTTPSのPortは443なので記載しましょう。SSLとHTTP2に対応させて、ついでに、httpへアクセスがあった場合にhttpsへリダイレクトされる設定を入れます。

```conf.d:default.conf
server {
        listen 80; # httpへのアクセスをhttpsへリダイレクトする
        listen [::]:80;
        return 301 https://$host$request_uri; 
}

server {
  	listen 443 ssl http2;　# HTTP/2を有効化する
  	listen [::]:443 ssl http2;
（以下略）
```

# 公開鍵と秘密鍵の場所を記載する

```conf.d:default.conf
server { 
# serverに追記
	ssl_certificate /etc/pki/CA/certs/www.XXXX.XX.crt;
　　　　　ssl_certificate_key /etc/pki/CA/private/www.XXXX.XX.key;

（以下略）
}
```
# SSLv3.0を無効化
　SSLv3.0は「POODLE」と呼ばれる重大な脆弱性が見つかったため、使用は回避しなければなりません。（ちなみに、SSL v1.0,2.0全部ダメです）
というわけで無効にする設定を入れます。
serverが記載されている設定ファイルに以下を追記

```conf.d:default.conf
server { 
# serverに追記
　　　　　ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

（以下略）
}
```

# 脆弱な暗号化スイートの無効
　使用する暗号化スイートを設定します。サーバ側ではブラウザ側と自身の両方がサポートされている暗号化スイートを選択しなければなりません。脆弱性のあるものや、あまり使われていない暗号化スイートを明示的にオフにすることでセキュリティを向上させることができます。


```conf.d:default.conf
server { 
# serverに追記

 ssl on;　# サーバ側の暗号化スイートを優先する
 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;
（以下略）
}
```


# Perfect Forward Security（PFS）の有効
　Forward Securityとは2014年のハートブリード（CVE-2014-0160）を期に注目された、秘密鍵が漏洩してもそれだけでは解読できないようにする仕組みです。具体的には、鍵の交換にEDH鍵交換方式を用いて、決まった鍵の代わりにセッションごとに、クライアントとサーバ側で異なったランダムな数字を鍵として使うことができます。これは、EDH鍵交換はDiffie-Hellman鍵共有という方法で実現しています。DH鍵共有の仕組みは離散対数問題とか数学の話になるので割愛。

# Perfect Forward Security (PFS) 
その中でも、以下の条件を満たしたものがPFSと呼ばれる。

* 鍵合意のために公開可能な、ランダムな値を使う。
* 鍵合意の過程で決定的なアルゴリズムを一切使わない。

このPFSを持ちるためにはDH鍵共有に使用するパラメータファイルが必要なので、opensslコマンドで2048bitの鍵を生成します。

> $ mkdir /etc/nginx/ssl

> $ cd /etc/nginx/ssl

> $ openssl dhparam 2048 -out dhparam.pem

さらにこれを、default.confのserverタブに追記

```conf.d:default.conf
server { 
# serverに追記

 ssl_dhparam /etc/nginx/ssl/dhparam.pem

（以下略）
}
```

# OCSP Staplingの有効

　OCSP（Online Certificate Status Protocol）とは、SSL/TLS暗号化通信の初期フェーズにおいて証明書の失効を確認するための手順のことです。クライアントがOCSP要求を行うのではなく、サーバがOCSP要求を行って、その応答をキャッシュします。サーバはキャッシュしたOCSP応答を、サーバ証明書と一緒にクライアントに送信します。これによりクライアントはOCSP responderに問い合わせる必要がなくなり、HTTPS通信の開始を高速化することができる。

```conf.d:default.conf
server { 
# serverに追記
       	ssl_stapling on;
	ssl_stapling_verify on;
	ssl_trusted_certificate /etc/letsencrypt/live/(your domain)/fullchain.pem;
        resolver 8.8.8.8;
（以下略）
}
```

# HSTSを有効化
サーバーからブラウザ側へHTTP平文を送らないでほしいというリクエストをヘッダに返します。すると以後そのブラウザで常時 HTTPS で暗号化した通信を行うようにするようになります。

```conf.d:default.conf
server { 
# serverに追記
  add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';

（以下略）
}
```



# nginxの再起動
サービスを再起動します
※上がってこないときは、confファイルの記述が間違えている可能性があります
> $ systemctl restart nginx 


# Qualys SSL Reportのセキュリティ評価
	
https://www.ssllabs.com/ssltest/ にアクセスして、Domain Nameに対象のURLを入力します。

しばらく評価がくだされるのを待ちます…!!











![スクリーンショット 2016-01-20 1.07.11.png](https://qiita-image-store.s3.amazonaws.com/0/71907/6f5b6e83-10ea-972d-1171-d3cbeeffeab8.png)


ほらね。

ということで、今回の目的は無事に果たせました！

次回はこいつをZabbixで監視する設定を入れてみようと思います。

# 参考文献
[https://juliansimioni.com/blog/https-on-nginx-from-zero-to-a-plus-part-2-configuration-ciphersuites-and-performance/](HTTPS on Nginx: From Zero to A+ Part 2 - Configuration, Ciphersuites, and Performance)