前回(Let’s Encrypt でSSLワイルドカード証明書を導入する)の続き?
MyDNSが公開しているPHPのscriptを導入して、renewが行えるようにした。
背景
もともとLet’s Encryptでワイルドカード証明書を導入する前はcertbot renew
をcronに登録していて放置していた。
そしてDNSのときのと同じくこちらも無料でアラートメールをもらって気づいた
前回(Let’s Encrypt でSSLワイルドカード証明書を導入する)重い腰を上げて導入したワイルドカード証明書関係が更新できていないようだ
そのあたりを調査して、MyDNSの自動更新スクリプトを導入した。というお話
ちなみにアラートメールはこんな感じ
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
User Guide — Certbot 1.15.0.dev0 documentation https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooksauthenticator.sh
script, attempt the validation, and then run thecleanup.sh
script. Additionally certbot will pass relevant environment variables to these scripts:
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のワンタイムパスワードについて
自宅サーバーやVPSに使える無料のダイナミックDNS (Dynamic DNS) https://www.mydns.jp/members/#domaininfo
Let’s Encryptのサーバー証明書を取得する際に、ワンタイムキーをDNS情報のTXTレコードに書くこと、という説明がありますが、MyDNS.JPでは専用APIと、そのAPIを使うためのスクリプトをGitHUBで公開しています。 ですので、Linuxでご利用の場合にはこちらのスクリプトを導入されることをお勧めいたします。
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とかもう少し管理しやすいスクリプトに書き換えて、そっちで管理してもいいかもね。