Mensaje de error
Peer certificate subjectAltName did not match expected name `api.example.com'
También se muestra como
- Warning: file_get_contents(): Peer certificate subjectAltName did not match expected name `api.example.com'
PHP encierra el nombre esperado entre un acento grave delante y un apóstrofo detrás. Los certificados sin extensión SAN producen en su lugar «Peer certificate CN=`…' did not match expected CN=`…'». Los clientes basados en ext-curl (Guzzle) informan de la misma situación como error 60 de cURL con «no alternative certificate subject name matches target hostname».
PHP streams (openssl stream wrapper) — verify_peer_name check
Qué significa
La cadena de certificados se verificó, pero ninguno de los nombres alternativos del sujeto (SAN) del certificado coincide con el nombre que esperaba PHP (el host de la URL o la opción de contexto peer_name). La envoltura de flujos de PHP hace esta comprobación por su cuenta después del handshake y rechaza la conexión, tras lo cual aparece «Failed to enable crypto».
Por qué ocurre
El certificado no incluye el nombre de host
frecuenteLa URL usa un nombre para el que no se emitió el certificado.
Conexión por IP o por un alias interno
frecuenteEs habitual en las conexiones a bases de datos, LDAP y SMTP configuradas con direcciones IP.
Servidores de retransmisión SMTP a los que se accede con otro nombre
ocasionalClientes de envío de correo configurados con «localhost» o con un alias del proveedor, mientras que el servidor presenta un certificado para su nombre público.
Cómo solucionarlo
- 1.
Comparar la lista de SAN con el host
El mensaje indica el host esperado; los SAN del certificado muestran qué nombres cubre.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName - 2.
Definir peer_name al conectar por dirección
La opción de contexto ssl peer_name indica a PHP qué nombre debe verificar mientras el socket se conecta a una dirección 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.
Usar en los DSN el nombre de host del certificado
Configura los clientes de envío de correo y demás clientes con el nombre que figura en el certificado del servidor.
text # Mail libraries (PHPMailer, Symfony Mailer): use the SMTP host name from the certificate MAILER_DSN=smtp://user:pass@mail.example.com:587
Errores relacionados
SSL operation failed with code 1. OpenSSL Error messages:PHP streams (file_get_contents, fopen, stream_socket_client, SoapClient, mail libraries)curl: (60) SSL: no alternative certificate subject name matches target hostname…curl (OpenSSL backend)x509: certificate is valid for example.com, not api.example.comGo crypto/x509