跳到主要内容
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 error 60”,并附带“no alternative certificate subject name matches target hostname”。

PHP streams (openssl stream wrapper) — verify_peer_name check

含义

证书链验证通过了,但证书的主题备用名称(SAN)中没有一个与 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 告诉 PHP 要验证哪个名称,而套接字本身连接的是 IP 地址。

    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

相关错误

浏览完整的签名错误库