本文へスキップ
ecdsa.com
PHP streams (openssl stream wrapper)PHP

エラーメッセージ

Peer certificate subjectAltName did not match expected name `api.example.com'

別の表記

  • Warning: file_get_contents(): Peer certificate subjectAltName did not match expected name `api.example.com'

PHP は、想定する名前の前にバッククォート、後ろにアポストロフィを付けて示します。SAN 拡張のない証明書では、代わりに「Peer certificate CN=`…' did not match expected CN=`…'」が出力されます。ext-curl ベースのクライアント(Guzzle)は、同じ状況を cURL のエラー 60 として、「no alternative certificate subject name matches target hostname」というメッセージとともに報告します。

PHP streams (openssl stream wrapper) — verify_peer_name check

このエラーの意味

証明書チェーンの検証には成功しましたが、証明書のサブジェクト代替名(Subject Alternative Name)のどれも、PHP が想定する名前(URL のホスト、または peer_name コンテキストオプション)と一致しません。PHP のストリームラッパーは、ハンドシェイクの後にこのチェックを独自に行って接続を拒否し、その後に「Failed to enable crypto」が続きます。

発生する理由

修正方法

  1. 1.

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

    メッセージには想定されるホストが示されています。証明書の 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.

    アドレスで接続するときは peer_name を設定する

    ssl コンテキストオプションの peer_name を使うと、ソケットは IP アドレスに接続したまま、どの名前を検証するかを PHP に指定できます。

    php
    // Connect to an address but verify the certificate's real name
    $context = stream_context_create(['ssl' => ['peer_name' => 'mail.example.com']]);
    $socket = stream_socket_client('tls://10.0.0.25:465', $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
  3. 3.

    DSN には証明書のホスト名を使う

    メール送信ライブラリやクライアントには、サーバーの証明書に記載されている名前を設定してください。

    text
    # Mail libraries (PHPMailer, Symfony Mailer): use the SMTP host name from the certificate
    MAILER_DSN=smtp://user:pass@mail.example.com:587

関連するエラー

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