さくらのVPS 標準OSの環境構築(5) Let's EncryptでSSL+HTTP/2対応

## 前回

[さくらのVPS 標準OSの環境構築(4) MariaDBとPHPのセットアップ](http://qiita.com/takahiko-takei/items/bcbfc8195188a3bce6d7)


## Let'sEncryptクライアントのインストール

クライアントをインストールする場所はどこでも構いません。
今回は習慣的な意味で`/usr/local/`にインストールします。

> `cd /usr/local/`
> `git clone https://github.com/letsencrypt/letsencrypt`

`letsencrypt-auto`を実行し、依存パッケージをインストールします。
ここでは`--help`オプションを**必ず**記述する必要があるので気をつけましょう。

> `cd /usr/local/letsencrypt`
> `./letsencrypt-auto --help`
> > `--help all`オプションを実行すると詳細なヘルプが表示されます。(もちろん英語表記)
> > `./letsencrypt-auto --help all`


## NginxにACMEプロトコル通信用のダミールートを設定

ACMEプロトコル通信があった場合に404エラーが発生すると証明書を発行できないため、専用のダミールートを設定します。
ダミー用のディレクトリ作成後、`Nginx`の設定に専用の`location`ディレクティブを加えます。

> `mkdir -p /letsencrypt-dummy-webroot`
> `vi /etc/nginx/conf.d/default.conf`

```diff:/etc/nginx/conf.d/default.conf
  server {
      listen      80;
      server_name example.com www.example.com;
      :
+     location ^~ /.well-known/ {
+          root /letsencrypt-dummy-webroot;
+     }

      location / {
      :
  }
```


## 証明書の取得

クライアントを実行して証明書を取得します。
`--webroot`オプションを用いて、HTTPサーバを動作させたままACMEプロトコルの通信を行います。

また、`-d`オプション`MY_DOMAIN`の部分に証明書を取得したいドメインを記述します。
`-d`オプションは、複数記述することで複数ドメインに対応した証明書を発行できます。(例: example.comとwww.example.comなど)

`--agree-tos`オプションでLet's Encryptの利用規約に同意したことになります。事前に[利用規約](https://letsencrypt.org/repository/)を確認しておきましょう。

> `./letsencrypt-auto certonly --webroot \`
> `-w /letsencrypt-dummy-webroot \`
> `-d example.com \`
> `-d www.example.com \`
> `-m info@example.com \`
> `--agree-tos`

```shell-session:実行結果
Checking for new version...
Requesting root privileges to run letsencrypt...
   /root/.local/share/letsencrypt/bin/letsencrypt certonly --webroot -w /letsencrypt-dummy-webroot -d example.com -d www.example.com -m info@example.com --agree-tos
/root/.local/share/letsencrypt/lib/python2.6/site-packages/cryptography/__init__.py:26: DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of cryptography will drop support for Python 2.6
  DeprecationWarning
Version: 1.1-20080819
Version: 1.1-20080819

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
   expire on 2016-07-23. To obtain a new version of the certificate in
   the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

```

> この実行結果では`Python2.6`のWarningが出ていますが証明書の発行には成功しました。
> 正式版で対応したのでしょうか？ただWarningの内容見る限りアップデートした方がよい感じです。
> 前回で`anyenv`を入れてあるので、`pyenv`で`Python2.7`を入れてもいいかもしれません。


## 発行した証明書でNginxのSSL+HTTP/2設定

`Nginx`の`SSL`+`HTTP/2`の設定を行います。
`80番(http)`でアクセスされた際に`https`にリダイレクトする`server`ディレクティブも追加します。

**注意点**
SSLv1.0〜v3.0はすべて深刻な脆弱性があるため使用してはいけません。

> `vi /etc/nginx/conf.d/default.conf`

```diff:/etc/nginx/conf.d/default.conf
  server {
      listen      80;
      server_name example.com www.example;
+     return      301 https://$host$request_uri;
+ }
+ server {
+     listen      443 ssl http2;
+     server_name example.com www.example;
      :
+     ssl                 on;
+     ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
+     ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
+ 
+     ssl_session_cache   shared:SSL:3m;
+     ssl_buffer_size     8k;
+     ssl_session_timeout 10m;
+ 
+     ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
+     ssl_ciphers         AESGCM:HIGH:!aNULL:!MD5;
+     ssl_prefer_server_ciphers on;
      :
      location / {
          proxy_set_header Host               $host;
          proxy_set_header X-Real-IP          $remote_addr;
+         proxy_set_header X-Forwarded-Proto  https;
          proxy_set_header X-Forwarded-Host   $host;
          proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;

          proxy_pass http://127.0.0.1:8080;
-         proxy_redirect off;
+         proxy_redirect http:// https://;
          :
  }
```


## ApacheのSSL設定

`Nginx`から受け取った`SSL`リクエストを`Apache`で正しく認識できるように設定します。

> `vi /etc/httpd/conf/httpd.conf`

```diff:/etc/httpd/conf/httpd.conf
  :
  <VirtualHost 127.0.0.1:8080>
      :
      RPAF_SetHostName On
+     RPAF_SetHTTPS On
      RPAF_ProxyIPs 127.0.0.1 10.0.0.1
      :
  </VirtualHost>
  :
```

これで`phpinfo()`などで`HTTPS`が`on`になっていることを確認出来れば大丈夫です。


## SSLはただ使えるようにするだけではない

SSLはただ導入するだけでなく、セキュリティ強度の向上などの設定も色々行い強固にする必要があります。
ドメインでのSSLの評価は[Qualys SSL Test](https://www.ssllabs.com/ssltest/analyze.html)で行うことができます。
今回はSSL導入のみの解説のため割愛しますが、出来るだけA+に近い評価を得られるようにしておきましょう。

> 他の方の記事ですが、こちらが参考になるかと思われます。
> 参考: [Let's EncryptのSSL証明書で、Qualys SSLTestでA+評価を獲得するには](http://qiita.com/dseg/items/bab80f6f14349fcd9c22)


## 証明書の更新とNginxの再起動をcronに登録する

証明書の更新とNginxの再起動を定期的に行う`cron`を設定します。
毎月1日の朝5時に実行されるようにします。

> `crontab -u root -e`

```diff:crontab
+ 00 05 01 * * /usr/local/letsencrypt/letsencrypt-auto renew --force-renew && /sbin/service nginx restart
```


## 次回

[さくらのVPS 標準OSの環境構築(6) Nginxリバースプロキシ環境でのGitLabの導入](http://qiita.com/takahiko-takei/items/16dd7a2845ec7f6b0be7)