Let’s Encrypt でワイルドカード証明書を発行してすべてのサブドメインにhttpsを適用

2019-12-05Web

はじめに

僕のブログやその他検証プログラムを配置しているラボページなどはいずれも「Let's Encrypt」を使ってSSLを実現しています。

「Let's Encrypt」のワイルドカード証明書の更新を行っていて、再度新たに設定し直したのですがやり方を忘れないように「ポストイット」にして貼り付けておきます。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ apachectl -v
Server version: Apache/2.4.6 (CentOS)

事前作業

  1. ドメイン が必須なので、事前に取得しておきましょう。
    • ※今回のブログ用に spinosaurus.work というドメインを取得し手順を整理しました。
  2. DNSレコードとして、ワイルドカードのAレコードを作成しておくとこのあとの確認がしやすいです。
    • 例えば *.spinosaurus.work のようなレコード

作業手順

「Let's Encryt」用のワイルドカード証明書を作成し、認証局・Webサーバに設定するために Certbot というツールを利用します。

インストールしたあとは Certbot を使えばあっという間にSSLによる通信ができ当たります。

「Certbot」のインストール

yum でインストールができるのですが、最新バージョンでない場合に正常に動作しないことがあってハマりした。
はまらないように最新バージョンを使うことをおすすめします。
( yum でインストールしたものでも問題が起きないときのほうが多いのですが、ときどきできなかったりするので。。。)

# まずはルートになります
$ sudo -i

# 古いものがあると正常に動作しない場合があるため、念の為削除コマンドを実行
$ yum remove -y certbot python2-certbot-apache

# 以下のディレクトリに"Certbot"を配置しておきます
$ cd /usr/local/src

$ git clone https://github.com/certbot/certbot.git

# 多くの場合は "/usr/local/bin" にパスが通っているので、シンボリックリンクを作成
$ ln -s /usr/local/src/certbot/certbot-auto /usr/local/bin

# バージョンを確認
$ /usr/local/bin/certbot-auto --version
certbot 0.33.1

正しくインストールされました。

定期的に git pull --rebase を実行して、最新ソースを取得しておくのが良いかもしれません。

ワイルドカード証明書作成

いよいよ本題のワイルドカード証明書の作成と発行について。
以下のコマンドを実行します。

ほぼこのままでいけますが、 -d <ドメイン> / -d *.<ドメイン> / -m <メールアドレス> の部分は当然ながらお使いのドメインやメールアドレスに置き換えてください。

$ /usr/local/bin/certbot-auto certonly \
  --manual \
  -d "spinosaurus.work" \
  -d "*.spinosaurus.work" \
  -m "genzouw@gmail.com" \
  --agree-tos \
  --manual-public-ip-logging-ok \
  --preferred-challenges dns-01 \
  --server https://acme-v02.api.letsencrypt.org/directory

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for spinosaurus.work

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.spinosaurus.work with the following value:

oXr-i6tCYP*********************************

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

oXr-i6tCYP********************************* の部分はマスキングしておきましたが、本当は半角文字列が表示されています。

このタイミングで、お使いのドメインの設定を変更します。

DNSに TXTレコード を追加します。
設定する内容は以下をご参考ください。(ドメイン部分はお使いのドメインに書き換えてくださいね(汗))

ホスト名TYPEVALUE
_acme-challenge.spinosaurus.workTXToXr-i6tCYP*********************************

DNSの設定変更後、結構待たないといけないです。
(さくらのDNSを使ったときは一瞬でしたが、お名前.comを使ったときは10分ぐらい待ちました。)

DNSサーバへのTXTレコード反映状況は、以下のコマンドを実行すれば確認できます。(1秒おきに更新されます。)

# `watch` コマンドがない場合には `dig -t txt _acme-challenge.spinosaurus.work` だけでもOK
$ watch -n 1 dig -t txt _acme-challenge.spinosaurus.work

失敗した場合はもう一度、今度は別のTXTレコードを追加するようにメッセージが表示されますので、追加しましょう。
(たまたまなのか、「変更」ではなく「追加」しないと成功しなかったので、失敗したときのTXTレコードは残したまま「追加」することをオススメします。)

正常に終了すれば以下のようなメッセージが表示されます。

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/spinosaurus.work/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/spinosaurus.work/privkey.pem
   Your cert will expire on 2019-07-05. 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 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

「Let's Encrypt」の証明書は 3ヶ月間 のみ有効であるため、有効期限が近づいてきたら更新が必要です。

成功したあとに表示されたメッセージにかかれている通り、 certbot-auto renew で更新可能です。
cron などに仕掛けておくのがいいですね。

僕は root ユーザのcronに以下の設定を仕掛けています。( 後述の「注意」を参照! / 良い方法があれば教えてください。)

0 0 */7 * * /usr/local/bin/certbot-auto renew --post-hook "sudo service httpd restart" >> /var/log/certbot.log

※(注意-2019-06-25追記)

証明書の有効期限が近づくと、上記で設定されたcronが更新処理を行うようになるはずですが、僕のサーバ環境では今まで成功したことがありません。
ネット上には「ワイルドカード証明書を利用した場合には certbot-auto renew は正しく動作しない」という情報もあります。

したがって、残念ながら現状では certbot-auto certonly --manual コマンドを再度実行し、DNSのTXTレコードの再設定を行うことで更新をしています。

良い方法をご存知の方、ぜひ情報をお待ちしています。

ワイルドカード証明書の作成を確認

本当に証明書ができたのか確認しておきましょう。

$ find /etc/letsencrypt -type f | grep spinosaurus

/etc/letsencrypt/renewal/spinosaurus.work.conf
/etc/letsencrypt/archive/spinosaurus.work/cert1.pem
/etc/letsencrypt/archive/spinosaurus.work/privkey1.pem
/etc/letsencrypt/archive/spinosaurus.work/chain1.pem
/etc/letsencrypt/archive/spinosaurus.work/fullchain1.pem
/etc/letsencrypt/live/spinosaurus.work/README

このように、 /etc/letsencrypt ディレクトリ配下に証明書が作成されていますね。

ApacheにSSL証明書を設定する

作成した証明書も利用しなければ意味がありません。

Apache上で利用したい場合は /etc/httpd/conf.d/spinosaurus.work.conf ファイルに以下のような記述を追記します。

$ vim /etc/httpd/conf.d/sub.spinosaurus.work.conf
<VirtualHost *:443>
  ServerName sub.spinosaurus.work
  DocumentRoot "/var/www/sub.spinosaurus.work/public_html"

  CustomLog /var/log/httpd/sub.spinosaurus.work-access.log combined
  ErrorLog /var/log/httpd/sub.spinosaurus.work-error.log
  LogLevel warn

  DirectoryIndex index.html index.php

  <Directory "/var/www/sub.spinosaurus.work/public_html">
    AllowOverride All
    Options -Indexes +FollowSymLinks
    Require all granted
  </Directory>

  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/archive/spinosaurus.work/cert1.pem
  SSLCertificateKeyFile /etc/letsencrypt/archive/spinosaurus.work/privkey1.pem
  SSLCertificateChainFile /etc/letsencrypt/archive/spinosaurus.work/chain1.pem
</VirtualHost>

大事な部分は ServerName の部分がサブドメインとなっている点と SSLEngine / SSLCertificateFile / SSLCertificateKeyFile / SSLCertificateChainFile で証明書の配置場所を指定する点です。

public_html ディレクトリに適当なHTMLファイルを配置してやれば https://sub.spinosaurus.work をブラウザで開いてページを閲覧できるはずです。

2019-12-05Web