MyDNSのLet’s Encryptのワイルドカード自動更新を導入した

前回(Let’s Encrypt でSSLワイルドカード証明書を導入する)の続き?
MyDNSが公開しているPHPのscriptを導入して、renewが行えるようにした。

背景

もともとLet’s Encryptでワイルドカード証明書を導入する前はcertbot renewをcronに登録していて放置していた。
そしてDNSのときのと同じくこちらも無料でアラートメールをもらって気づいた
前回(Let’s Encrypt でSSLワイルドカード証明書を導入する)重い腰を上げて導入したワイルドカード証明書関係が更新できていないようだ
そのあたりを調査して、MyDNSの自動更新スクリプトを導入した。というお話
ちなみにアラートメールはこんな感じ

Let’s Encryptからのアラートメールはこんな感じ

JTrimでコピペしたんだけど、jpg圧縮の品質悪いっすね
Affinityもってるんだから、面倒臭がらないで、そっちでするべきだったか

現状

アラートメールを受けて、まずはcronに登録しているコマンドを実施確認
(と、その前にまずはcron確認)

# crontab -l
* * * * * /bin/certbot renew && /bin/systemctl reload nginx
→certbotはrootで動かしているが、他のユーザ管理にしたいね
→cronの時間は念の為マスク

# type certbot
certbot is hashed (/usr/bin/certbot)
# which certbot
/usr/bin/certbot
# ls /bin/certbot -l
-rwxr-xr-x 1 root root 960 Apr  7 10:01 /bin/certbot
# ls /usr/bin/certbot -l
-rwxr-xr-x 1 root root 960 Apr  7 10:01 /usr/bin/certbot
→ cronに登録しているcertbotが/binにたいして、certbotは/usr/binにあった
→ シンボリックリンクでもハードリンクでもない
# sha256sum /bin/certbot
2e92fb3a6ca39f7de974ca3e4161197cc347139da68484398e575ec817600587  /bin/certbot
# sha256sum /usr/bin/certbot
2e92fb3a6ca39f7de974ca3e4161197cc347139da68484398e575ec817600587  /usr/bin/certbot
→どっちとも同じハッシュで問題もなく動くが、/usrに変更
# crontab -e
crontab: installing new crontab
# crontab -l
* * * * * /usr/bin/certbot renew && /bin/systemctl reload nginx
→cronの時間は念の為マスク

certbot確認

# certbot renew
(抜粋)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/meto4d.pgw.jp.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.')
Failed to renew certificate meto4d.pgw.jp with error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.')

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

プラグインエラーが起きているから--manual-auth-hookを使えとのこと

certbot certonly --manual --manual-auth-hook /path/to/http/authenticator.sh --manual-cleanup-hook /path/to/http/cleanup.sh -d secure.example.com

This will run the authenticator.sh script, attempt the validation, and then run the cleanup.sh script. Additionally certbot will pass relevant environment variables to these scripts:

User Guide — Certbot 1.15.0.dev0 documentation https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks

certbotはshell変数を読み取って認証を取る
--manual-auth-hookを指定することで認証前にスクリプトを実行して、shell変数に代入→--manual-cleanupで変数を削除
ということらしい
そもそもcertbotはワンタイムパスワードを取得して、_acme-challengeのTXTレコードにそのワンタイムパスワードを入力、それを認証局が確認して認証という手順
そのワンタイムパスワード関係をshell変数周りで解決するということ

どうもワイルドカードの場合はAPI先を変更しないといけない関係で、certbot renewだけではだめっぽい
手動で認証を取らないといけないっぽい
うーん、めんどうくさい…

MyDNSのLet’s Encrypt更新スクリプトを導入

ということで、MyDNSが公開していたLet’s Encrypt自動更新スクリプトを導入
スクリプトにPHPはちょっとなあと思っていたが、宗教的な感覚なので、重い腰を上げて導入
MyDNSのDomainInfoにこうある

3-2) Let’s Encryptのワンタイムパスワードについて

Let’s Encryptのサーバー証明書を取得する際に、ワンタイムキーをDNS情報のTXTレコードに書くこと、という説明がありますが、MyDNS.JPでは専用APIと、そのAPIを使うためのスクリプトをGitHUBで公開しています。 ですので、Linuxでご利用の場合にはこちらのスクリプトを導入されることをお勧めいたします。

自宅サーバーやVPSに使える無料のダイナミックDNS (Dynamic DNS) https://www.mydns.jp/members/#domaininfo

GitHUBにて専用APIを叩くPHPスクリプトが置かれている
ご丁寧に導入方法も書いてある
が、導入通りのwgetではなく、git cloneでとってくる
PHP8対応が挟まると更新が必要になるかもしれないしね

