本文へスキップ
ecdsa.com
Ruby openssl (Net::HTTP verify_hostname, default true)Ruby

エラーメッセージ

state=error: certificate verify failed (hostname mismatch)

別の表記

  • OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=127.0.0.1:8443 state=error: certificate verify failed (hostname mismatch)

メッセージ全文:「SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (hostname mismatch)」。ホスト名自体はメッセージに含まれません。URL と証明書を比較してください。

Ruby openssl (Net::HTTP verify_hostname, default true) — OpenSSL::SSL::SSLError from SSL_connect

このエラーの意味

チェーンは信頼されていますが、Net::HTTP の接続先のホスト名が、証明書のサブジェクト代替名に含まれていません。現在の Ruby のバージョンでは、ハンドシェイク中に OpenSSL がホスト名をチェックする(verify_hostname)ため、この問題は証明書の検証の失敗として表面化します。古い Ruby では、接続後に「hostname … does not match the server certificate」という別のエラーが発生していました。

発生する理由

修正方法

  1. 1.

    SAN のリストとホストを比較する

    メッセージには名前が含まれていないため、証明書から名前を出力してください。

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -ext subjectAltName
  2. 2.

    証明書の名前を使い、アドレスを固定する

    Net::HTTP#ipaddr= を使うと、SNI と検証にはホスト名を使ったまま、指定した IP に接続できます。

    ruby
    # Connect to a specific address but verify the certificate's name (Net::HTTP#ipaddr=)
    http = Net::HTTP.new("www.example.com", 443)
    http.ipaddr = "10.0.0.5"
    http.use_ssl = true
    http.get("/health")
  3. 3.

    使用中のすべての名前を含めて再発行する

    不足している名前を subjectAltName に追加してください。

    bash
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com,DNS:www.example.com"

関連するエラー

署名エラーデータベースをすべて見る