本文へスキップ
ecdsa.com
curl (OpenSSL backend)curl

エラーメッセージ

curl: (60) SSL: no alternative certificate subject name matches target hostname 'api.example.com'

別の表記

  • curl: (60) SSL: no alternative certificate subject name matches target host name 'api.example.com'

curl 8.x は「target hostname」と出力します。curl 7.x では「target host name」でした。引用符で囲まれたホストは、URL に含まれていたものがそのまま表示されます。非常に古いバージョンの curl(7.62.0 より前)は、このチェックに終了コード 51 を使っていました。

curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, hostname check in lib/vtls/openssl.c

このエラーの意味

証明書チェーンは信頼されていますが、証明書のサブジェクト代替名(SAN)拡張に含まれる DNS 名(または IP アドレス)のどれも、URL のホストと一致しません。curl は URL のホストを SAN のエントリとだけ比較し、SAN 拡張がある場合、サブジェクトのコモンネームは無視されます。末尾に引用符付きで示される名前は、curl に接続先として指定されたホストです。

発生する理由

修正方法

  1. 1.

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

    返される証明書の subjectAltName 拡張を表示してください。解決策は、その名前を含む証明書を使うか、記載されている名前のいずれかを使った URL にするかのどちらかです。

    bash
    # Names the served certificate actually covers
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
  2. 2.

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

    すべてのホスト名(クライアントが IP で接続する場合は IP アドレスも)を SAN エントリとして要求してください。名前をコモンネームにだけ入れても、現行のクライアントではどれも機能しません。

    bash
    # ACME: list every name the certificate must cover
    sudo certbot certonly --nginx -d example.com -d www.example.com -d api.example.com
    
    # Private CA: put all names into subjectAltName (CN is ignored for matching)
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com,DNS:www.example.com,IP:10.0.0.5"
  3. 3.

    名前はそのままで、アドレスだけを変える

    特定のアドレス(ロードバランサーのノード、トンネル、ステージングの IP)に接続する必要がある場合、--resolve や --connect-to を使えば URL のホストが維持されるため、SNI とホスト名のチェックには引き続き証明書の名前が使われます。

    bash
    # Keep the certificate's name in the URL and steer the connection to another address
    curl --resolve api.example.com:443:10.0.0.5 https://api.example.com/
    curl --connect-to api.example.com:443:lb-internal.example.net:443 https://api.example.com/
  4. 4.

    サーバー管理者:SNI のルーティングを確認する

    SNI ありとなしのリクエストで証明書が異なる場合は、その名前の server ブロック(または Ingress のルール)を追加し、実際のホスト名に対してクライアントがデフォルトの証明書を受け取ることがないようにしてください。

    bash
    # Compare what the server returns with and without SNI
    openssl s_client -connect 10.0.0.5:443 -servername api.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject
    openssl s_client -connect 10.0.0.5:443 -noservername </dev/null 2>/dev/null | openssl x509 -noout -subject

関連するエラー

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