専用ディレクトリ(/root/cron/mydns)を作って、そこで作業
上でちょろっと書いたけど、root以外で作業させたいね

# php -v
PHP 8.0.3 (cli) (built: Mar  4 2021 13:26:46) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.3, Copyright (c) Zend Technologies
→PHP8がすでにarchのパッケージに配布されていた

# git clone https://github.com/disco-v8/DirectEdit.git
# ls
DirectEdit
# cd DirectEdit
# ls
README.md  txtdelete.php  txtedit.conf  txtregist.php
# chmod 700 *.php
# chmod 600 *.conf
# vim txtedit.conf
→mydnsのIDやパスワードを入力
→yourdomainはワイルドカード手前のサブドメインまで
→ *.meto4d.pgw.jpであればmeto4d.pgw.jp
# certbot certonly --manual \
--preferred-challenges=dns \
--manual-auth-hook /your/domain/directory/DirectEdit-master/txtregist.php \
--manual-cleanup-hook /your/domain/directory/DirectEdit-master/txtdelete.php \
-d meto4d.pgw.jp -d *.meto4d.pgw.jp \
--server https://acme-v02.api.letsencrypt.org/directory \
--agree-tos -m hogehoge@hoge \
--manual-public-ip-logging-ok

Use of --manual-public-ip-logging-ok is deprecated.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Use of --manual-public-ip-logging-ok is deprecated.
Cert not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/meto4d.pgw.jp.conf)

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the certificate (may be subject to CA rate limits)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Renewing an existing certificate for meto4d.pgw.jp and *.meto4d.pgw.jp

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp/privkey.pem
   Your certificate will expire on 2021-08-01. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - 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

前回(Let’s Encrypt でSSLワイルドカード証明書を導入する)で登録していたが、certbot certonlyでもrenew動作と同じように更新上書きしてくれる
この記事を書きながら実施する前に、テストで前回と同様のcertbot certonlyでTXTレコードを更新して、云々を実施していたので、証明書が更新済み
それでも更新するかしないかを聞かれている
Use of --manual-public-ip-logging-ok is deprecated.と言われているので、それは後で修正しよう

これでOK
あとはsystemctl reload nginxで読み込んでいる証明書を更新

Cron登録用のshellscriptを作る

上の更新をスクリプトに落とし込んでcronに登録してやる
コード表示用プラグインのせいなんだが、上はshellscriptで下はそれを実施したときのコマンド

#!/bin/bash
if test $# -eq 0 ; then
  INPUT=1
else
  if test $1 -eq 1 || test $1 -eq 2; then
    INPUT=$1
  else
    INPUT=1
  fi
fi

echo $INPUT | /usr/bin/certbot certonly --manual --preferred-challenges=dns --manual-auth-hook /root/cron/mydns/DirectEdit/txtregist.php --manual-cleanup-hook /root/cron/mydns/DirectEdit/txtdelete.php -d meto4d.pgw.jp -d *.meto4d.pgw.jp --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -m hogehoge@hoge
# chmod 700 certbot.mydns.sh
# certbot.mydns.sh 1
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Cert not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/meto4d.pgw.jp.conf)

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the certificate (may be subject to CA rate limits)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): Keeping the existing certificate

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal; no action taken.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Saving debug log to /var/log/letsencrypt/letsencrypt.log

ちゃんと動作しているみたいだ

# crontab -l
* * * * * /root/cron/mydns/DirectEdit/certbot.renew.mydns.sh 1; /usr/bin/certbot renew && /bin/systemctl reload nginx

定期更新の時間はmaskしてるせいで毎分実施されているように見えるが実際は違う
とはいえ、範囲で指定している
certbot renewは更新なくskippedでも正常終了で終わる(ということを今知った)
→systemctl reload nginxが勝手に挟まってしまう
これはなんとかしたいね
不用意にnginxが再ロードされてしまう。

まあ、これはv6.meto4d.pgw.jpが6/30に切れるらしいので、その更新を手動で行って、証明書更新があったときの文字列を見る→grepとかで探してあれば更新にしよう
cronはコメントアウトして、もう一度アラートメールを受け取るようにして今日は終了。

余談:更新するPHPの中身

DirectEdit/txtregist.php at master · disco-v8/DirectEdit · GitHub https://github.com/disco-v8/DirectEdit/blob/master/txtregist.php

単純にcertbotからやってくる可能性のある変数を配列に入れて、MyDNSへクエリを飛ばしているだけだった
PythonとかRubyとかもう少し管理しやすいスクリプトに書き換えて、そっちで管理してもいいかもね。

コメントを残す

メールアドレスが公開されることはありません。