Let’s Encrypt + getssl で証明書更新エラー

2つの罠

未だに古いOSで動作させているサーバは多いと思います。CentOS6 とか。特に不具合は無いし、httpsを待ち受けしているだけだから…みたいな感じでしぶしぶ動かしている的な。

で、この対象のなるサーバでもご多分に漏れずそういう運用の仕方をしていた訳です。費用も掛けられないので、Let’s Encrypt + getssl を cron でぶん回して自動更新、これで手間いらず! とかね。

そうしたら、麗らかな曇り空の日曜日。トラブルを告げる電話が来た訳です。

「サーバに接続できません。何か証明書の期限が何たらで…」

と。

おかしい。このサーバは証明書の自動更新が掛かるはずだ! なぜ???

ひとつ目の罠 getssl が壊れていた。

更新プログラムは getssl なので、それを叩いてみました。
反応無し…これはスクリプトのはずなので、中身を見てみました。すると…

400: Invalid request

何、これ。意味わかんない。これじゃ動作する訳もありません。
同じディレクトリには、getssl.v2.43 という残骸も残っていました。getssl 自体のスクリプトを読むと、自身を更新する機能も持っているようです。仕方がないので、公式サイトに行ってみました。

GitHub – srvrco/getssl: obtain free SSL certificates from letsencrypt ACME server Suitable for automating the process on remote servers.

> Upgrade broken in v2.43

いやいや、broken じゃねーよ。無料で使わせて頂いてもらってるけれど、broken はやめてください。いやほんと。
という訳で新しいスクリプトをダウンロードします。

# curl --silent --user-agent getssl/manual https://raw.githubusercontent.com/srvrco/getssl/latest/getssl --output getssl | chmod 700 ./getssl

これで新しいスクリプトがダウンロードできました。
これを今までのファイルと置き換えて…更新っと。

# /**your server path**/getssl -u -a -q
getssl: ERROR curl "https://acme-v02.api.letsencrypt.org" failed with 60 and returned:

curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

はぁぁぁああああ????
今度は root 証明書エラー…?!

ふたつ目の罠 root 証明書の更新が必要

色々と調べてみました。エラー内容を見ると

curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

とあります。とりあえず読みにいきましたが、よー判りません。ググって見ると、どうやら root 証明書が古いと出るらしいです。 CentOS6 も既に古いOSなので、仕方ないですよね…という訳で対応します。

$ wget --no-check-certificate https://curl.se/ca/cacert.pem

--2021-10-31 12:14:53--  https://curl.se/ca/cacert.pem
curl.se をDNSに問いあわせています... 151.101.66.49, 151.101.2.49, 151.101.130.49, ...
curl.se|151.101.66.49|:443 に接続しています... 接続しました。
警告: 証明書に記載されている名前 `c.sni-561-default.ssl.fastly.net' とホスト名 `curl.se' が一致しません
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 208065 (203K) [application/x-pem-file]
`cacert.pem' に保存中

100%[================================================================================================================>] 208,065     --.-K/s 時間 0.008s

2021-10-31 12:14:53 (23.5 MB/s) - `cacert.pem' へ保存完了 [208065/208065]

ダウンロードできました。
そうしたら、既存の root 証明書をバックアップして、新しいファイルをコピーします。

注) CentOS6の場合。他OSは場所が違うので locate してね。

$ su -
# mv /etc/pki/tls/certs/ca-bundle.crt /etc/pki/tls/certs/ca-bundle.crt_bk
# cp -p ./cacert.pem /etc/pki/tls/certs/ca-bundle.crt

更新完了。とりあえず通信テストします。

# curl -I https://www.google.com/

HTTP/1.1 200 OK
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Date: Sun, 31 Oct 2021 03:17:06 GMT
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Expires: Sun, 31 Oct 2021 03:17:06 GMT
Cache-Control: private
Set-Cookie: 1P_JAR=2021-10-31-03; expires=Tue, 30-Nov-2021 03:17:06 GMT; path=/; domain=.google.com; Secure
Set-Cookie: NID=511=ojP4TH76yudGt4E4K8e_AwJCNuKHjQ5DnAxcAJ-4Ut9hSjPqACxON20n9KWxSS_CVSiUvlUqs9pWsVBbKRu816Zh3HUzqTCJ-w2lCB4Ky4Vz-deVtPijYDXD3mPariqQh674ULXGP1YWTvn0B1rxSn7nXhxnAPN4ie2fvGSFMj0; expires=Mon, 02-May-2022 03:17:06 GMT; path=/; domain=.google.com; HttpOnly
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

通信できました。これで getssl が動作します。

SSL更新。

# /** your server path **/getssl -u -a -q
getssl: **************.jp - rsa certificate obtained but certificate on server is different from the new certificate

お、ちゃんと更新してきたようですね。
getssl のセットアップ方法はそれこそググれば死ぬほど出てくるので、そちらをどうぞ。

# less ssl-renew.sh

rsync -auv /root/.getssl/*************.jp /etc/pki/tls/certs/
sleep 1
/etc/rc.d/init.d/httpd stop
sleep 1
/etc/rc.d/init.d/httpd start

自分はこんなスクリプトを書いて月1で回しています。/etc/pki/tls/certs/ 以下にコピーして httpd を自動で再起動するだけですが、今のところトラブルはありません。( getssl も同様に cron で月1更新するようにしています)

当然、この URL に対しては外部から監視をしているので、再起動のタイミングでエラーメールが飛んできますが、直ぐに復帰するので問題無いという判断です。どうせ一瞬ですしね。

「Let’s Encrypt + getssl で証明書更新エラー」への2件のフィードバック

  1. 本日、こちらのエラーが出て焦ってぐぐったらこちらのサイトが見つかりました
    修正内容もこちらの環境とバッチリ合っていたので即座に適用できて対応できました
    大感謝です!ありがとうございます!
    (2021/11/02 火曜日 0:33:20 のコメントは削除してくださるようお願いいたします)

  2. ヨシダ様
    ご依頼頂いた通り、投稿は削除致しました。

    この手のエラーって本当に焦りますよね。
    少しでも色々な人達の助けになれば幸いです。無事に解消して何よりでした!

コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください