/ letsencrypt

Let's Encrypt automatic update failure

Let's Encryptからこんなメールが来ていました。

Your certificate (or certificates) for the names listed below will expire in
19 days (on 21 Mar 17 04:30 +0000). Please make sure to renew
your certificate before then, or visitors to your website will encounter errors.

lorentzca.me

...

個人サーバで持ってるドメインのSSL証明書はLet's Encryptのものを使っており、certbotで自動更新しています。certbotは証明書の期限が1ヶ月を切ると証明書をアップデートしてくれます。

なので上のメールのように証明書の期限が残り19日と言うのは異常事態なのです。

Let's Encryptで管理している証明書は4つあり、そのうちの1つで更新がうまく行っていないようです。

手動実行したら以下のようなエラーが出ました。

$ sudo /usr/bin/certbot renew --post-hook "systemctl restart h2o"
...
2017-03-02 00:08:15,469:WARNING:certbot.renewal:Attempting to renew cert from /etc/letsencrypt/renewal/lorentzca.me.conf produced an unexpected error: Failed authorization procedure. lorentzca.me (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://lorentzca.me/.well-known/acme-challenge/O4pA5V2WArdhj29DOZAbie6JMJnRmnekfGgNufx4rjI [188.166.206.17]: 404. Skipping.

原因調査

エラーを見るとLet's Encryptが外部から認証しに来るためのhttp://lorentzca.me/.well-known以下のpathが404になっています。

しかし、ブラウザでアクセスするとhttp://lorentzca.me/.well-knownへはアクセスできます。

うーん。次にLet's Encryptの認証方式などが設定されている/etc/letsencrypt/renewal/lorentzca.me.confファイルを見てみると、以下のようになっていました。

# renew_before_expiry = 30 days
version = 0.8.1
cert = /etc/letsencrypt/live/lorentzca.me/cert.pem
privkey = /etc/letsencrypt/live/lorentzca.me/privkey.pem
chain = /etc/letsencrypt/live/lorentzca.me/chain.pem
fullchain = /etc/letsencrypt/live/lorentzca.me/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = webroot
installer = None
account = xxxxxxxxxxxxxxxxxxxxxxxx
webroot_path = /var/www/ghost,
[[webroot_map]]
lorentzca.me = /var/www/ghost

何かおかしい...。lorentzca.meのpathは/var/www/toppageにしているのですが、/var/www/ghost/var/www/ghost,となっている...。

これら部分を/var/www/toppageになおして再度手動実行。

$ sudo /usr/bin/certbot renew --post-hook "systemctl restart h2o"

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/ghost.ponpokopon.me.conf
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/ponpokopon.me.conf
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/lorentzca.me.conf
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/lorentzca.me/fullchain.pem
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/blog.lorentzca.me.conf
-------------------------------------------------------------------------------

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/ghost.ponpokopon.me/fullchain.pem (skipped)
  /etc/letsencrypt/live/ponpokopon.me/fullchain.pem (skipped)
  /etc/letsencrypt/live/blog.lorentzca.me/fullchain.pem (skipped)
Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/lorentzca.me/fullchain.pem (success)

無事更新された!✨

期限もopensslコマンドから5月に伸びたのを確認できました。

  • s_clientで対象ホストにSSL接続
  • 入力受付状態になるので/dev/null流し込んで終了させる
  • 受け取った証明書をx509形式(公開鍵の形式)で読み込ませ-textで人にわかる形に復号
  • 適当にgrepして日付を確認
$ openssl s_client -connect lorentzca.me:443 < /dev/null | openssl x509 -text | grep Not
depth=1 /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
verify error:num=20:unable to get local issuer certificate
verify return:0
DONE
            Not Before: Mar  1 14:25:00 2017 GMT
            Not After : May 30 14:25:00 2017 GMT
                  User Notice:

根本的な原因

根本的な原因(lorentzca.me.confがおかしい原因)はおそらく新ドメイン切り替えのタイミングで、certbotコマンドをtypoした状態で実行し証明書を取得してしまったからと思われる。

問題となった部分は# Options used in the renewal processとあるように、更新のタイミングで使われる値だったので、初回取得時は問題にならず、更新のタイミングで爆発したんだと思う。

感想

初回更新までは油断できないな...。初回は強制更新オプションをつけて更新の動作確認をしたほうが良いかも。

自動化は人が関わらない分楽で良いけど、人知れずひっそりシステムが死んでいるかもしれないので、自動化の仕組みがちゃんと動いているかを監視する機構は必須だなあと思いました(今回の場合は自動更新が発動される日時より証明書の期限が短ければアラートが来るように設定している)。

Let's Encryptを個人サーバ(CentOS7)で動かして暫く経つので、そろそろまとめておきたい。