ページコンテンツ
Let’s Encryptで作ったSSLサーバ証明書にて問題発生
以下の投稿で、Let’s Encryptを導入してみたことを書いた。
導入後も特に問題は見受けられず、運用していたのだが、ふとmacbook airのchromeでサイトを見たところ、証明書エラーが出ていた。
証明書を確認すると、ルート証明書と中間証明書の期限が2021年9月30日となっており、期限切れでエラーとのこと。ルート証明書は「DST Root CA X3」となっていた。
でも、通常使っているwin10であれば、chromeでもfirefoxでも問題なく閲覧できている。そして、ルート証明書を確認すると、「ISRG Root X1」となっていた。
端末依存かな?と思ってルート証明書について調べてみると、どうやらLet’s Encrypt界隈ではすごく有名な話題とのこと。
いろいろ書いてるけど、原因and解決は以下。
https://it.ama2pro.net/2021/10/18/lets-encrypt%e3%81%ae%e3%83%ab%e3%83%bc%e3%83%88%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%a8%e3%83%a9%e3%83%bc%e5%af%be%e5%bf%9c/#i-3
勝手に証明書の更新をしてくれる仕組みなのに、なぜ期限が切れたの?
バグなの?
上記のページの内容そのままではないが、内容を理解するためにはSSLサーバ証明書の基本的な話を理解していないといけない。
SSLサーバ証明書を使っているサイトが「ちゃんとした証明書を使っている」と判断するために、「信頼する証明書のリスト」をクライアント側が持っており、そのリストに入っているかどうかで「問題ない」と判断される。
もちろん、サイトごとに証明書は異なるので、世にあるSSLサーバ証明書がすべてそのリストに入っているかというとそうではない。
信頼された拠点(認証局)にて、ルート証明書を持っており、そのルート証明書がリストに入っている。そのリストは、winだったりmacだったりiphoneだったりandroidだったりで持っている。
で、各サイトのSSLサーバ証明書を作るときに、認証局のルート証明書を使って作ることで、SSLサーバ証明書に認証局のお墨付きをもらい、それによって「このSSLサーバ証明書に紐づくルート証明書はリストに入っているので、このSSLサーバ証明書はOK」として、エラーなく表示するようになる。
(さらに暗号化処理などあるけど、いったん今回とは関係ないので省略)
新しく立ち上がった認証局が「私のルート証明書をリストに入れてください」と言っても、素性もわからないし、どこもリストに入れないわけです。
どの端末のリストにも入っていないのであれば、誰も使わないので、何とかしてリストに入れてもらう必要があります。ただ、それだと時間がかかるので、すでにリストに入っていた「 DST Root CA X3 」をルート証明書として使わせてもらうことで、利用できるようにしたみたい。
(「DST Root CA X3」はIdenTrustというところのルート証明書らしいが、そこにお願いして使えるようにしたのだろう)
よって、Let’s EncryptでSSLサーバ証明書を作ると、ルート証明書として 「 DST Root CA X3 」 と自分とこの「ISRG Root X1」を持つようになった。
ルート証明書というか中間証明書なのかも。「CA」って言っているし。
時は流れ、 「ISRG Root X1」 はいろんな端末で信頼されるリストに入ってきた。ただしまだ完全に広まり切ったというわけではないらしい。ただ、ここにきて 「DST Root CA X3はもう終了」ということになったらしい。
なので、今後は 「ISRG Root X1」 をルート証明書として参照すればいいらしい。
環境依存とのことだが、どうやら自分の端末は問題のバージョンではないらしい
この問題についてwebの情報を見ると、
いくつかの環境でまだ「ISRG Root X1」がないものがあるとのこと。よく言われるのがAndroid7.0以前の端末。たしかにこれはまだまだ多いかも。
ということが言われていた。今回はmacだが、OS X El Capitan(10.11)以前のバージョンは出るとのこと。
でも、自分のはそれより全然新しい。
さらに、証明書のリストを見ると「 ISRG Root X1 」が入っており、期限も2035年となっている。
(key chainにて「システムルート」の「証明書」を選択して、メニューの「表示」から「有効期限の切れた証明書を表示」とすると、今回問題になっている「 DST Root CA X3 」もあるのですがね)
なんで表示エラーになる?
いや、表示エラーにあることもあるだろう。でもなんでfirefoxは大丈夫なの?
firefoxではエラーにならなかった
chromeとsafariではエラーになった。証明書を確認すると、ルート証明書がどちらも 「 DST Root CA X3 」となっていた。
じゃあ、なぜfirefoxは大丈夫なのかということだが、どうやら、firefoxは独自の信頼できる証明書リストを持っており、それを使っているからなのかもという推測ができた。
じゃあ、macで持っている信頼できる証明書リストがおかしいの?
なんかそれも納得いかない。
Let’s Encryptを使っているほかのサイトを確認したところ。。。
いろいろ仕事をしている中で、hetemlで運用しているサイトがあるのだが、そこでは無料SSLを使っており、それはLet’s Encryptを使っていることを知っていた。
「そのサイトはどうなるかな?」とmacのchromeで見てみたところ、なんの問題もなかった。
ここで、問題が発生していれば、「端末依存だ。端末がおかしいので、古いサーバ証明書を削除するか何かしよう」と思えたのだが、Let’s Encryptを使っているサイトが問題なく見れるということは、自分のサーバに問題があると思われた。
ちゃんとサーバでの(どこかわからんけど)設定をしていれば、問題は起こらないはず。
Let’s Encrypt自体の設定に問題は見受けられない。。。
とはいえ、つい先日設置して、まだ新品ピカピカな状態。
「更新がうまくいっておらずルート証明書が古い」とか、考えられない。
かつ、設定と言っても、ほぼcertbotに依存している状況。間違えそうなところが思い浮かばない。
そこで、いろいろ調べてみたところ、以下の問題があることが分かった。
openssl 1.0.2系を使っていると、問題があるらしい。
1.1.0とかでは問題ないらしいが、1.0.2系では 「 DST Root CA X3 」 と 「ISRG Root X1」 の2つをルートに入れている場合、信頼できるほうを使って処理すればいいものをわざわざ 「 DST Root CA X3 」 を使って処理しようとしてしまうらしい。
で、いろいろ調べてみたところ、 「 DST Root CA X3 」 と 「ISRG Root X1」 の2つがchainに入っているので、 「 DST Root CA X3 」 を削除すればいいみたいなことがあった。
サーバ上の証明書を見ると、chain.pemみたいなのがあり、その中を見ると確かに2つの証明書があった。
-rw-r--r-- 1 root root 692 9月 24 17:20 README
lrwxrwxrwx 1 root root 38 9月 24 17:20 cert.pem -> ../../archive/it.ama2pro.net/cert1.pem
lrwxrwxrwx 1 root root 39 9月 24 17:20 chain.pem -> ../../archive/it.ama2pro.net/chain1.pem
lrwxrwxrwx 1 root root 43 9月 24 17:20 fullchain.pem -> ../../archive/it.ama2pro.net/fullchain1.pem
lrwxrwxrwx 1 root root 41 9月 24 17:20 privkey.pem -> ../../archive/it.ama2pro.net/privkey1.pem
2つの証明書をそれぞれ別のファイルにして以下のコマンドで見てみると、確かに 「 DST Root CA X3 」 と 「ISRG Root X1」 だった。
上の方
Issuer: C=US, O=Internet Security Research Group, CN=ISRG Root X1
下の方
Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
この下の方を削除すればいいのかと思い、
・下を削除して保存
・apacheリロード
をやってみたが、変わらなかった。
なんかopenssl公式が出している以下の記事を見ると、なんか全部openssl clientでの対策となっている。
もしかして、「クライアントとしてopenssl1.0.2を使う場合の注意点なのか?じゃあ、関係ないかも。」と思った。
(実はあとあと考えると、今回の作業はまったくもって意味ないことをしているのだが。。。)
ただ、openssl1.0.2問題はいろんなところに出るので、openssl1.1.0とかを入れたほうがいいのかなぁ。と思った。
CentOS7にopenssl1.1.1を入れてみる。
「yumでは入らないので、ソースから入れるしかないがやめといたほうがいい」という情報をよく見る。
でも、なんかあるんじゃないかなぁと思って探したら、やっぱりあった、と小躍り。
(詳細は「CentOS7 openssl1.1.1」とかで検索してみて)
ただ、結論としてやっぱり難しそう。
・ソースをダウンロードしてコンパイルするところまでは手順通りで問題なさそう。でもそれを普通に使える(apacheと連携させたり、cuiで使ったり)ようにするには、もっと知識が必要。ちなみに、古いopensslを削除しようとすると、DB serverまで、依存関係故に削除しようとされて慌てて止めた。
・openssl1.1.1をインストールした後、その環境をベースとしてapacheをソースからインストールする方法が紹介されていた。今後、どこでクリティカルな脆弱性が出るかわからないので、apacheまでyumの管理を外すのはちょっと難しい。。。
・そもそもmod_sslも更新が必要なのでは?その辺について言及された記事は見当たらなかった。
・「package管理までちゃんとやる、これ一つでopenssl1.1.1をインストールできるよ」的なスクリプトを公開しているサイトがあったが、そのスクリプトについてすべて理解しないと使うのは怖いと思った。どこでどんな難しい設定をしているかわからないので、何かあったときに、それで環境が壊れてリカバリできない状況になった日には。。。(過去に無理やりopensslを入れて環境がどうしようもなくなったことがあるので。依存関係無視してのインストールは危険。)
コンパイルまでしたが、これから先は悩ましい。。。と思った。
基本に立ち返った(証明書の設置)ところ、解決。
そもそも、やっていることはLet’s Encryptでもらった証明書をapacheで読み込んでいるだけのはず。読み込んでいるのは証明書、鍵、CAだけのはず。
その中に古いのがあったら、外してみよう。
と思った。
そこで、Certbotで作った証明書、鍵の設定方法をwebで見たところ、以前とは違うサイトで、apacheのconfigに「証明書」「鍵」「CA」を指定しているのを見つけた。
「あれ?」と思った。
「Let’s Encryptを導入した時は、「証明書」「鍵」だけ指定したはず。なんでCAもしていしているんだ?」と。
サーバに証明書を設置する作業は実は百以上経験している。
apacheでは「証明書」「鍵」「CA」 の3つのファイルを指定するのだが、nginxでは「証明書とCAをがっちゃん越したファイル」「鍵」の2つを指定するので、「apacheでもこういうことするんだー。Let’s Encryptはそうなんだー。」と思っていたが、どうやらそうじゃないらしい。
certbotを使って、証明書を生成すると、上にも記載したが、以下の4つのファイルが生成される。
・証明書ファイル
・鍵ファイル
・chainファイル
・fullchainファイル
今までapacheで設置してきたケースだと、「 証明書ファイル 」「 鍵ファイル 」「 chainファイル 」を使うことになるだろう。ちょっとこれでやってみようと思った。
で、やってみたところ、エラーが出なくなった!
やっと解決、ここまで(ぶっとうしで作業し続けていたわけではないが、およそ30時間ぐらい。。。)
その後
apacheでちゃんとCAを指定することで問題なくなったということ。
ただ、 「 証明書ファイル 」+「 chainファイル 」 と「fullchainファイル」の中身を比べたところ、違いはなさそう。
中身一緒なんだから処理的には変わらないのでは?と思ったが、「SSLCertificateChainFile」をちゃんと指定してやることが重要なんだと思う。
win10のchromeやfirefoxでは「そういう風に設定しているけど、要は証明書がここで、こっちの部分はCAでしょ?」と認識して処理してくれるが、macのchromeやsafariはその辺を厳格に確認しているのかも?よくわからん。
(そもそも同じchromeが端末によりその辺の挙動を変えるとも思えない)
ちなみに、上では「 it.ama2pro.net 」のchain.pemにて、 「 DST Root CA X3 」 の部分を削除した。
「 apa2pro.net 」側も同じように 「 証明書ファイル 」「 鍵ファイル 」「 chainファイル 」 を指定するように修正したのだが、こちらの 「 chainファイル 」 には 「 DST Root CA X3 」 の情報がまだ入っている。
もしかしたらopenssl1.0.2系の問題である「古い方を参照しちゃう」という問題が起こるかなと思ったが、特にama2pro.net側も閲覧上問題なかった。
やっぱりclientとしての挙動なのかなぁ。。。でもこの問題について「サーバ運用上、openssl1.0.2はもう終了かも」という情報はよく目にする。
Centos8はopenssl1.1.1をパッケージ管理ソフト(CentOS7以前でいうyum)で普通にインストールできるけど、今年の年末でサポート切れるし、CeontOS7はもうしばらく続くし。。。
web上でもubuntuの情報よく見るけど、そっちにシフトするべきなんかなぁ。。。
あと、関係ないけど、「http」でのアクセスだと各ブラウザで「安全じゃないです」みたいな表示を出すようになった。
なので、http→httpsのリダイレクトをapacheのconfigに設定した。
<VirtualHost *:80>
ServerName it.ama2pro.net:80
RewriteEngine On
RewriteRule ^/(.*) https://it.ama2pro.net/
</VirtualHost>