無料SSL「Let’s Encrypt」を設定する

社内資料として非公開していた情報を整理しながら公開していくシリーズです。
若干情報が古い場合もありますがご了承ください。

さて今回は、無料SSLで有名なLet's Encryptについて書いていってみたいと思います。

初めてのインストール

1つ目のドメインを設定しながら、Let's Encryptをセットアップしていきます。
2つ目からは一部手順を省略する形になります。

事前準備

まずは確認しましょう。

rpm -qa | grep centos-release

CentOS 6

CentOS 6の場合は「epel-release」をインストールします。

yum install epel-release

CentOS 7

CentOS 7の場合は「epel-release」に加えて「certbot python-certbot-apache」もインストールします。

yum install epel-release
yum install certbot python-certbot-apache

インストール

curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
chmod 700 /usr/bin/certbot-auto
/usr/bin/certbot-auto certonly --webroot -w /var/www/vhosts/example.com/public_html --email example@example.com --debug -d example.com

▲こちらの内容は自分の環境に合わせて書き換えてください。
分解すると次のような設定になります。「」の個所を書き換えます。

/usr/bin/certbot-auto certonly --webroot -w 「ドキュメントルート」 --email 「自分のメールアドレス」 --debug -d 「ドメイン」

初回は必要なパッケージが読み込まれます。

-------------------------------------------------------------------------------
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
-------------------------------------------------------------------------------
(A)gree/(C)ancel: a

「利用規約を読んで同意してください。」といった内容です。
画面にある https:// ~ のURLをコピペしてブラウザで開いて内容を確認します。
※上記は2016.pdfになっているので最新版はファイルが変わると思います。

同意する場合は、「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 EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: n

「Certbotを開発する組織ですか?」と聞かれてる個所があるので、「いいえ」かな。

「n」を入力してEnterします。

このままトラブルなく進んでいくと証明書が作成されます。

2つ目以降のドメインを追加

1つ目のドメインを追加するときは、Let's Encryptのインストールや設定も兼ねていたのですが、2つ目のドメインからは証明書の発行部分だけになります。

1つ目のときと内容は同じになりますが、下記を実行して証明書を作成します。

/usr/bin/certbot-auto certonly --webroot -w /var/www/vhosts/example.com/public_html --email example@example.com --debug -d example.com

▲こちらの内容は自分の環境に合わせて書き換えてください。
分解すると次のような設定になります。「」の個所を書き換えます。

/usr/bin/certbot-auto certonly --webroot -w 「ドキュメントルート」 --email 「自分のメールアドレス」 --debug -d 「ドメイン」

証明書の確認

作成された証明書は次の場所にあります。

ls -la /etc/letsencrypt/live

httpd.confに設定

apache 2.4

SSLCertificateFile    /etc/letsencrypt/live/ドメイン/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/ドメイン/privkey.pem

apache 2.2

SSLCertificateKeyFile   /etc/letsencrypt/live/ドメイン/privkey.pem
SSLCertificateFile      /etc/letsencrypt/live/ドメイン/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/ドメイン/chain.pemBashCopy

apacheの再起動

設定を反映させるため再起動します。

/etc/init.d/httpd restart

証明書の自動更新設定

自動化はCRONに設定するので、まずは手動で動かしてみて確認します。

/usr/bin/certbot-auto renew --post-hook "/etc/init.d/httpd restart"

この時点では期限切れの証明書もないので、「更新対象なし」として終了します。

問題無さそうなのでCRONに設定します。

vi /etc/cron.d/letsencrypt
MAILTO="通知先にする自分のメールアドレス"
0 2 * * 2 root /usr/bin/certbot-auto renew --post-hook "/etc/init.d/httpd restart"

実行時間はそんなに頻繁でなくて構いません。
上記だと「毎週火曜の午前2時0分」の設定なので週一実行です。
証明書の期限は90日です。
期限切れが近づいてきたときに更新処理が実行されれば更新されますが、まだまだ期限があるときに実行しても何も行われません。

不要になった証明書を削除

公開が終了したり、サーバを引越ししたりして使わなくなったドメインは証明書を削除しましょう。

次の手順で行います。
「ドメイン」の2カ所を書き換えてください。

# 確認
ls -la /etc/letsencrypt/live

# 失効
/usr/bin/certbot-auto revoke --cert-path=/etc/letsencrypt/archive/ドメイン/cert1.pem

# 削除
/usr/bin/certbot-auto delete -d ドメイン

トラブル対応

証明書の発行でエラーになる

次のようなエラーが発生したときの対応方法を記します。

Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator webroot, Installer None
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for www.example.net
Using the webroot path /home/example_net/public_html for all unmatched domains.
Waiting for verification...
Challenge failed for domain www.example.net
http-01 challenge for www.example.net
Cleaning up challenges
Attempting to renew cert (www.example.net) from /etc/letsencrypt/renewal/www.example.net.conf produced an unexpected error: Some challenges have failed.. Skipping.
IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: www.example.net
   Type:   unauthorized
   Detail: Invalid response from
   https://www.example.net/.well-known/acme-challenge/xxxxxx
   [xxx.xxx.xxx.xxx]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML
   2.0//EN\">\n<html><head>\n<title>403
   Forbidden</title>\n</head><body>\n<h1>Forbidden</h1>\n<p"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

2つ目のメッセージに「https://www.example.net/.well-known/acme-challenge/xxxxxx」の個所があります。
XXXXXXは毎回ランダムな文字に変わります。

証明書の発行では、Let's Encryptからこのファイルをチェックしにくる仕組みになっているのですが、アクセスできなかったためにエラーになったことを意味します。

認証ファイルは生成できていますか?

ドキュメントルート直下に「 .well-known 」が自動生成されているはずですが、存在するでしょうか。
存在しない場合は、ドキュメントルートの指定でパスを間違っていないか確認してみます。

リダイレクト設定は正しいですか?

htaccessでリダイレクトしている場合、 .well-known 以下もリダイレクト範囲に入っていないでしょうか。

http でアクセスできますか?

80番ポート(http)でアクセスできるでしょうか?
常時SSLにしたいので「http は閉じちゃえっ!」と言いたいところですが、Let's Encryptの認証は http にやってきます。

ただし、http から https にリダイレクトすることはサポートされています。
WEBサーバの設定として、http のアクセスを問答無用で https にリダイレクトすることで対応できます。
こちらの詳細は公式のこちらをご覧ください。

海外アクセスを拒否していませんか?

証明書の発行には Let's Encrypt からのアクセスを許可する必要があります。

海外からのアクセスをIPアドレス判定で拒否していることもあると思いますが、 Let's Encrypt からのアクセスは許可しておかないと証明書が発行できません。

いくつかある解決策のうちの1つですが次のようにすることもできます。

vi ドキュメントルート/.well-known/.htaccess
order deny,allow
deny from all
allow from 66.133.109.36

.well-known 以下に限定して、IPアドレスを指定してアクセスを許可しています。

ただしこの方法には重大な決定があって、 Let's Encrypt から接続してくるIPアドレスはこの1つだけとは限らないことです。2020年1月現在で5つくらいのIPアドレスがあるようです。
そして、 Let's Encrypt の公式発表としてはIPアドレスを公開していないことになっています。

そもそも、海外アクセスを拒否する目的は .well-known とは無関係なので、 .well-known 以下のアクセスは特に制限することなく全公開で良いじゃないかと思います。

vi ドキュメントルート/.well-known/.htaccess
order allow,deny
allow from all

こうですね。
.well-known の下に .htaccess を置くのがポイントです。