Сообщение об ошибке
x509: certificate is not valid for any names, but wanted to match api.example.com
Также выводится как
- tls: failed to verify certificate: x509: certificate is not valid for any names, but wanted to match api.example.com
Имя после «wanted to match» — адрес, к которому вы подключаетесь. Для сертификатов вообще без расширения SAN Go вместо этого сообщает «x509: certificate relies on legacy Common Name field, use SANs instead» (если бы CN совпал).
Go crypto/x509 — HostnameError for a certificate with no DNS SANs (e.g. IP-only or empty SAN list)
Что это означает
Go попытался сопоставить имя хоста с сертификатом и не нашёл в нём ни одного DNS-имени: расширение SAN есть, но содержит только IP-адреса (или записи других типов), а общее имя (CN) не учитывается. Go сообщает, что сертификат не покрывает ни одного имени, и затем указывает имя, которое искал.
Почему это происходит
Сертификат, выпущенный для IP-адреса, используется с именем хоста
частоСертификаты, созданные для адреса узла или виртуальной машины (только IP SAN), к которым позже стали обращаться по DNS-имени.
Сертификат для другой цели
иногдаКлиентские сертификаты, сертификаты электронной почты (S/MIME) или подписи кода не содержат DNS SAN и не могут служить серверными сертификатами.
Сервер предъявляет не тот сертификат
иногдаСервер по ошибке настроен с клиентским или внутренним сертификатом, часто после ротации ключей.
Как исправить
- 1.
Проверьте записи SAN и назначение сертификата
Список SAN показывает, какие типы имён в нём есть; extendedKeyUsage показывает, серверный ли это сертификат вообще.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -ext subjectAltName,extendedKeyUsage - 2.
Выпустите серверный сертификат с DNS SAN
Включите DNS-имена, которые используют клиенты, а также записи IP, если клиенты подключаются и по адресу.
bash openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com,IP:10.0.0.5" - 3.
Или подключайтесь по адресу, указанному в сертификате
IP SAN совпадает, только если клиент подключается именно к этому IP-адресу.
go // If the certificate is meant for the IP address, dial the IP (it is matched against IP SANs) resp, err := client.Get("https://10.0.0.5:8443/")