SSL証明書の更新作業でドハマりした話


はじめに

思い込みは危険。
そして自分への戒めということで備忘録として残す。
ネタ自体はさんざん既出だと思うけどw

SHA2対応の証明書組み込み作業

あるあるSHA2対応のサーバー証明書組み込み。
今回は有効期限切れ前の証明書の更新作業。
SHA2対応にかかわらずオペレーションとしては一緒だけど。

今回組み込んだ環境(Apacheのバージョン)は以下の通り。

$ httpd -v
Server version: Apache/2.2.29 (Unix)
Server built:   Mar 12 2015 03:50:17

証明書アップロード(SCP)

証明書関連のファイルのアップロード。
アップロード方法は諸方法あるけど、当方の環境はsshでconfigに設定記載済みのため、configのホスト情報を使ってscpでアップロードを行う。

.ssh/config
### 設定はダミーなので適宜読み替え必要
Host cert_hostname
HostName 10.**.***.123
User username
IdentityFile ~/.ssh/id_rsa/host.pem
Port 22

[username@hostname]の省略くらいにしかならないけど。
要は[username@hostname]を.ssh/configのHostで置き換える形。

-> % scp certfile cert_hostname:/path/to/dstdir
    certfile   100% 1675     1.6KB/s   00:00

環境確認

SSLの設定はデフォルトでここ。
/etc/httpd/conf.d/ssl.conf

既存の設定は中間証明書未使用。
今回は中間証明書使用。

    #   Server Certificate:
    SSLCertificateFile /path/to/certfile

    #   Server Private Key:
    SSLCertificateKeyFile /path/to/keyfile

    #   Server Certificate Chain:
    #SSLCertificateChainFile /path/to/chainfile

SSLCertificateChainFile と SSLCACertificateFile の違い

  • SSLCertificateChainFileディレクティブ:サーバー証明書における中間証明書のパスを設定
  • SSLCACertificateFileディレクティブ:クライアント証明書における中間証明書のパスを指定

注)これはあくまでApache2.2.x時点の設定
Apache2.4.8以降はSSLCertificateChainFileディレクティブはない。

ファイルの設置とパーミッションの変更

新しい証明書ファイル持ってきて、既存ファイルはリネーム。
ファイルのパーミッションもセキュリティの観点からreadonlyに。

# chmod 400 keyfile
# chmod 404 chainfile
# chmod 404 certfile

ssl.confの設定変更

中間証明書を利用するためSSLCertificateChainFileディレクティブのコメントアウトを外す。

    #   Server Certificate:
    SSLCertificateFile /path/to/certfile

    #   Server Private Key:
    SSLCertificateKeyFile /path/to/keyfile

    #   Server Certificate Chain:
    SSLCertificateChainFile /path/to/chainfile

configtest(シンタックスチェック。httpd -tと同義)

    # service httpd configtest
    Syntax OK

プロセスの状態を確認

    # service httpd status
    httpd (pid  1210) is running...

設定を反映

    # service httpd graceful

証明書の組み込み確認(s_client利用)

組み込み確認も諸方法あるけど、手っ取り早いのはサーバーの中にsshで入ってる状態であればopensslの s_client を利用する方法。
オプション駆使すればcipher周りの脆弱性のチェックも可能。
オプション駆使しなくても openssl s_client -connect だけでわりと見たい情報は見れる。便利便利。

$ openssl s_client -connect sub.example.com:443
CONNECTED(00000003)
depth=0 CN = sub.example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = sub.example.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 CN = sub.example.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain

・・・ 中略 ・・・

   Start Time: 1473157714
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

で、ここでエラーが出た。
chain情報とかすっ飛ばして、Verify return codeのステータスである程度わかる。
要はエラーになっている。

何回設定見返してもファイルアップロードし直しても改善されない。
その原因は・・・

まさかのSSL設定ファイルがカスタム設定になっていた

デフォルトは /etc/httpd/conf.d/ssl.conf なんだが
まさかのVirtualHostがきってあってSSL設定の参照先がデフォルトじゃねーよ!!!!
(※ちなみにこの更新作業において 事前情報として何も知らされていない

シンタックスチェックするなら -t より -S 使うほうがVirtualHostの設定も一覧で確認できるし良いと思う。

# httpd -S
    VirtualHost configuration:
    wildcard NameVirtualHosts and _default_ servers:
    *:443                  is a NameVirtualHost
             default server sub.example.com (/etc/httpd/conf.d/customssl.conf:22)
             port 443 namevhost sub.example.com (/etc/httpd/conf.d/customssl.conf:22)

・・・ 以下略 ・・・

 Syntax OK 

はい。これで書き換えたらちゃんとVerify return code: 0 (ok)で返ってきましたよ。

    $ openssl s_client -connect sub.example.com:443
    CONNECTED(00000003)
    depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
    verify return:1
    depth=1 C = US, O = GeoTrust Inc., CN = RapidSSL SHA256 CA
    verify return:1
    depth=0 CN = sub.example.com
    verify return:1
    ---
    Certificate chain
     0 s:/CN=sub.example.com
       i:/C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA
     1 s:/C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA
       i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
    ---
    Server certificate

    ・・・ 中略 ・・・

        Start Time: 1473165777
        Timeout   : 300 (sec)
        Verify return code: 0 (ok)

思い込みとは 怖いものだ。。。
みんなも作業時はあらゆる可能性を考慮して作業しましょう。。。