opensslコマンドでの証明書の有効期限の確認方法・オプション解説
目次
こんにちは。株式会社ビヨンド システムソリューション部所属のなかです。
皆さんが閲覧しているこのビヨンドブログはHTTPS化をしております。
この十数年でHTTPS化はかなり浸透し、HTTPのサイトは随分と減りましたよね。
HTTPS化に必要となる「SSL証明書」は現時点では1年で更新するのが一般的なため、定期的な更新作業が必要になりますが、
その際にSSL証明書の有効期間を確認する方法として、ブラウザを使って確認する方も多いかと思います。
ただ「ブラウザは不確定だからコマンドで確認したい」という方や「開発中のため外部にポートを開けていないのでブラウザで確認できない」
といった理由でコマンドで調べる方も当然いらっしゃるかと思いますが、たまにしか使わないコマンドを検索するととある問題が発生します。
「人によってコマンドの使い方やオプションが微妙に違っているけど、どう違うの?」
「manを叩いてもオプション量が多くてよくわからない」
そんな方に向けて、SSL証明書を確認する時のopensslコマンドでよく使うオプションの意味や使い方も合わせてご説明したいと思います。
実行環境
・OS:AlmaLinux8(WSL2環境)
・Shell:bash
・OpenSSL:OpenSSL 1.1.1k FIPS 25 Mar 2021
opensslコマンドを使って「ローカル」or「リモート」で確認する
そもそもopensslコマンドとはOpenSSL プロジェクトが開発・公開しているコマンドで、主流のLinuxディストリビューションでは大抵デフォルトで扱えるコマンドです。
このコマンドは非常に出来ることが多いのですが、今回はSSL証明書の有効期限確認に用います。
また、このコマンドを使って確認する場合にも「ローカルでSSL証明書を確認する」方法と「外部からリモートでSSL証明書を確認する」方法に分かれています。
まずは前者のローカルからご説明します。
ローカル環境
ローカル環境で確認する際に、筆者がよく使うコマンドはこちらです。
opensslコマンドを使ってローカルに保存されている証明書を読み込んで、コモンネームと有効開始日・有効期限日を表示させています。
$ openssl x509 -noout -subject -dates -in /etc/pki/tls/certs/example.crt
※出力サンプル subject=CN = exmaple.com ※コモンネーム(≒ドメイン名) notBefore=Mar 31 04:42:17 2022 GMT ※有効開始日 notAfter=May 2 04:42:16 2023 GMT ※有効期限日
x509
SSL証明書を扱う時は「openssl」コマンドに「x509」というサブコマンドを使用します。
※「X.509」とは公開鍵証明書の標準フォーマットの名前なので関連付けておくと覚えやすいかもしれません。
-in
ローカル環境で実行する場合は読み込む証明書の名前を指定する必要があるので、このオプションを用います。
-subject
読み込んだ証明書から、subjectフィールド(コモンネームが記載されている場所)を出力するオプションです。
-dates
読み込んだ証明書から、有効開始日と有効期限日を出力するオプションです。
-noout
「他のオプションで指定した情報以外は出力しないようにする」オプションです。
仮にこのオプションがない場合、下記のようなコマンドによって読み込まれた復号前の証明書も一緒に表示されます。
-----BEGIN CERTIFICATE----- MIIGMjCCBRqgAwIBAgIMMGPvI3CXFUjGngZcMA0GCSqGSIb3DQEBCwUAMEwxCzAJ BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSIwIAYDVQQDExlB ~以下数十行省略~ -----END CERTIFICATE-----
余談ですが、証明書の内容を表示しない事に限定した -nocert オプションというのもあります。
リモート環境
リモートで確認する際に、筆者がよく使うコマンドはこちらです。
openssl s_client コマンドを使って対象ホストにアクセスし、そこから証明書を読み込んでコモンネームと有効開始日・有効期限日を表示させています。
$openssl s_client -connect beyondjapan.com:443 < /dev/null 2> /dev/null | openssl x509 -noout -subject -dates
※実際の出力 subject=CN = beyondjapan.com notBefore=Mar 31 04:42:17 2022 GMT notAfter=May 2 04:42:16 2023 GMT
s_client
SSL/TLSで通信をする際に必要なクライアント機能を提供するサブコマンドを使用します。
-connect host:port
ローカルで -in を使用してファイルを指定したように、リモート用(接続先のhostとポートを指定する)オプションです。
※今回は443(HTTPS)を使用していますが、SMTPなどのポートを指定してSSL/TLSの接続確認に使用する使い方もあります。
< /dev/null
「openssl s_client」コマンドは指定先に接続を行ってから「入力待ち状態」になりますので、無(/dev/null)を標準入力に入れて入力待ちを終わらせています。
これを使用しない場合、ctrl+c でコマンドを終了させる手間がかかるので使用しています。
※これはオプションではなくShell(本環境ではbash)の標準入力に関する指定です。
2> /dev/null
こちらはLinuxにおける標準エラー出力(2)を無(/dev/null)に出力して捨てて、Shell上に表示させなくしています。
前段の < /dev/null を使った場合、不要なError文が出るのでそれを消すための処置です。
※これはオプションではなくShell(本環境ではbash)の標準出力に関する指定です。
| openssl x509 -noout -subject -dates
「|」(パイプ)を使い、通信で受け取ったSSL証明書の中身を読み込むコマンドに渡します。
パイプ後のコマンドはローカルの時とほぼ同じですが、証明書はパイプで受けとっているので読み込む証明書を指定する -in オプションは使用しません。
※ -in オプションがない場合は、標準入力に渡された内容を処理するのがこのコマンド(x509)の仕様です。
他の人が使ってるコマンドやオプション
コマンド
echo | openssl s_client -connect ~
リモート環境で確認する際、筆者は < /dev/null を使用して、入力待ちを終了させましたが、
これはechoを使うことでShell上に標準出力させる命令が優先され、強制的に入力待ちの状態に終わらせているのだと思われます。
意図としては < /dev/null と同じです。
~ | openssl x509 -text | grep "Not"
-text オプションで証明書の内容を全て解号してテキストで出力します。
他のオプションで個別に指定し表示させていた内容も含む全てなので、中身を全て確認したい場合に使う物です。
その出力内容をパイプで grep に渡して"Not"が入った行を出力させています。
$ openssl s_client -connect beyondjapan.com:443 < /dev/null 2> /dev/null | openssl x509 -text | grep "Not" Not Before: Mar 31 04:42:17 2022 GMT Not After : May 2 04:42:16 2023 GMT
このように有効開始日と有効期限日の行を出力します。
コマンドが長いですがシンプルではあるので「わかってる人」にとっては理解しやすいコマンドだと思います。
ただ、専用のオプションがあるのにgrepに頼ることでオプションのことをあまり調べなくなり、
opensslコマンドに対する理解が進まないままになってしまう気がしたため筆者は最初に提示したコマンドを使うようにしています。
それに、ドメイン名(コモンネーム)の出力もしようとすると正規表現オプションを使う関係上コマンドの判読性が落ちてしまうのが悩みどころです。
オプション
-enddate
読み込んだ証明書から、有効期限日だけを表示するオプションです。
また、同様に有効開始日を表示する -startdate というオプションもあるのですが、
この両方のオプションを同時に適用したことになるのが -dates オプションのため、特に拘りがないなら -dates で良いかと考えています。
-text
上記でも説明しましたが、証明書をテキスト形式で表示するオプションです。
出力される内容は、公開鍵・署名アルゴリズム、発行者・subject name・有効期限等々すべての設定情報が含まれています。
-noout を使用しないパターン
この場合、コマンドによってリクエストされている復号されていない証明書がそのまま表示された後、オプションで指定した有効期限日などが表示されます。
正直復号化されていない証明書の内容は見ないので、つけていた方が見やすいです。
コマンドの出力結果に「CERTIFICATE」という文字が出るため、「証明書を確認している」事がハッキリとわかるのでそこがメリットかもしれません。
< /dev/null 2> /dev/null がないパターン
ctrl + c でコマンドを終了する前提の物で、手動入力のしやすさとパッと見たときの判読性が高いように思えるのでそちらを優先した意図の物だと思います。
この辺りは好みなような気がしますが、ついコマンドを終了しないまま次のコマンド打ってしまって出力やログが汚れてしまう……
といった事があるため筆者は入れるパターンが好きです。
最後に
opensslコマンドも出来ることが多い上に、オプションの量も多いため非常にややこしいと本記事を書いていて改めて思います。
これでもできることの一部分にすぎないですし、大本の技術である暗号化・認証方式の分野自体が非常にロジカルで奥深いです。
この記事を読んで、少しでもopensslコマンドへの抵抗感や疑問が解消されれば幸いです!
ここまで読んで頂き、ありがとうございました。
次回記事
「有効期限」と合わせて確認する事が多い、
「整合性・検証結果」の確認方法は下記でご説明しております。
opensslコマンドでの証明書の整合性と検証結果の確認方法・オプション解説
参考資料
OpenSSL公式 のopenssl-x509に関するマニュアルページ
https://www.openssl.org/docs/manmaster/man1/openssl-x509.html
OpenSSL (ArchWiki)
https://wiki.archlinux.jp/index.php/OpenSSL