【PHP】SSL証明書の有効期限を取得する方法

  • 投稿 : 2020-02-12
ご利用は、自己責任で!!
異常系を考えてないので、想定外の時はいろいろまずいかも。

自動更新が失敗したら?!

多くのレンタルサーバーでは、無料SSLサーバー証明書 Let's Encryptは自動更新してくれて、失敗した時はメールで通知がくると思います。リトライとかも数回はやってくれるところが
多いので心配はいらないですが、自身でも検出出来たらよいかなぁと思ってました。PHPでSSL証明書の有効期限を取得できると知ったので、ちょっとやってみました。

参考にしたもの

How to get SSL certificate info with CURL in PHP? - Stack Overflow
PHP で外部サーバーの SSL サーバー証明書の有効期限を取得する - Qiita

1つ目を参考にしました。2つ目は情報源です。

方法その1:お勧め

<?php
function get_ssl_expire_date($domain){
  $stream_context = stream_context_create(array(
    'ssl' => array('capture_peer_cert' => true,
                   'verify_peer'         => false,
                   'verify_peer_name'    => false)
  ));
  $resource = stream_socket_client(
    'ssl://' . $domain . ':443',
    $errno,
    $errstr,
    30,
    STREAM_CLIENT_CONNECT,
    $stream_context
  );
  $cont = stream_context_get_params($resource);

  $parsed = openssl_x509_parse($cont['options']['ssl']['peer_certificate']);

  $date = null;

  if(strpos($parsed['subject']['CN'], $domain) !== false){
    $date = date('Y/m/d', $parsed['validTo_time_t']);
  }

    return $date;
}

//----------
// MAIN
//----------
$domain = $_SERVER['HTTP_HOST'];

$date = get_ssl_expire_date($domain);
echo $date;

$domain = $_SERVER['HTTP_HOST'];で、このスクリプトが動作しているドメイン(ホスト名)のSSLの期限を調べます。日付は、GMT/グリニッジ標準時です。

バリューサーバー、スターサーバーで動作確認しました。

補足

PHP: openssl_x509_parse - Manual

方法その2:curl版

<?php
function get_ssl_expire_date_curl($domain){
  $fp = tmpfile();

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL,"https://".$domain);
  curl_setopt($ch, CURLOPT_STDERR, $fp);
  curl_setopt($ch, CURLOPT_CERTINFO, 1);
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_NOBODY, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); //文字列に出力

  $result = curl_exec($ch);
  
  fseek($fp, 0);
  $output = fread($fp, 8192);
  //echo $output;
  fclose($fp);

  //----------
  $pattern="/expire date:(.*?)\n/";

  $subject=$output;
  preg_match($pattern,$subject, $matches);
  //print_r($matches);

  $date = new DateTime($matches[1]);
  //echo $date->format('U');
  //echo $date->format('Y-m-d H:i:s');

  return $date->format('Y-m-d');
}


//----------
// MAIN
//----------
$domain = $_SERVER['HTTP_HOST'];

$date = get_ssl_expire_date_curl($domain);
echo $date;

無料系のサーバーでは、stream_socket_clientあたりも制限されていて動作しないことが多いので、curlを使ったバージョンです。

スタードメイン付属の無料サーバーではうまく取得できています。バリューサーバーでも動作しました。

補足

CURLOPT_CERTINFO TRUE を設定すると、セキュアな転送時に SSL 証明書の情報を STDERR に出力します。
PHP: curl_setopt - Manual

これを利用して、SSLの有効期限を取得しています。

curl_setopt($ch, CURLOPT_STDERR, $fp);で、標準エラー出力を作業ファイル($fp)に出力しています。

出力内容を、pattern="/expire date:(.*?)\n/"; のパターンで正規表現で取得してますが、こんな決め打ちで良いのかは不明です。

スポンサーリンク
タグ#PHP#code