Saltar al contenido
ecdsa.com
Node.js tls.checkServerIdentity()crypto de Node.js

Mensaje de error

Hostname/IP does not match certificate's altnames: Host: api.example.com. is not in the cert's altnames: DNS:www.example.com

También se muestra como

  • Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the cert's list:
  • code: 'ERR_TLS_CERT_ALTNAME_INVALID'
  • ERR_TLS_CERT_ALTNAME_INVALID

El host y la lista de altnames se rellenan con los valores de cada fallo. Para direcciones IP, el texto es «Hostname/IP does not match certificate's altnames: IP: <address> is not in the cert's list: <entries>». npm lo muestra como «npm error code ERR_TLS_CERT_ALTNAME_INVALID».

Node.js tls.checkServerIdentity() — code ERR_TLS_CERT_ALTNAME_INVALID

Qué significa

La cadena de certificados es de confianza, pero tls.checkServerIdentity() no encontró ningún nombre alternativo del sujeto (SAN) que coincida con el host al que se conectó Node.js. El mensaje muestra ambos lados: el host solicitado y los nombres que contiene realmente el certificado, así que la discrepancia se ve de un vistazo. El nombre común se ignora cuando el certificado tiene una extensión SAN.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Listar los nombres del certificado

    Compara subjectAltName con el host al que te conectas.

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -ext subjectAltName
  2. 2.

    Volver a emitir el certificado con todos los nombres en uso

    Añade todos los nombres DNS y, donde los clientes se conecten por dirección, las entradas de tipo IP.

    bash
    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.

    Establecer servername al conectarse por dirección

    Deja el nombre del certificado en servername (y en el encabezado Host) y conéctate a la dirección; así la verificación usa el nombre correcto en lugar de quedar desactivada.

    js
    // Connect to an address but verify the certificate's real name (also sent as SNI)
    import https from "node:https";
    
    https.get({ host: "10.0.0.5", port: 443, path: "/", servername: "api.example.com",
                headers: { host: "api.example.com" } }, (res) => res.resume());
  4. 4.

    Excepción acotada con checkServerIdentity

    Para un host heredado cuyo certificado todavía no se puede volver a emitir, asigna un único alias conocido al nombre del certificado y delega en tls.checkServerIdentity(). Nunca devuelvas undefined de forma incondicional: eso desactiva por completo la comprobación del nombre.

    js
    // Narrow exception for a host you cannot reissue: accept one extra name, keep all other checks
    import https from "node:https";
    import tls from "node:tls";
    
    const agent = new https.Agent({
      checkServerIdentity: (host, cert) =>
        tls.checkServerIdentity(host === "legacy-alias.internal" ? "api.example.com" : host, cert),
    });

Errores relacionados

Explorar toda la base de datos de errores de firma