今回はこのブログサイトのウェブサーバー構築のお話から
独自ドメインでウェブサイトを開発・運用するとなると、今や欠かせないのがSSL証明書。 今回のエントリは、このブログサイトのウェブサーバー構築の時の作業から、Let\’s Encryptという無料SSL証明書を提供してくれるサービスを使って、ウェブサーバーにSSL証明書をインストールした際の経験をお伝えします。
SSL証明書というと年間で少なくとも数千円はかかるというイメージを持つ方が多いのではないかと思います。
ところが、無料でSSL証明書を世の中に提供すると言う志の高いサービス Let\’s Encrypt があることを知り、このブログサイトの開発では、それを使おうと思い立ちました。
Let\’s Encrypt の無料SSL証明書を手に入れるには、どのような作業が必要なのか、実際に体験した内容をお届けしたいと思います。
Let\’s Encrypt について
– 公式サイト
- Let\’s Encrypt は、米国サンフランシスコ州に拠点を置く非営利団体によって運営されるサービスで、無料でSSL証明書(TLS/X.509証明書)を発行しています。
- 証明書の発行作業を自動化することで、この無料のサービスを実現しています。
- 2018年9月中旬時点で、累計で3億8000万通の証明書を発行しており、現時点ではさらに増えています。
- 発行される証明書は、90日間だけ有効の期間が短いものですが、後述する
certbot
という公式のツールを使って、定期的に証明書を更新するというスタイルで運用していきます。
Let\’s EncryptのSSL証明書をインストールする環境について
このブログサイトのウェブサーバーにLet\’s EncryptのSSL証明書を導入したわけですが、そのウェブサーバーの種類やサーバーの環境について書いておきます。
- サーバーインフラは、AWSを利用(EC2インスタンス)
- OS : Ubuntu 18.04.3 LTS
- ウェブサーバー : Nginx
- DBサーバー : RDS(AWS)
- DNSサーバー : Route53(AWS)
-
Python : 3.6.8
今回のエントリ内容に関連する環境情報は、とりあえず上記です。
Nginxをインストール&設定済みということを前提に話を進めて参りたいと思います。
certbot のインストール
まず、Let\’s Encrypt が提供する証明書管理ツールである certbot
を導入します。
これを導入することにより、先ほど述べた証明書の自動更新が可能となるわけです。
OSによってインストール方法が少し変わります。
Debian, Ubuntu の場合、リポジトリの中に certbot が含まれるので、コマンドで簡単にインストールをすることができます。
それ以外の場合は、Git のリポジトリからソースコードをダウンロードして、インストールします。
今回は、Ubuntu なので、リポジトリからパッケージを取得して、インストールを進めます。
リポジトリに含まれるパッケージを検索してみました。
$ apt search certbot
Sorting... Done
Full Text Search... Done
certbot/bionic-updates 0.27.0-1~ubuntu18.04.1 all
automatically configure HTTPS using Let's Encrypt
letsencrypt/bionic-updates 0.27.0-1~ubuntu18.04.1 all
transitional dummy package
(・・・中略・・・)
python3-certbot-nginx/bionic 0.23.0-1 all
Nginx plugin for Certbot
certbot
と python3-certbot-nginx
をインストールしました。
$ sudo apt install certbot python3-certbot-nginx
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python-pyicu python2.7 python2.7-minimal
python3-acme python3-certbot python3-configargparse python3-future python3-josepy python3-lib2to3 python3-mock python3-parsedatetime
python3-pbr python3-pyparsing python3-requests-toolbelt python3-rfc3339 python3-tz python3-zope.component python3-zope.event
python3-zope.hookable
Suggested packages:
python3-certbot-apache python-certbot-doc python-doc python-tk python2.7-doc binutils binfmt-support python-acme-doc
python-certbot-nginx-doc python-future-doc python-mock-doc python-pyparsing-doc
The following NEW packages will be installed:
certbot libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python-pyicu python2.7 python2.7-minimal
python3-acme python3-certbot python3-certbot-nginx python3-configargparse python3-future python3-josepy python3-lib2to3 python3-mock
python3-parsedatetime python3-pbr python3-pyparsing python3-requests-toolbelt python3-rfc3339 python3-tz python3-zope.component
python3-zope.event python3-zope.hookable
0 upgraded, 26 newly installed, 0 to remove and 27 not upgraded.
Need to get 5216 kB of archives.
After this operation, 24.1 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
(・・・中略・・・)
update-alternatives: using /usr/bin/python3-pasteurize to provide /usr/bin/pasteurize (pasteurize) in auto mode
Setting up python (2.7.15~rc1-1) ...
Setting up python-pyicu (1.9.8-0ubuntu1) ...
Setting up python3-acme (0.31.0-2~ubuntu18.04.1) ...
Setting up python3-parsedatetime (2.4-2) ...
Setting up python3-certbot (0.27.0-1~ubuntu18.04.1) ...
Setting up certbot (0.27.0-1~ubuntu18.04.1) ...
Created symlink /etc/systemd/system/timers.target.wants/certbot.timer → /lib/systemd/system/certbot.timer.
Setting up python3-certbot-nginx (0.23.0-1) ...
Processing triggers for mime-support (3.60ubuntu1) ...
インストール処理は、先ほどのコマンド一発で完了でした。
続いて、いよいよ certbot を使って、ドメインの登録&SSL証明書の取得の作業に進みます。
certbotを使ったドメインの登録とSSL証明書の取得
さっそく、certbot を使って、Let\’s Encrypt にドメインを登録し、SSL証明書を取得しました。
登録するドメインは yuukou-exp.plus
です。
緊急時の連絡用メールアドレス(恐らく、証明書の有効期限が迫ることを知らせるアラートメール用?)も、求められたので登録しました。
certbot には、以下のオプションを指定します。
- Nginxを使っているので、
--nginx
-
ドメインには
yuukou-exp.plus
を指定するので、-d yuukou-exp.plus
実行したコマンドと、その出力はこちらです。
$ sudo certbot --nginx -d yuukou-exp.plus
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): **********@gmail.com # ← ここで緊急連絡用のメールアドレスを入力
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A # ← 合意を求められるので `A` を入力してEnter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y # ← 合意を求められるので `Y` を入力してEnter
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for yuukou-exp.plus
Using default addresses 80 and [::]:80 ipv6only=on for authentication.
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/default
# HTTP リクエストが来た際の振る舞いについての質問
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2 # ← HTTPS 側にリダイレクトする設定を希望したので `2` と入力してEnter
No matching insecure server blocks listening on port 80 found.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://yuukou-exp.plus
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=yuukou-exp.plus
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/yuukou-exp.plus/privkey.pem
Your cert will expire on 2020-02-07. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the certonly option. To non-interactively renew *all* of
your certificates, run certbot renew
- 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
- 証明書は、
/etc/letsencrypt/live/yuukou-exp.plus
以下に保存されます。/etc/letsencrypt/live/(ドメイン名)
ということになりますね。
- 有効期限が来る前に
certbot renrew
を実行すれば、設定している全ての証明書を更新できます。
certbot で変更された Nginx の設定を確認&修正
SSL用にNGINXの設定を変更したことが画面に表示されていたので、内容を確認しました。
すると、変更が加わっていたのは、 /etc/nginx/sites-enabled/default
の方でした。 追加された行は以下の通りです。
server_name yuukou-exp.plus; # managed by Certbot
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/yuukou-exp.plus/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
Nginxの設定ファイルが、以下のような構造になっていれば、大丈夫です。
(ウェブサーバーの設定部分(※1)は、お好みのスタイルで。直接書いても良し、別ファイルに分けてincludeするも良しです)
# HTTPSへのリダイレクト設定(1)
server {
listen 80;
server_name yuukou-exp.plus;
return 301 https://yuukou-exp.plus$request_uri;
}
# HTTPSへのリダイレクト設定(1)
server {
listen 80;
server_name www.yuukou-exp.plus;
return 301 https://yuukou-exp.plus$request_uri;
}
# HTTPS用ウェブサーバー設定
server {
client_max_body_size 10m;
server_name yuukou-exp.plus;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl on;
ssl_certificate /etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/yuukou-exp.plus/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# 以下、ウェブサーバーの設定(※1)
...
}
DNSレコードにLet\’s Encryptを登録する
certbot を使い、SSL証明書をインストールし、Nginxを再起動すると、ウェブサイト https://yuukou-exp.plus にアクセスすることが出来るようになっていました。
証明書情報を見ると、有効期限が作業日から約90日後の2020/02/08
になっていることを確認できました。
しかし、完全には信用できないとか条件付きのメッセージが一緒に表示されているのが気になります。
certbot によるドメイン設定時に表示された、証明書確認用URLを叩いてみたところ、 DNS CAA
が無いという警告を見つけました。 https://www.ssllabs.com/ssltest/analyze.html?d=yuukou-exp.plus
調べたところ、証明書を発行する認証局をだます余地がある状態という意味であり、DNSサーバーに CAA レコード
を追加する必要があることが分かりました。
DNSには、AWS の Route53 を使っていたので、Route53の管理画面から、以下のレコードを追加しました。
yuukou-exp.plus. IN CAA 0 issue letsencrypt.org
それから5分ぐらい経過してからでしょうか、ブラウザでアクセスしたところ上記問題は解決していました。
Let\’s Encrypt のSSL証明書の組み込みは、以上で完了となります。
certbot を使ったSSL証明書の運用
Let\’s Encrypt を使ってSSL証明書を組み込んでしばらくたってから、SSL証明書の状態を確認しました。
SSL証明書の状態を把握するには、certificates
サブコマンドを指定します。
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: yuukou-exp.plus
Domains: yuukou-exp.plus
# ↓ 日本時間では 2020-02-08 01:00 に有効期限を迎える
Expiry Date: 2020-02-07 16:00:35+00:00 (VALID: 34 days)
Certificate Path: /etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem
Private Key Path: /etc/letsencrypt/live/yuukou-exp.plus/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
まだまだ、有効期限まで日数がありますね。
後述しますが実は、certbot は自動的に有効期限日数をチェックしており、それが30日を切ると自動的にSSL証明書の更新をしてくれます。
実際に更新される際、どんな出力がされるのか、確かめたいのですが、残り30日を切る絶妙なタイミングを待つというのも苦労が多く、しかもうっかりと見逃がしてしまいそうで懸念があります。
そんな時は、--dry-run
オプションを付けて certbot renew
を実行することで、リハーサルを体験することが出来ます。
$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yuukou-exp.plus.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for yuukou-exp.plus
Waiting for verification...
Cleaning up challenges
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of nginx server; fullchain is
/etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SSL証明書が実際に自動更新されているか確かめてみた
リハーサルもして、あとは certbot に任せれば安全!ということなのですが、何ぶん初めてのことなので、本当にSSL証明書を更新してくれるのか、気になります。
先ほど確認した有効期限(2020/02/08)まで30日を切った時点で、証明書の状態を確認してみました。 すると・・・ばっちり自動更新されていました!
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: yuukou-exp.plus
Domains: yuukou-exp.plus
# ↓ 証明書の有効期限が 2020-04-08 05:57 (日本時間)になっている
Expiry Date: 2020-04-07 20:57:30+00:00 (VALID: 75 days)
Certificate Path: /etc/letsencrypt/live/yuukou-exp.plus/fullchain.pem
Private Key Path: /etc/letsencrypt/live/yuukou-exp.plus/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
次の有効期限が、2020-04-07 20:57:30+00:00
に延びているのが分かります。(日本時間だと、2020-04-07 05:57:30
です)
これはありがたいですね!
メンテナンス作業いらずの自動化ツールが、しっかり働いているようです。
certbot の自動チェック処理、どのように実装されているのか気になりますね。
どこかに定期実行される処理を定義するスクリプトがあるはずです。
各ユーザーおよびrootユーザーの crontab にもcertbot由来の定期実行処理の定義が追加されている痕跡は見つかりませんでした。
となると、順当に考えて、探す場所は cron の設定ディレクトリ群になります。
/etc/cron.d
, /etc/cron.daily
, /etc/cron.hourly
, /etc/cron.monthly
, /etc/cron.weekly
を見て回ったところ、 /etc/cron.d
で certbot のスクリプトを発見しました。
$ cd /etc/cron.d
$ ll
total 28
drwxr-xr-x 2 root root 4096 Nov 9 16:55 ./
drwxr-xr-x 96 root root 4096 Jan 22 06:17 ../
-rw-r--r-- 1 root root 102 Nov 16 2017 .placeholder
(・・・中略・・・)
-rw-r--r-- 1 root root 485 Oct 3 19:49 certbot # ← これがcertbotのスクリプト
(・・・中略・・・)
その中身を確認したところ、半日に1回、証明書の自動更新処理を実行するものでした。BINGO!
certbot インストール時に一緒に配備されたスクリプトであることが分かります。
他の定期実行処理への考慮・配慮なのでしょうか。Perl でランダムな待機時間を設けてから、SSL証明書を更新しています。(時間差負荷分散になりますね)
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
こちらのエントリも併せてどうぞ!
目次 1 逆引き:Ubuntu環境で自分で作ったサービスをシステムに登録する1.1 systemd に開発したサービスを登録する1.2 自前サービスの定義する1.3 シンボリックリンクを張ってサービス定義を配備する1.4 systemctl コマンドを使ってサービスを登録する1.5 サービスが起動す […]
目次 0.1 概要0.2 インストール手順0.2.1 Hyper-V を有効化0.2.2 Docker Desktop for windows をインストールする0.2.3 インストーラーの起動0.2.4 インストール処理0.3 Docker Desktop の起動0.4 Docker Deskto […]
目次 1 今回はこのブログサイトのウェブサーバー構築のお話から1.1 Let\’s Encrypt について2 Let\’s EncryptのSSL証明書をインストールする環境について3 certbot のインストール4 certbotを使ったドメインの登録とSSL証明書の取 […]