Saltar al contenido
ecdsa.com
curl (OpenSSL backend)curl

Mensaje de error

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

También se muestra como

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

curl 8.x imprime «target hostname»; curl 7.x imprimía «target host name». El host entre comillas es el que contenga la URL. Las versiones muy antiguas de curl (anteriores a 7.62.0) usaban el código de salida 51 para esta comprobación.

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

Qué significa

La cadena de certificados es de confianza, pero ninguno de los nombres DNS (ni de las direcciones IP) de la extensión de nombre alternativo del sujeto (SAN) del certificado coincide con el host de la URL. curl solo compara el host de la URL con las entradas SAN; el nombre común del sujeto se ignora cuando existe una extensión SAN. El nombre entre comillas del final es el host al que se pidió a curl que se conectara.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Comparar la lista SAN con la URL

    Imprime la extensión subjectAltName del certificado servido. La solución es un certificado que incluya el nombre o una URL que use uno de los nombres incluidos.

    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.

    Volver a emitir el certificado con todos los nombres en uso

    Solicita todos los nombres de host (y las direcciones IP, si los clientes se conectan por IP) como entradas SAN. Poner el nombre solo en el nombre común no funciona con ningún cliente actual.

    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.

    Mantener el nombre y cambiar solo la dirección

    Si tienes que llegar a una dirección concreta (un nodo del balanceador de carga, un túnel, una IP de preproducción), --resolve o --connect-to mantienen el host de la URL, de modo que el SNI y la comprobación del nombre de host siguen usando el nombre del certificado.

    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.

    Propietarios del servidor: comprobar el enrutamiento por SNI

    Si el certificado cambia entre solicitudes con y sin SNI, añade un bloque de servidor (o una regla de ingress) para el nombre y asegúrate de que los clientes no reciban el certificado predeterminado para los nombres de host reales.

    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

Errores relacionados

Explorar toda la base de datos de errores de firma