Let’s Encrypt SSL 証明書の更新時のエラー

クラウド

SSL 証明書の更新に失敗する
SSL 証明書の更新時(certbot renew)に以下のエラーが発生する場合があります。

Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Some challenges have failed.. Skipping.

example.com.conf から証明書を更新しようとすると、予期しないエラーが発生しました。
いくつかのチャレンジが失敗しました。

The following certs could not be renewed:
/etc/letsencrypt/live/example.com/fullchain.pem (failure)

  Domain: example.com
   Type:   unauthorized
   Detail: Invalid response from
   http://example.com/.well-known/acme-challenge/jg6hppppE41mW96wqqqq4arrrrrhOouKRGssss2USaI
   [12.225.xxx.xx]: "<!DOCTYPE html>\n<html
   lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>404 Page Not
   Found</title>\n<style type=\"text/css\">\n\n::sele"

   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.

Let’s Encrypt は、/.well-known/acme-challenge/にアクセスすることで認証を行うため、外部からこの URI にアクセスできる必要があります。
例えば .htaccess などですべてのアクセスを Rewrite によって index.php に飛ばしている場合などでは、このエラーになります。
RewriteCond で、.well-known を無視するよう設定しましょう。

RewriteCond $1 !^(index\.php|.well-known|assets|robots\.txt|favicon\.ico)



Let’s Encrypt のすすめ
Let’s Encrypt とは、非営利団体の Internet Security Research Group により運営されている証明書認証局で、SSL 証明書を無料で発行しているため、Web サイトの HTTPS 化(SSL の導入)にお勧めです。

AWS(Amazon Web Service)や GCP(Google Coloud Platform)などの IaaS では、無料で SSL の導入ができるということでそちらを利用している方も多いかと思いますが、AWS にしても GCP にしても証明書の適用にはロードバランサーが必要で、実はこれが有償になります。

Amazon EC2 の場合

Amazon EC2 のロードバランサーの料金


GCE(Google Compute Engine)の場合

GCE のロードバランサーの料金


そもそも負荷分散が必要なほどのサーバであればいいのですが、なくても問題ないということであればこれが丸々 SSL の導入コストとなります。
意外と馬鹿にならない金額かと思いますし、無駄な中継はレスポンス性能を落とすだけなのであまり得策とは思えません。

Let’s Encrypt であれば正真正銘無料ですし、導入も簡単です。
残念ながらワイルドカード(マルチドメイン)には対応していませんが、1つのサーバで複数のドメインを公開している場合でも適用可能です。
※一部複数の利用ができないホスティングサービスがあります。

SSL 証明書の取得・適用
※各ホスティングサービスによって若干の手順の違いがあります。

certbot をインストールします。
EPELリポジトリが必要な場合はまずはそちらから。

>yum install epel-release
>yum install certbot python3-certbot-apache # apache
>yum install certbot python2-certbot-nginx # nginx

インストールした certbot を利用してSSL証明書を取得します。

>certbot --apache -d example.com # apache
>certbot --nginx -d example.com # nginx


上記コマンド実行後、certbot は以下の内容を聞いてきますのでそれに答えます。
以下はその内容と回答例です。

1) 証明書の期限切れを通知するメールアドレス
 → メールアドレスを入力します。

2) 利用規約に同意しますか?
 → A(Agree 同意します)

3) メールアドレス情報を共有しますか?
 → N(共有しません)

4) http のアクセスを https にリダイレクトさせるか?
 → 2(リダイレクトさせる)

これで SSL 証明書が取得できました。
証明書は/etc/letsencrypt/live/{ドメイン名}配下に作成され、apache や nginx の設定ファイルを検出して自動で適用してくれます。

# 追記される
SSLCertificateFile			/etc/letsencrypt/live/{ドメイン名}/cert.pem
SSLCertificateKeyFile		/etc/letsencrypt/live/{ドメイン名}/privkey.pem
SSLCertificateChainFile		/etc/letsencrypt/live/{ドメイン名}/chain.pem
# 追記される
ssl_certificate			/etc/letsencrypt/live/data.sample.co.jp/fullchain.pem;
ssl_certificate_key		/etc/letsencrypt/live/data.sample.co.jp/privkey.pem;

あとは、web サーバを再起動して完了です。

>systemctl restart httpd # apache
>systemctl restart nginx # nginx


証明書の更新
Let’s Encrypt で取得した証明書は有効期限が3ヶ月であるため、証明書の有効期限を延長します。
更新は certbot コマンドでできますが、3ヶ月ごとに更新作業をするのも面倒なので、cron にまかせましょう。
更新処理後は、web サーバの reload が必要になりますので、certbot の hook オプションを利用しましょう。

# 毎週日曜日の 0:00 に実行
0 0 * * 0 root certbot renew --post-hook "systemctl reload httpd" # apache
0 0 * * 0 root certbot renew --post-hook "systemctl reload nginx" # nginx
pre-hookcertbot の証明書更新処理の開始前に実行
post-hookcertbot の証明書更新処理の終了後に実行
deploy-hook証明書ごとに更新処理が成功したときのみ実行

certbot-renew.timer という自動更新用のタイマーユニットがあるそうなので、こちらを利用する方が良いかもしれません。

>vim /etc/sysconfig/certbot
POST_HOOK="--post-hook 'systemctl reload nginx'" # POST_HOOKの行にreloadの記述を追記

>systemctl enable certbot-renew.timer
>systemctl list-timers



トラブルへの対処

apache 再起動時にエラー
以下のエラーが発生する場合、

Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service"
and "journalctl -xe" for details.

mod_ssl が入っていない可能性があります。

>yum list installed | grep mod_ssl # mod_sslがインストールされているか確認
>yum install mod_ssl # mod_sslをインストール
>vim /etc/httpd/conf.modules.d/00-ssl.conf # apacheの設定
LoadModule ssl_module modules/mod_ssl.so # 追記
>systemctl restart httpd


繋がらない
SELinux は disabled になっていますか?
SELinux は色々と難しいので、まずは disabled にしてここが原因かどうか確認してみましょう。

>vim /etc/selinux/config
SELINUX=disabled

443 ポートは開放されていますか?

>firewall-cmd --list-all # httpsがあるかどうか確認
services: http https

# httpsがなければ追加します
>firewall-cmd --add-service=https [--zone=public] --permanent
>firewall-cmd --reload

コメント