server-memo.net

【CentOS7】Lets EncryptでSSL証明書を取得

   

「centOS 7」環境で「Lets Encrypt」のSSL証明書を取得する方法です。

事前準備

Lets EncryptでSSL証明書を取得する場合、事前に下記の設定を行っておく必要が有ります。

  • 証明書を取得対象のホスト名がインターネット上で名前解決できること
  • 80番または443番ポートで通信できること

上記の設定が完了していない場合は、まず先にDNSの設定やファイアウォールの設定を行っておいてください。

DNS設定

「Lets Encrypt」でSSL証明書を取得する場合、「Lets Encrypt」のサーバからSSL証明書を取得しようとしているホスト名(FQDN)へ接続し所有者かどうかの確認を行いますので、事前にインターネット上で名前解決ができるようにDNSの設定をしておく必要があります。

「80」「443」 ポート通信設定

確認の通信は「80/tcp」「443/tcp」ポート宛に行われるので、ファイアウォールで通信をブロックしている場合は、通信ができるようにポートの解放作業を行っておく必要があります。

cerbotのインストール

「Lets Encrypt」は「certbot」というクライアントを使用してSSL証明書の取得や更新を行うため、まずは「certbot」をインストールしていきます。

CentOS7の場合は「epelリポジトリ」からインストール可能なので、そちらからインストールを行っていきます。

# yum install --enablerepo=epel certbot

※epelリボジトリの使用できるようにする方法はこちらのページで説明しています。

SSL証明書の取得

インストールした「certbot」を使用して「Lets Encrypt」からSSL証明書を取得するには「--standalone」オプションを使用してする方法と「--webroot」オプションを使用する方法があります。

それぞれのオプションごと動作の違いは下記のようになります。

オプション 特徴
--standalone 「certbot」の簡易webサーバ機能を使用してドメイン所有者の確認を行うため、サーバ上で既に「apache」や「nginx」等のwebサーバが動作している場合は停止させる必要がある
--webroot ドメイン所有者の確認は既に動作している「apache」や「nginx」等のwebサーバを使用して行うため、webサーバを停止する必要がない。
ただし、ドキュメントルートに「.well-known」というディレクトリが作成され、その中に確認用の一時ファイルが自動作成される

私は勝手にサーバ上にディレクトリやファイルが作成されるのが嫌なので、「--standalone」オプションをいつも使用しています。後述する証明書の更新作業もアクセス数が少ない深夜帯に行えば影響も少ないですから。

webサーバを停止させたくない場合は「--webroot」オプションを使用すると良いでしょう。

どちらを使用するかは個人の好みなので、お好きなほうをお使いください。

--standalone オプション使用を使用する場合

「--standalone」オプションを使用してSSL証明書を取得する場合は、現在動作しているWebサーバを事前に停止させる必要があります。

webサーバを停止後下記コマンドを実行することで、「Let's encrypt」からSSL証明書を取得することが出来ます。

# certbot certonly --standalone -d ホスト名 -m 連絡先メールアドレス --agree-tos

初回実行時は「Electronic Frontier Foundation」からのメール通知を受け取るかの確認がありますので、「Y」(Yes)か「N」(No)のお好きなほうを指定してください。

-------------------------------------------------------------------------------
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 EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: N

実行例

下記の内容で「--standalone」オプションを使用してSSL証明書を取得する実行例となります。

  • SSL証明書取得ホスト名 conoha.server-memo.net
  • 連絡先メールアドレス tamohiko@server-memo.net

webサーバは「nginx」を使用しています。

# systemctl stop nginx
# certbot certonly --standalone -d conoha.server-memo.net -m tamohiko@server-memo.net --agree-tos
# systemctl start nginx

--webroot オプションを使用使用する場合

「--webroot」オプションを使用する場合は、現在動作しているwebサーバを停止する必要がありませんので、下記コマンドを実行することでSSL証明書を取得することが出来ます。

ドキュメントルートはwebサーバで設定しているディレクトリを指定します。

# certbot certonly --webroot -w ドキュメントルート -d ホスト名 -m 連絡先メールアドレス --agree-tos

