はじめに
WebサーバーにSSLサーバー証明書を設定したときは、Webブラウザで証明書の情報を確認しますよね。
また、僕は「SSL Server Test (Powered by Qualys SSL Labs)」でも、SSL設定や証明書の情報を確認します。
SSL Server Testでは、Webブラウザからのアクセスではわからない、たとえば次のような内容を確認できるので、とても便利です。
- 中間証明書チェーンに不具合がないか。
- Apache/Nginx等のWebサーバーソフトウェアのHTTPSセキュリティ設定、暗号化通信設定が適切か。
- デバイス、ブラウザごとの対応状況。
ここで、以下のようにWebサーバーがCDNやWAF配下のオリジンとなる構成の場合を考えてみます。
このような構成の場合、Webブラウザで確認できる証明書情報や、SSL Server Testで表示される証明書の情報は、CDNやWAFに設定された証明書情報であって、Webサーバーに設定した証明書情報ではありません。
ここでは、Webサーバーの前段にCDNやWAFがある場合に、オリジンWebサーバーに設定した証明書の情報を確認する方法について記載します。
確認方法
SSLサーバー証明書を設置したオリジンWebサーバー上で openssl s_client コマンドでクライアントからのWebアクセスを実行することで、証明書の情報を確認します。
openssl s_client コマンドを利用したSSLサーバー証明書の検証方法については、以下の記事がとてもわかりやすいです。
(参考)
・WebサーバーなどのSSL証明書 検証方法 – Info Circus, Inc. 技術情報
https://www.infocircus.jp/2019/10/23/openssl_cert_verify/
以下、証明書を確認したいWebサイトのドメインは inaba-serverdesign.jp とします。
証明書の検証
証明書の有効期限が切れていないことや、中間証明書のチェーンが正しいことを確認します。
-conect オプションで、ローカルホストのHTTPSポート 127.0.0.1:443 を指定するのがポイントです。
-servername で、確認したいWebサイトのドメインを指定します。
※ここで、-connect inaba-serverdesign.jp:443 とすると、DNSを参照して、前段のWAFもしくはCDNにアクセスします。そのため、出力される情報は、WAFまたはCDNに設定した証明書の情報となり、オリジンWebサーバーの証明書情報を確認できません。
$ openssl s_client -connect 127.0.0.1:443 \
-servername inaba-serverdesign.jp < /dev/null
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = inaba-serverdesign.jp
verify return:1
---
Certificate chain
0 s:/CN=inaba-serverdesign.jp
i:/C=US/O=Let's Encrypt/CN=R3
1 s:/C=US/O=Let's Encrypt/CN=R3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
(証明書の内容、省略)
-----END CERTIFICATE-----
subject=/CN=inaba-serverdesign.jp
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3174 bytes and written 445 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 032E9F21804B382BA5B56F8F9FEBD698545637ADCA5C9DE58A1584E6B5FF1F8B
Session-ID-ctx:
Master-Key: CB6AB037311B98F9A960339D902435E54239AA42ED7194D4297EFA6255F64DDEB6C7D998B8BF3A1FC352B1CD7EE37821
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 600 (seconds)
TLS session ticket:
(TLSセッションチケットの内容、省略)
Start Time: 1608705697
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE
証明書のチェーンやSSL接続情報などが出力されます。
検証としては、末尾のほうの「Verify return code: 0 (ok)」がポイントです。
Start Time: 1608705697
Timeout : 300 (sec)
Verify return code: 0 (ok)
この値が「0」以外であれば、中間証明書のチェーンがおかしい、証明書の有効期限が切れている、などの問題があります。
エラーの内容がエラーコードのうしろのカッコ内に記載されているので、それをもとに調査、対処することになります。
証明書の情報を確認
先ほどの検証コマンドの出力結果に対して、openssl x509 コマンドを実行することで、有効期間の日時や、、コモンネーム以外に証明書に追加したドメインを確認できます。
$ openssl s_client -connect 127.0.0.1:443 \
-servername inaba-serverdesign.jp < /dev/null \
2> /dev/null | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:ad:71:c4:f1:42:5b:56:4d:d5:07:63:2e:58:cd:77:a0:2c
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=R3
Validity
Not Before: Dec 3 04:50:43 2020 GMT
Not After : Mar 3 04:50:43 2021 GMT
Subject: CN=inaba-serverdesign.jp
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
(省略)
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
B4:6A:05:34:E4:66:F1:BD:01:DD:B4:93:95:3A:69:75:1C:54:07:D5
X509v3 Authority Key Identifier:
keyid:14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6
Authority Information Access:
OCSP - URI:http://r3.o.lencr.org
CA Issuers - URI:http://r3.i.lencr.org/
X509v3 Subject Alternative Name:
DNS:inaba-serverdesign.jp
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.44947.1.1.1
CPS: http://cps.letsencrypt.org
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1(0)
Log ID : 5C:DC:43:92:FE:E6:AB:45:44:B1:5E:9A:D4:56:E6:10:
37:FB:D5:FA:47:DC:A1:73:94:B2:5E:E6:F6:C7:0E:CA
Timestamp : Dec 3 05:50:43.663 2020 GMT
Extensions: none
Signature : ecdsa-with-SHA256
(省略)
Signed Certificate Timestamp:
Version : v1(0)
Log ID : 7D:3E:F2:F8:8F:FF:88:55:68:24:C2:C0:CA:9E:52:89:
79:2B:C5:0E:78:09:7F:2E:6A:97:68:99:7E:22:F0:D7
Timestamp : Dec 3 05:50:43.767 2020 GMT
Extensions: none
Signature : ecdsa-with-SHA256
(省略)
Signature Algorithm: sha256WithRSAEncryption
(省略)
-----BEGIN CERTIFICATE-----
(証明書の内容、省略)
-----END CERTIFICATE-----
証明書の有効期間は「Validity Not Before, Not After」で、コモンネームは、「Subject: CN」で確認できます。
Validity
Not Before: Dec 3 04:50:43 2020 GMT
Not After : Mar 3 04:50:43 2021 GMT
Subject: CN=inaba-serverdesign.jp
また、コモンネーム以外に証明書に追加したドメインは、「Subject Alternative Name DNS:」で確認できます。
X509v3 Subject Alternative Name:
DNS:inaba-serverdesign.jp
有効期間の日時のみピックアップしたい場合は、実行結果の標準出力に対して「Not」で grep すればよいです。
あるいは、openssl x509 のオプションで -noout -dates としても同様の結果となります。
$ openssl s_client -connect 127.0.0.1:443 \
-servername inaba-serverdesign.jp < /dev/null \
2> /dev/null | openssl x509 -text | grep "Not"
Not Before: Dec 3 04:50:43 2020 GMT
Not After : Mar 3 04:50:43 2021 GMT
$ openssl s_client -connect 127.0.0.1:443 \
-servername inaba-serverdesign.jp < /dev/null \
2> /dev/null | openssl x509 -noout -dates
notBefore=Dec 3 04:50:43 2020 GMT
notAfter=Mar 3 04:50:43 2021 GMT
証明書の更新作業の際は、有効期間を確認することで、古い証明書ではなく、新しく設定した証明書が参照されていることを確認できますね。
まとめ
CDNやWAF配下のオリジンWebサーバーに設置した証明書の確認方法を記載しました。
なぜ今回、この確認方法をブログ記事にしたかというと。。
僕は一度、外部WAFサービス配下のオリジンWebサーバーの証明書更新作業の際に確認を怠って、証明書の設定ミスに気付かなかったことがあるからです。
新しい証明書ファイルをサーバーに保存し、証明書ファイルそのものの内容は確認したのですが、シンボリックリンクの設定ミスでApacheに反映されず、古い証明書ファイルが参照されたままとなっていました。
そのときは幸い、オリジンWebサーバーの証明書の有効期限が切れたあとも、Webサイトはエラーもなく正しく表示されていたので、実質的な悪影響はありませんでした。
(外部WAFサービスからオリジンWebサーバーへのHTTPS通信時に、証明書の有効期限切れをスルーしていたようだ。)
ですが、エンジニアとしては、設定ミスそのものよりも、未テストで済ませてしまったことが恥ずかしいミスでした。
SSLサーバー証明書を新規、もしくは更新設定したときは、必ず何らかのクライアントからのアクセスで、証明書の情報を確認しましょう!

