自由帳

とりとめのない学習メモです。主に Web サービスのシステム基盤や運用に関することを書いています

Let’s EncryptのSSL証明書で WordPress + Nginx をフルSSL化する

はじめに

無料で利用可能な Let’s Encrypt の証明書を使って WordPress + Nginx のサイトをフルSSL化してみます。

Let’s Encrypt

Let’s Encrypt とは

Let’s Encrypt は無料で使えるSSL/TLS証明書を発行する認証局(CA)です。 企業や非営利団体などの様々な組織のサポートを受けながら、 Internet Security Research Group (略称:ISRG) という団体によって運営されています。 2016年4月から正式サービスとして開始されています。

Let’s Encrypt の仕組み

Let’s Encrypt の認証・証明書取得のクライアントプログラム(シェルスクリプト)があるので、それを実行するのみです。

初回実行時は以下の様なドメイン認証が実施されます。

  1. 証明書をインストールしたいWebサーバから、ドメイン名(FQDN)の情報をLet's Encryptの認証局に伝え、認証してもらう。
  2. Let's Encrypt 側からワンタイムトークン(認証用の一時的な番号)と、認証用ファイルとそれを配置すべきPATH情報(${ドキュメントルート}/.well-known)がWebサーバに送られ、クライアントプログラムによってファイルが配置される。
  3. Webサーバ側はクライアントプログラムが生成した秘密鍵で、ワンタイムトークンへ署名し、公開鍵とともにLet's Encryptのサーバへ送信する。
  4. Let's Encrypt側から「http://<ドメイン名>/.well-known/acme-challenge/認証用ファイル名」が参照され、認証用ファイルが取得される。
  5. Let's Encrypt側でワンタイムトークンに対する署名とウェブサーバからダウンロードした認証用のファイルの妥当性を検証され、認証に成功すると、公開鍵によって識別されたクライアントプログラムに対して、以後の証明書の発行や更新、失効といった作業を自動的に実施できるようになる。

Let's Encrypt証明書の取得

動作環境

今回は Ubuntu 16.04 LTS 上で動作している Nginx + WordPress 環境に対して証明書の適用を実施します。

OS Ubuntu 16.04 LTS(4.4.0-21-generic)
Webサーバ nginx/1.10.0
その他 WordPress, php7.0-fpm

Let's Encryptの認証局との通信のため、外部へhttp,httpsで通信できる必要があります。

Let's Encrypt のクライアントソフトウェア Certbot の取得

Let's Encrypt は、クライアントソフトウェア Certbot を用いて、SSL/TLS サーバ証明書の取得・更新作業を自動化できる仕組みになっています。 まずはこれを取得します。

$ sudo curl https://dl.eff.org/certbot-auto -o /usr/local/bin/certbot-auto

実行権限を付与します。

$ sudo chmod 700 /usr/local/bin/certbot-auto
$ certbot-auto certonly \             # 証明書を取得
  --webroot \                         # 現在稼働中のWebサーバを使って証明書を取得
  --webroot-path ${ドキュメントルート} \    # ドキュメント・ルートのパス
  -d ドメイン名 \                        # 認証するドメイン名
  --email メールアドレス                       # メールアドレス登録(証明書期限切れの通知用)

不足パッケージがある場合、ここでパッケージのインストールが始まります。

その後以下の様な画面が出ます。 Agree を選択します。

┌──────────────────────────────────────────────────────────────────────┐
│ Please read the Terms of Service at                                  │
│ https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf.    │
│ You must agree in order to register with the ACME server at          │
│ https://acme-v01.api.letsencrypt.org/directory                       │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
│                                                                      │
├──────────────────────────────────────────────────────────────────────┤
│                     <Agree >           <Cancel>                      │
└──────────────────────────────────────────────────────────────────────┘

自動的に certbot-autoLet’s Encrypt認証局と通信を行い、証明書を自動生成します。 以下の画面が出れば終了です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/blog.dshimizu.jp/fullchain.pem. Your cert
   will expire on 2016-12-02. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot-auto again. To
   non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to shimizu.daisuke.sd@gmail.com.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

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

Webroot を指定した場合、 ${ドキュメントルート}/.well-known/acme-challenge に一時ファイル(ワンタイムトークン)を作成し、Let's Encrypt の認証サーバから HTTP リクエストによって取得することで認証が行われます。 その際、Webサーバには下記のようなアクセスログが記録されます。

66.133.109.36 - - [31/Aug/2016:hh:mm:ss +0900] "GET /.well-known/acme-challenge/XeJCJUeYYC9SZWi5tvorvnhwhXf8iKB4FRO6LP_vEhY HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"

処理が終わると、 /etc/letsencript 以下のディレクトリに証明書ファイルが自動生成されています。

$ sudo ls -l /etc/letsencrypt/live/{ドメイン名}
total 2
lrwxrwxrwx 1 root root 40  8月 31 hh:mm cert.pem -> ../../archive/{ドメイン名}/cert1.pem
lrwxrwxrwx 1 root root 41  8月 31 hh:mm chain.pem -> ../../archive/{ドメイン名}/chain1.pem
lrwxrwxrwx 1 root root 45  8月 31 hh:mm fullchain.pem -> ../../archive/{ドメイン名}/fullchain1.pem
lrwxrwxrwx 1 root root 43  8月 31 hh:mm privkey.pem -> ../../archive/{ドメイン名}/privkey1.pem

Nginx の設定

Nginxの設定ファイルには ssl_certificate,ssl_certificate_keyに letsencrypt の証明書設置先の Path を指定します。 他は 80ポートへのリクエストは https へ転送し、 443 ポートで WordPress の PHP を処理できるようにします。

ざっくり以下のような記述があれば良いと思います。 ※管理画面へのアクセス制御などは考慮していないのでご注意ください。

server {
    listen 80;
    index index.html index.htm index.php;
    server_name {ドメイン名};

    root ${ドキュメントルート};
    index index.html;

    access_log ${Nginxログディレクトリ}/access.log;
    error_log ${Nginxログディレクトリ}/error.log;

    location / {
        return 301 https://blog.dshimizu.jp$request_uri;
    }
}

server {
    listen 443;
    ssl on;

    index index.html index.htm index.php;
    server_name {ドメイン名};

    ssl_certificate         /etc/letsencrypt/live/{ドメイン名}/cert.pem;
    ssl_certificate_key     /etc/letsencrypt/live/{ドメイン名}/privkey.pem;

    root ${ドキュメントルート};
    index index.html;

    access_log ${Nginxログディレクトリ}/ssl_access.log;
    error_log ${Nginxログディレクトリ}/ssl_error.log;

    client_max_body_size 20M;

    location / {
        try_files $uri $uri/ @wordpress;
    }

    location ~ \.php$ {
        try_files $uri @wordpress;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_pass php-fpm-socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location @wordpress {
        fastcgi_index index.php;
        fastcgi_pass php-fpm-socket;
        rewrite ^ /index.php last;
        include       fastcgi_params;
    }

}

設定を反映させるため、Nginxを reload します。

$ sudo systemctl reload nginx

確認

ブラウザから「https://<ホスト名>/」を開きし、正常に HTTPS で通信できることを確認します。

おわりに

今後もますますセキュリティには気を配る必要がありますが、インターネット上の通信をセキュアにするには SSL/TLS 通信が必要不可欠です。 Let’s Encrypt であれば、オンライン上で無料かつ簡単に証明書を作成できます。 ぜひ一度利用されてみると良いかもしれません。

参考