こちらの場合も「--standalone」オプションを使用した場合と同じく、初回実行時は「Electronic Frontier Foundation」からのメール通知を受け取るかの確認がありますので、「Y」(Yes)か「N」(No)のお好きなほうを指定してください。

実行例

下記は私が実際にSSL証明書を取得した際の作業ログとなります。

webサーバは「nginx」を使用し、下記内容で証明書を取得しています。

  • ドキュメントルート /usr/share/nginx/conoha/
  • SSL証明書取得ホスト名 conoha.server-memo.net
  • 連絡先メールアドレス tamohiko@server-memo.net
# certbot certonly --webroot -w /usr/share/nginx/conoha/ -d conoha.server-memo.net -m tamohiko@server-memo.net --agree-tos

オプション説明

「certbot」を使用してSSL証明書を取得する際に使用しそうなオプションについて説明しておきます。

オプション 説明
certonly 証明書の発行のみ実施
--standalone SSL証明書を取得する際にcertbotに内蔵されているwebクライアントを使用する
この場合、現在起動しているwebサーバを停止させる必要がある
--webroot webサーバを起動させたままでSSL証明書を発行したい場合に使用
-w webrootを使用する場合に証明書の一時保管ディレクトリを指定
-d 証明書を作成するホスト名(FQDN)を指定する
複数指定も可能で、その場合は一つの証明書で複数のホスト名に対応する
-m 連絡先メールアドレスを指定
このアドレスにSSL証明書の期限切れ等の連絡が送信される
--agree-tos 利用規約へ同意する
--dry-run テスト用オプション
実際に証明書を取得・更新せずにテストを行うことができる

証明書の保管場所

作成された証明書の実体は「/etc/letsencrypt/archive/ホスト名(ドメイン名)」ディレクトリ配下に格納されます。

ただし、ここに作成される証明書は更新作業を行う度にファイル名の数字部分が増加したファイル新しく作成されていきます。

証明書更新作業前
# ls -l /etc/letsencrypt/archive/conoha.server-memo.net/
total 16
-rw-r--r-- 1 root root 1818 Apr  7 21:30 cert1.pem
-rw-r--r-- 1 root root 1647 Apr  7 21:30 chain1.pem
-rw-r--r-- 1 root root 3465 Apr  7 21:30 fullchain1.pem
-rw-r--r-- 1 root root 1704 Apr  7 21:30 privkey1.pem
証明書更新作業後

「cert2.pem」「chain2.pem」「fullchain2.pem」「privkey2.pem」といったように、数字部分が増加したファイルが新しく作成されていることが確認できます。

# ls -l /etc/letsencrypt/archive/conoha.server-memo.net/
total 32
-rw-r--r-- 1 root root 1818 Apr  7 21:30 cert1.pem
-rw-r--r-- 1 root root 1818 Apr 14 18:14 cert2.pem
-rw-r--r-- 1 root root 1647 Apr  7 21:30 chain1.pem
-rw-r--r-- 1 root root 1647 Apr 14 18:14 chain2.pem
-rw-r--r-- 1 root root 3465 Apr  7 21:30 fullchain1.pem
-rw-r--r-- 1 root root 3465 Apr 14 18:14 fullchain2.pem
-rw-r--r-- 1 root root 1704 Apr  7 21:30 privkey1.pem
-rw-r--r-- 1 root root 1704 Apr 14 18:14 privkey2.pem

証明書を使用する場合

Webサーバ等でSSL証明書を使用する場合、実ファイルをの方を指定してしまうと、証明書を更新するたびに設定ファイルの証明書のファイル名を編集する必要が出てきてとても面倒な事になります。

ですので、実際に設定する場合は「/etc/letsencrypt/live/ホスト名(ドメイン名)」ディレクトリにある、シンボリックリンクをSSLの証明書として設定ファイルに指定するようにします。

こちらのリンクは証明書を更新すると、自動的に新しい証明書の方にリンクを張りなおしてくれので、証明書の更新時に設定ファイルの編集を行う必要がなくなります。

