Сообщение об ошибке
Hostname/IP does not match certificate's altnames: Host: api.example.com. is not in the cert's altnames: DNS:www.example.com
Также выводится как
- 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
Хост и список altnames в каждом случае свои. Для IP-адресов формулировка такая: «Hostname/IP does not match certificate's altnames: IP: <address> is not in the cert's list: <entries>». npm выводит эту ошибку как «npm error code ERR_TLS_CERT_ALTNAME_INVALID».
Node.js tls.checkServerIdentity() — code ERR_TLS_CERT_ALTNAME_INVALID
Что это означает
Цепочка сертификатов признана доверенной, но tls.checkServerIdentity() не нашла ни одного альтернативного имени субъекта (SAN), совпадающего с хостом, к которому подключился Node.js. В сообщении указаны обе стороны: хост, который вы запросили, и имена, которые на самом деле содержит сертификат, поэтому несоответствие видно сразу. Общее имя (CN) игнорируется, если в сертификате есть расширение SAN.
Почему это происходит
В сертификате нет этого имени
частоСертификат для www.example.com не распространяется ни на api.example.com, ни на домен без поддомена; wildcard-имя покрывает только одну метку (один уровень) домена.
Подключение по IP, через localhost или по псевдониму контейнера
частоURL вроде https://127.0.0.1:8443 или https://backend:443 внутри docker-compose запрашивают имена, которых нет в сертификате; для IP-адресов нужны записи типа IP в SAN.
Изменён только заголовок Host, а не имя для TLS
иногдаЕсли при подключении по IP задать в headers.host (заголовок Host) правильное имя, это не изменит того, что проверяет Node.js: параметр servername (или хост в URL) определяет, какое имя проверяется и отправляется в SNI.
Сервер вернул сертификат по умолчанию
иногдаОбратный прокси, в конфигурации которого нет этого имени, отвечает сертификатом другого сайта.
Как исправить
- 1.
Посмотрите имена в сертификате
Сравните subjectAltName с хостом, к которому подключаетесь.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName - 2.
Перевыпустите сертификат со всеми используемыми именами
Добавьте все DNS-имена, а если клиенты подключаются по адресу, то и записи типа 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.
Задавайте servername при подключении по адресу
Укажите имя из сертификата в servername (и в заголовке Host), а подключайтесь по адресу; тогда проверка идёт по правильному имени, а не отключается.
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.
Точечное исключение через checkServerIdentity
Для устаревшего хоста, сертификат которого пока нельзя перевыпустить, сопоставьте один известный псевдоним с именем из сертификата и передайте проверку в tls.checkServerIdentity(). Никогда не возвращайте undefined безусловно: это полностью отключает проверку имени.
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), });
Связанные ошибки
npm error code ERR_TLS_CERT_ALTNAME_INVALIDnpm (Node.js)x509: certificate is valid for example.com, not api.example.comGo crypto/x509curl: (60) SSL: no alternative certificate subject name matches target hostname…curl (OpenSSL backend)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch,…Python ssl module (OpenSSL host check)