その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

SSL/TLS化しているサイトにリクエストを投げたら証明書の検証にしくじっているという時

表題のような状況のトラブルシュートについて記します.

moznion.hatenablog.com

というかこれの続きです.怪奇現象など存在しない.

背景

  • ブラウザとかcurlとかからはリクエストが通るのにJavaからは通らない
  • Let's encryptの証明書を使っている
    • Let's encryptでSSL/TLS化された他のサイトにはリクエストが通る
  • 当該サーバにSSHする権利がない (あとで出来るようになった)

検討したこと

  • 認証局が違うのではないか
  • Cipherがおかしいのではないか (鍵長が短いとか)
    • 証明書側
    • リバースプロキシ側
    • Java*1
  • 中間証明書がなんかおかしいのではないか

調査方法

とりあえずcipherは調べたけど特におかしいところは見当たりませんでした.
認証局についてはブラウザで確認してみたら双方同じRoot CA,中間CAで,それぞれfingerprintも同一だし問題なかろういう結論に.
というわけで中間証明書周りを疑いはじめる (というかid:hdkshjmさんとid:uzullaさんから示唆を受ける).しからば検証.

$ openssl version
OpenSSL 1.0.2l  25 May 2017
$ openssl s_client -connect $TARGET_HOST:443 -showcerts < /dev/null

とすると末尾に

Verify return code: 21 (unable to verify the first certificate)

というのが出てくる.証明書の検証にしくじっているのはまず間違いなさそう.
では認証チェーンのチェックをしてみましょう (一部ドメイン情報に編集を入れています).

$ openssl s_client  -connect moznion.net:443 < /dev/null | grep "Certificate chain" -A 10
Certificate chain
 0 s:/CN=moznion.net
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
(以下略)
$ openssl s_client -connect $TARGET_HOST:443 < /dev/null | grep "Certificate chain" -A 10
Certificate chain
 0 s:/CN=<host>
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
(以下略)

正常に動いている https://moznion.net と比較すると中間証明書がすっぽ抜けている事がわかります.

こうなるともはや何も難しいことはありません.nginxの ssl_certificateサーバ証明書だけが突っ込まれており,中間証明書が結合されていないという典型的なやつでした.
というわけでLet's encryptが提供してくれる fullchain.pemssl_certificate に食わせてやると果たして正しく動作しましたとさ.めでたしめでたし.

教訓

  • おちついてトラブルシューティングをする.ちゃんとやればわかる.
  • opensslコマンドをちゃんと知っておく.
  • サーバをセットアップした人にちゃんとヒアリングすると楽.

その他

curlやブラウザには当該中間証明書 (すっぽ抜けてたやつ) がバンドルされているからリクエストが通った?
Javaにはそれがなかった? あるいはJavaはチェーンの検証が厳密?