[Let's Encrypt]9/30の中間証明書変更に伴い、iMacやiPhoneXでページが認証されなくなった事件の顛末と解決(なお根本原因は知識不足により未解決)


事件の発生

弊社の社内アプリは、自社で借りているVPS上にWebアプリとして実装している関係上SSLを利用しているため、そこの証明書にLet’s Encryptを利用しています。
とはいえLet’s Encriptにかかわるニュースを日々確認しているわけでもなく、のんびりただの社内PHPerとしてアプリ開発をしている日々に事件は起きます。

10/1
朝出勤すると総務等の社内がざわついており、社長が寄ってきて一言。
「なんか、社員のシフトを管理するアプリに入れないんだけど」

何も知らないまま地獄の開始です👼

起きていることを調べる

インターネット上で事件が起きた時は、とりあえずTwitterで検索です。
Twitterにはサーバーのプロがいっぱいいるので先人に聞くのが一番早いですからね!

というわけで、
Let's Encrypt 繋がらない
と入れて検索。

常日頃からちゃんとインターネットの情報を調べている勤勉な人は絶対に居るもので、すぐにきちんとした情報が出てきました。

2021年にLet’s Encryptのルート証明書が変更!影響や備えておくべきこととは?

この分野に詳しくはないので、専門家に指摘されたら恥で死にそうな要約ですが、
中身についてザックリ書くと以下のような感じです。

  • ルート証明書を新しいのにする。
  • 今まで使っていたルート証明書は9/30に切れるようになっている。
  • 2014年以降のOSを利用している端末なら何もしなくても大丈夫。

実際に起きていることを確認する

さてここで社長の端末を確認してみます。
iMacでした。
OSを見せてくださいとは言えませんが、どう見てもこのシルエットは2014年より後に出たハードです。私の記憶が確かなら去年くらいに買ってたような気がします。

同時期、我々システム担当部署のシフトを管理している人からも連絡が入っていました。
「手持ちのiPhoneで社内アプリに入れない」
見せてもらいました。iPhoneXでした。
どう考えても2014年より後に出ています。

このあたりでTwitterでもどうやら一部のiPhoneで問題が起きてないか?とざわついているのが見えるようになります。

「さては、これは次のOSアップデートで直るのかな?」

私は安堵して
「とりあえず今はちょっと様子見をお願いします、もしかしたらOSアップデートで治るかもしれません」
とだけ告げていつもの業務に戻りました。

一週間経過

「治ってません」
iOS15に上げた担当者から告げられます。
ついでに社長にも同じことを言われます。
Twitterでは完全にLet's Encryptの件は解決済みという雰囲気で、問題が起きているWebページは私の観測範囲では弊社の社内アプリのみ。
「これはウチのサーバーの問題なのでは?」
やっと自分のサーバーの問題なのではと気が付いて動き始めました。

さて、サーバーの状態は

弊社では複数のVPSを契約していますが、今回の問題を語るにあたりサーバーA,サーバーB,サーバーCの3つを持っているものとして語らさせてもらいます。

各サーバーは以下のような状態になっています

サーバーA
CentOS6
一番不慣れな時期に説明ページとにらめっこしながら立てたサーバー。ちょっとしたWebアプリが動いている。

サーバーB
CentOS6
そこそこ慣れた時期に立てたサーバー。今回のアクセスできないといわれているWebアプリが動いている。ほぼ毎日使う。

サーバーC
Ubuntu21
つい最近に立てたばかりのサーバー。たまに使う重要なWebアプリが動いている。

一週間経過時点で、サーバーA、サーバーB、サーバーCすべてのサーバーで認証エラーが出る状態でした。

で、何が原因なんだろうか

ルートCA期限切れの件について調べていたところ、以下のページにたどり着きました。

Let's EncryptのルートCA期限切れで OpenSSL 1.0.2が思わぬ事故を起こす件

こちらによるとやるべきことは以下の3つです

  1. クライアント側でOpenSSLのバージョンを上げる
  2. クライアント側で DST Root CA X3 を信頼済みCA一覧から削除する
  3. サーバ側で死者の書いた証明書を排除する

こちらのアクセスできないといわれているWebアプリに入っているOSはCentOS6。
こちらは2020年にはもう完全に開発も停止したもの。opensslのバージョンは1.0.1。
かといって新しいopensslを入れるのは私の技術と今現在動いているサーバーということを加味して難しい……。

とりあえず、サーバーがそもそもLet’s Encryptのルート証明書を理解できていないのでは?とあたりをつけて、
3番目の「サーバー側で死者の書いた証明書を排除する」を行ってみました。

こちらのページの4.3を参考に
LetsEncryptのROOT証明書の期限が切れたら古いOSからアクセスできなくなって困った

※yumが動くように事前にライブラリの調整は行っています。

$ su -

# yum update ca-certificates

# update-ca-trust enable
# update-ca-trust

# perl -e 'while(<>){last if $_ =~ m/DST Root CA X3/;}print $_;while(<>){last if length($_)==1;print $_}' </etc/pki/tls/certs/ca-bundle.crt > /etc/pki/ca-trust/source/blacklist/DST_Root_CA_X3.pem

# update-ca-trust extract

# grep "DST Root CA X3" /etc/pki/tls/certs/ca-bundle.crt
>
# grep "ISRG Root X1" /etc/pki/tls/certs/ca-bundle.crt
> # ISRG Root X1

どうやらうまくいったようです!
(いろいろとぶっ壊す恐れがあるので、それぞれのコマンドについてはきちんとリンク先で説明を読んでから行ってください)

サーバーの状態を確認

サーバーの状態は以下のようになりました。

サーバーA
問題なくアクセス可能。

サーバーB
認証されていないと出る

サーバーC
認証されていないと出る
(なおサーバーCはOSがUbuntu20なのでそもそもDST Root CA X3を消す処理は行っておりません。opensslが新しいバージョンのものであることを目視確認済みです)

少なくともサーバーAとサーバーBの状態が異なるということに違和感を覚えます。

同じような認証エラーはApacheの設定でも出ていなかったか?

ふと、大量に検索を行った中で、この記事が目に留まります
SSL証明書の更新作業でドハマりした話
ものすごく前の記事ではありますが、そもそも一般的に「認証されていない」と出るとき、それはApacheのSSL設定を失敗しているときです。
9/30までは問題なく動いていたとはいえ、問題が発生したときはとりあえず一番近いところからチェックしていくのが基本。
というわけでApacheの設定を確認します

サーバーA

httpd.conf
...

SSLCertificateFile /etc/letsencrypt/live/domain_name/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain_name/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain_name/chain.pem

...

サーバーB、サーバーC

httpd.conf
...

SSLCertificateFile /etc/letsencrypt/live/domain_name/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain_name/privkey.pem

...

もしかしてfullchain.pemがおかしくなっている…???

そして解決

すべてのsslの設定をサーバーAの方式にそろえたところ、弊社内にあるすべての媒体で問題なくアクセスに成功しました。
社長と担当者に頭を下げてこれにて解決です!

……で、なんで9/30以降急にfullchainが使えなくなったのでしょうか?

有識者からのコメントを募集しておりますorz