SSL証明書更新前

SSL証明書へのシンボリックリンクとなっていることが確認できます。

# ls -l /etc/letsencrypt/live/conoha.server-memo.net/
total 4
lrwxrwxrwx 1 root root  46 Apr  7 21:30 cert.pem -> ../../archive/conoha.server-memo.net/cert1.pem
lrwxrwxrwx 1 root root  47 Apr  7 21:30 chain.pem -> ../../archive/conoha.server-memo.net/chain1.pem
lrwxrwxrwx 1 root root  51 Apr  7 21:30 fullchain.pem -> ../../archive/conoha.server-memo.net/fullchain1.pem
lrwxrwxrwx 1 root root  49 Apr  7 21:30 privkey.pem -> ../../archive/conoha.server-memo.net/privkey1.pem
-rw-r--r-- 1 root root 543 Apr  7 21:30 README
SSL証明書更新後

SSL証明書の更新作業後に確認してみると、新しいファイルにリンクされていることが確認できます。

# ls -l /etc/letsencrypt/live/conoha.server-memo.net/
total 4
lrwxrwxrwx 1 root root  46 Apr 14 18:14 cert.pem -> ../../archive/conoha.server-memo.net/cert2.pem
lrwxrwxrwx 1 root root  47 Apr 14 18:14 chain.pem -> ../../archive/conoha.server-memo.net/chain2.pem
lrwxrwxrwx 1 root root  51 Apr 14 18:14 fullchain.pem -> ../../archive/conoha.server-memo.net/fullchain2.pem
lrwxrwxrwx 1 root root  49 Apr 14 18:14 privkey.pem -> ../../archive/conoha.server-memo.net/privkey2.pem
-rw-r--r-- 1 root root 543 Apr  7 21:30 README

SSL証明書の自動更新

「lets encrypt」で取得することができるSSL証明書の有効期限は90日間と短く、毎回手動で更新していると更新忘れなどが起きそうなので、「cron」に登録して自動更新を行うようにしていきます。

更新用スクリプト作成

まずは「cron」に登録するために更新用スクリプトを作成していきます。

# vi /root/sslcert-renew.sh

※スクリプトの名前や場所に決まりはないのでお好きな名前で作成してください。

スクリプト内容

このスクリプトは下記の動作を実装しています。

  • 「--standalone」と「--webroot」両方のオプションに対応
  • 実行時のログを任意のファイルに出力
  • 更新の結果(成功・失敗)をメール送信

スクリプト自体はとても単純なので、お好きなようにカスタマイズして使用してください。

変数説明
変数 説明
MAILTO 通知先メールアドレスを設定
LOGFILE ログ出力先を設定(任意の場所を指定)
CERTBOT certbotの場所をフルパスで設定
WEB_START webサーバの起動コマンドを設定
「--standalone」オプション使用時用
WEB_STOP webサーバの停止コマンドを設定
「--standalone」オプション使用時用
WEB_RELOAD webサーバの設定再読み込みコマンドを設定
「--webroot」オプション使用時用

下記スクリプトはwebサーバが「nginx」を想定したスクリプトとなっています、「apache」の場合は「WEB_START」「WEB_STOP」「WEB_RELOAD」部分を適宜置き換えてください。

#!/bin/bash
MAILTO=通知先メールアドレス

LOGFILE=/var/log/renew_sslcert.log
CERTBOT=/bin/certbot
WEB_START="/bin/systemctl start nginx"
WEB_STOP="/bin/systemctl stop nginx"
WEB_RELOAD="/bin/systemctl reload nginx"


echo "===== Start renew sequence Let's Encrypt SSL Cert  `date` =====" >> $LOGFILE

### test setting ###
# --standalone option test setting
#$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" --dry-run >> $LOGFILE

# --webroot option test setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" --dry-run >> $LOGFILE

### renew setting ###
# --standalone option setting
$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" >> $LOGFILE

# --webroot option setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" >> $LOGFILE


STATUS=$?


