連載
» 2018年05月09日 05時00分 公開

Tech TIPS:OpenSSLでSSLサーバ証明書の有効期間を自動的に確認して更新漏れを防ぐ

運用・管理担当者にとって面倒なSSLサーバ証明書の更新。有効期間内に正しく更新できるように、OpenSSLを使って自動的かつ定期的にサーバの証明書を実際に調べて、期限切れが近づいているかどうか網羅的に確認する方法を紹介する。

[島田広道,デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

対象:Windows OS、OpenSSL


 Webサイト運用担当者や社内システム管理者にとって、SSLサーバ証明書の更新はやっかいな仕事の1つに挙げられるだろう。証明書の更新は手動作業が多く、手間がかかる。その一方で有効期間内に更新を忘れると、そのサーバにアクセスしたクライアントでエラーが生じるため、ユーザーに迷惑をかけることにもなるからだ。

 証明書の枚数が少なければ、期限が切れる日をオンラインのカレンダーに登録し、事前に通知させるといった対策も有効だろう。しかし数十枚、数百枚となると、これを手動で管理するのは手間がかかるし、間違える恐れもあり現実的ではない。

 それよりは、サーバに設定されているSSLサーバ証明書を読み出し、有効期間があとどれくらいで終わるのか、定期的かつ自動的にチェックした方が手間なく確実だ。本TIPSではその方法の一例を紹介したい。

 前提として、証明書を取り扱うコマンドにはデファクトスタンダードである「OpenSSL」を利用する。またその実行プラットフォームはWindows OSとする。以下では、Windows 10バージョン1709とOpenSSL Ver.1.1.0hの組み合わせで動作を確認している。

【準備】WindowsにOpenSSLをインストールする

 まず、証明書のチェックを実行するWindows PCにOpenSSLをインストールする。Windowsの場合は、TIPS「WindowsにOpenSSLをインストールして証明書を取り扱う(基本編)」の手順でインストールしていただきたい。インストーラは、開発者向けのファイルを含まないLight版で十分だ。

 インストールしたら、Windows OSの実行パスに「<インストール先フォルダ>\bin」を加えておく。その後、コマンドプロンプトでフルパスを指定することなくopensslコマンドが実行できることを確認する。

C:\>openssl version
OpenSSL 1.1.0h  27 Mar 2018



 「version」オプションを指定して実行すると、上記のようにOpenSSLのバージョンが表示されるはずだ。

証明書の有効期間の確認に利用するOpenSSLの2つのサブコマンド

 OpenSSLを使ってSSLサーバ証明書の有効期間を確認するには、作業を次の2つに分類して実施する。

  1. 監視対象のサーバに設定されているSSLサーバ証明書を取得(ダウンロード)する
  2. 取得した証明書から有効期間を抽出する

 「1.」にはOpenSSLのサブコマンド「s_client」を、「2.」には「x509」を用いる。これらのサブコマンドの使い方を以下で解説していく。

サーバに登録されているSSLサーバ証明書を取得する

 リモートサーバからSSLサーバ証明書を取得するには、次のように「s_client」サブコマンドを実行する。

openssl s_client -connect <サーバの名前またはIPアドレス>:<ポート番号> < nul > <保存先ファイル名>



 <サーバの名前またはIPアドレス>には、次の例のように、監視対象のSSL/TLS対応サーバに到達できる(名前解決が可能な)ホスト名か、IPアドレスを指定する。

  • FQDNで指定: -connect www.example.jp:443
  • Windows OSのコンピュータ名で指定: -connect WINSVR01:443
  • IPv4アドレスで指定: -connect 203.0.113.111:443
  • IPv6アドレスで指定: -connect [2001:db8::111]:443

 <サーバの名前またはIPアドレス>は、対象のSSLサーバ証明書の共通名(Common Name、CN)あるいは別名(Subject Alternative Names、SAN)のいずれかと合致していなくてもよい。

 また<ポート番号>には、次の例のように、対象サーバがSSL/TLSをリッスンしているポートの番号を指定する。

  • 一般的なHTTPSサーバ: -connect www.example.jp:443
  • リモートデスクトップセッションホスト: -connect www.example.jp:3389
  • SMTP over SSL/TLSのサーバ: -connect www.example.jp:465

 標準入力をnulにリダイレクトしているのは、SSL/TLSのセッションを自動的に閉じるためだ。s_clientサブコマンドは、サーバに接続してSSL/TLSのセッションを開いた後、コマンド入力待ちの状態になる。SSLサーバ証明書を取得するだけならコマンド入力は不要なので、セッションはすぐ閉じてよい。

 正しくSSLサーバ証明書が取得できると、標準出力に出力されるので、リダイレクト先として<保存先ファイル名>を指定して保存する。これは後ほどx509サブコマンドで入力ファイルとして利用する。

OpenSSLのs_clientサブコマンドの実行例 OpenSSLのs_clientサブコマンドの実行例

●バーチャルホストの場合は「-servername」オプションが必須

 1つのIPアドレスで複数のサーバ(ホスト)がリッスンしている、いわゆる「バーチャルホスト」の場合、「-servername」オプションを追加して対象サーバを明確に指定する必要がある。

openssl s_client -connect <サーバの名前またはIPアドレス>:<ポート番号> -servername <サーバのFQDN> < nul > <保存先ファイル名>



 <サーバのFQDN>には、バーチャルホストのFQDN(完全なドメイン名)を指定する。これは通常、対象となっているSSLサーバ証明書の共通名あるいは別名のいずれかと合致しているはずだ。

 もし、このオプションを指定せずにバーチャルホストからSSLサーバ証明書を取得しようとすると、同じIPアドレスのデフォルトのホスト、つまり(たいていの場合は)見当違いのホストに割り当てられている証明書が返されてしまう。

●STARTTLSの場合は「-name」「-starttls」オプションが必須

 587番ポートをリッスンするSMTPサーバは通常、「STARTTLS」というプロトコルを使ってTLSでの接続を確立する。この場合、次のように「-name」「-starttls」オプションを指定する必要がある(指定しないとエラーになる)。

openssl s_client -connect <サーバの名前またはIPアドレス>:<ポート番号> -name <サーバのFQDN> -starttls smtp < nul > <保存先ファイル名>



 <サーバのFQDN>には、対象のSMTPサーバのホスト名を完全なドメイン名で記述する。

SSLサーバ証明書の有効期間の終了日時を表示する

 取得・保存したSSLサーバ証明書の期限が切れる日時を表示するには、次のようにOpenSSLの「x509」サブコマンドを実行する。

openssl x509 -in <証明書を格納したファイル> -nocert -enddate



 <証明書を格納したファイル>には、前述のs_clientサブコマンドの標準出力を保存したファイルを指定する。「-enddate」オプションは、証明書の有効期間の終了日時を表示するためのものだ。「-nocert」オプションは、(ここでは不要な)証明書の内容表示を止めるために指定する。

 s_clientサブコマンドの出力とx509サブコマンドの入力を、次のようにパイプでつないでもよい。

openssl s_client -connect www.example.jp:443 < nul | openssl x509 -nocert -enddate



 どちらの場合でも、「notAfter=Nov 24 23:59:00 2018 GMT」というフォーマットで有効期間の終了日時が表示される。

OpenSSLのx509サブコマンドの実行例(-enddateオプション) OpenSSLのx509サブコマンドの実行例(-enddateオプション)

SSLサーバ証明書の有効期間が30日以内に終了するかどうか確認する

 SSLサーバ証明書を漏れなく更新しなければならない立場としては、その有効期間の日時そのものより、証明書の期限が近日中に切れてしまうのか、それともまだ余裕があるのか判定できる方が便利だ。「-checkend」オプションを使うと、例えば30日以内に期限が切れるかどうかを判定できる。

openssl x509 -in <証明書を格納したファイル> -checkend <期限切れまでの秒数> -nocert



 例えば<期限切れまでの秒数>に「2592000」(=30日×24時間×60分×60秒)と指定すると、実行時点から30日後に対象の証明書の有効期間が終了しているかどうか判定され、次のように出力される。

  • Certificate will not expire」: 30日後でも、まだ有効期間内
  • Certificate will expire」: 30日後には、有効期間が終了する

 ちなみにいずれもGMT(グリニッジ標準時)で判定されるため、日本だと9時間の時差による誤差が生じる。それでも、十数日あるいは数十日といった単位で証明書の有効期間を判別するだけならば特段問題はないだろう。

OpenSSLのx509サブコマンドの実行例(-checkendオプション) OpenSSLのx509サブコマンドの実行例(-checkendオプション)

 また有効期間が終了すると判定された場合、openssl実行後の戻り値が1になる(期限内なら0)。これを利用すると、スクリプトやバッチファイルで有効期限切れが近い証明書を見つけたら通知する、といった処理が簡単に実現できる。

複数のサーバの証明書有効期間を一括確認する

 あとはスクリプトやバッチファイルなどで、管理下の各サーバの証明書を一括確認し、有効期間の終了が間近なものだけ通知するようにし、タスクスケジューラで1日1回実行するように設定しよう。こうすることで、手動に比べてはるかに網羅的に確認できる。

 参考までに、バッチファイルでの実装例を紹介しよう(言うまでもなくPowerShellやシェルスクリプトで実装してもよい)。まず対象のサーバのFQDNとポート番号、サービス名をタブ区切りのテキストファイルにまとめる(ここではlist-hosts.txtとする)。サービス名はSTARTSSLが必須かどうか判定するのに用いる。

#HostName              PortNumber  Service
www.example.jp       443              www
svr01.example.local  3389             rdsh
smtp.example.jp       587              startssl



 このリストをforコマンドで1行ずつ取得して、OpenSSLのオプションに設定しつつ実行する。以下にその例を記す。シンプルにするためエラー処理を省いているので、適宜強化していただきたい。

@echo off
setlocal

REM ----- ↓↓サーバ一覧ファイルの在りか
set URLList=.\list-hosts.txt
REM ----- ↓↓認証局の証明書ファイルの在りかを指定
set OsslClientOpts=-CAfile C:\local\CAcert\ca-bundle.crt
REM ----- ↓↓2592000秒=30日後に有効期間が終了しているかどうか判定
set OsslX509Opts=-checkend 2592000

REM ---------- 一覧ファイルのサーバを1つずつ検証 ----------
for /F "skip=1 tokens=1,2,3 delims=    " %%i in (%URLList%) do (
    set Host=%%i
    set Port=%%j
    set Service=%%k
    echo ----- %%i:%%j - %%k -----
    call :OpenSSL
)

REM ---------- 終了処理 ----------
:END
endlocal
exit /b

REM ---------- SSLサーバ証明書の有効期間を判定 ----------
:OpenSSL

if "%Service%" == "startssl" (
    openssl s_client -connect %Host%:%Port% %OsslClientOpts% -name       %Host% -starttls smtp <nul | openssl x509 %OsslX509Opts%
) ELSE (
    openssl s_client -connect %Host%:%Port% %OsslClientOpts% -servername %Host%                <nul | openssl x509 %OsslX509Opts%
)
if errorlevel 1 call :Notification
REM ----- ↑↑もし戻り値が1以上だったら、期限切れが間近だと見なして通知する

exit /b
REM -----

REM ---------- 通知の送信 ----------
: Notification

REM ----- ここにメール送信あるいはWebhookなど通知のためのロジックを記述 -----

exit /b
REM -----



 正常に動作することを確認したら、TIPS「タスクスケジューラの基本的な使い方(Windows 7/8.x/10編)」の手順でタスクスケジューラに登録し、1日1回定時に実行されるように仕込むとよいだろう。


 筆者が確認した限りでは、上記の手法でHTTPS対応Webサイトはもちろん、その他のSSL/TLS対応サーバでも有効期間を確認できた。

  • リモートデスクトップセッションホスト
  • リモートデスクトップゲートウェイ
  • SSTP対応のVPNサーバ(Windows Server)
  • IIS付属のSMTPサーバ

 一方、プロキシサーバを経由する必要があるネットワーク環境や、クライアント証明書が必須のサーバなどでは、s_clientサブコマンドにそのためのオプションを追加指定する必要がある。本稿では触れないので、OpenSSLのヘルプなどを参照していただきたい。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© 1999-2018 Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。