Mensaje de error
invalid peer certificate: certificate not valid for name "api.example.com"; certificate is only valid for DnsName("www.example.com")
El nombre esperado y la lista presentada se rellenan en cada fallo; las direcciones IP aparecen como IpAddress(…). Las versiones anteriores de rustls solo imprimían el nombre de la variante («invalid peer certificate: NotValidForName»).
rustls 0.23 (via reqwest, ureq, hyper-rustls) — CertificateError::NotValidForNameContext
Qué significa
La cadena es de confianza, pero el nombre al que se conectó el cliente no figura entre los nombres alternativos del sujeto (SAN) del certificado. rustls 0.23 muestra ambos: el nombre esperado y todos los nombres que presenta el certificado (entradas DnsName, IpAddress), lo que hace evidente la discrepancia.
Por qué ocurre
El certificado no cubre este nombre
frecuenteFalta en la lista SAN otro subdominio, el dominio raíz o un servicio renombrado; un comodín solo cubre una etiqueta.
Conexión por IP o por un alias interno
frecuenteNombres de servicio (Kubernetes, docker-compose) o direcciones IP directas para los que nunca se emitió el certificado.
El servidor envió su certificado predeterminado
ocasionalUn proxy sin configuración para el nombre solicitado sirve el certificado de otro sitio.
Cómo solucionarlo
- 1.
Comparar los nombres presentados con la URL
El mensaje ya los enumera; openssl confirma qué envía el servidor.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName - 2.
Sustituir la dirección, no el nombre
ClientBuilder::resolve de reqwest asocia un nombre de host a una dirección de socket concreta, así que la verificación sigue usando el nombre del certificado.
rust // Keep the certificate's name in the URL and send the connection to a specific address let addr: std::net::SocketAddr = "10.0.0.5:443".parse()?; let client = reqwest::Client::builder().resolve("www.example.com", addr).build()?; let resp = client.get("https://www.example.com/health").send().await?; - 3.
Volver a emitir con todos los nombres en uso
Añade al certificado los nombres DNS que faltan (o las entradas 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"