if [ "$STATUS" != 0 ]; then
    echo "Failed renew SSL cert." >> $LOGFILE
    echo "Failed renew SSL cert. " |\
    mail -s "Faild renew SSL cert in `hostname`" $MAILTO
  else
    echo " Complete renew SSL cert." >> $LOGFILE
    echo " Complete renew SSL cert." |\
    mail -s "Complete renew SSL Cert in `hostname`" $MAILTO
fi

echo "===== End renew sequence Let's Encrypt SSL Cert  `date` ======" >> $LOGFILE

使用方法

スクリプトには、テスト用(test setting)と本番用(renew setting)が用意されていて、それぞれに「--standalone」と「--webroot」オプションで使用するコマンドが記述されています。

有効化したいコマンド部分の「#」を削除し有効化し、それ以外は「#」を付けてコメントに設定を無効化して使用していください。

### test setting ###
# --standalone option setting
#$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" --dry-run >> $LOGFILE

# --webroot option setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" --dry-run >> $LOGFILE

### renew setting ###
# --standalone option setting
$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" >> $LOGFILE

# --webroot option setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" >> $LOGFILE

※上記の場合は「--standalone」オプションを使用して、実際にSSL証明書を更新させるコマンドが有効となっています。

スクリプト説明

webサーバの停止・起動・再読み込みについて

「--standalone」オプションをしている場合は、SSL証明書を更新する際にwebサーバを停止させる必要があるのですが、それは「certbot」の「--pre-hook」(更新前に実行する動作を設定)と「--post-hook」(更新後に実行する動作を設定)の機能を使用して実装しています。

「--webroot」オプションを使用している場合は、SSL証明書を更新した際に証明書を再読み込みさせるために「--post-hook」でwebサーバの設定を再読み込みさせています。

証明書の更新頻度について

証明書発行側の無駄な負荷を避けるために、証明書の有効期限が30日未満の場合更新されるようになっています。

30日未満以外の場合も証明書を更新したい場合は「$CERTBOT renew」の部分に「--force-renew」オプションを追加して「$CERTBOT renew --force-renew」とすることで、強制的に証明書を更新することが出来ます。

パーミッション変更

スクリプトが作成できましたら、パーミッションを変更してスクリプトを実行できるようにしておきます。

# chmod 744 sslcert-renew.sh

動作試験

スクリプトの作成が終わりましたら、スクリプト内の「test setting」部分の設定を有効化して動作試験を行っていきます。

下記は「--standalone」オプションを使用時のテスト実施設定となります。
これで「--dry-run」オプションが有効となり、実際に証明書を更新することなく動作試験を行うことができるようになります。

変更部分
### test setting ###
# --standalone option setting
$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" --dry-run >> $LOGFILE

# --webroot option setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" --dry-run >> $LOGFILE

### renew setting ###
# --standalone option setting
#$CERTBOT renew --pre-hook "$WEB_STOP" --post-hook "$WEB_START" >> $LOGFILE

# --webroot option setting
#$CERTBOT renew --webroot --post-hook "$WEB_RELOAD" >> $LOGFILE

スクリプトの設定変更が完了しましたら、スクリプトを実行して動作確認を実施してください。

# sh -x /root/sslcert-renew.sh

メール通知やログ出力についても確認してください。

動作確認完了後は、動作確認用に変更した部分をもとに戻すのを忘れないようにしてください。

crontabへ登録

作成したスクリプトが正常に動作することが確認できましたら、「crontab」にでも登録して、定期的にスクリプトが実行されるように設定します。

# cp -p /etc/crontab /etc/crontab_yyyymmdd
# vi /etc/crontab

2週間に1回程度スクリプトが実行されるように設定しておけば安心でしょう。(心配であれば毎週でもよいです)

下記設定は毎月1日と15日のAM4:00にスクリプトが実行される設定となります。

00 04 01,15 * * root /root/sslcert-renew.sh

実行する日時には特に決まりがないので、お好きな時間に設定してください。
ただし、「--standalone」オプションを使用してSSL証明書の更新を行う場合はWebサーバ停止するので、できるだけアクセスが少ない時間帯が良いと思います。

 - Tips