rustls 0.23 (via reqwest, ureq, hyper-rustls)Rust
エラーメッセージ
invalid peer certificate: certificate not valid for name "api.example.com"; certificate is only valid for DnsName("www.example.com")
期待される名前と提示された名前のリストには、失敗ごとに実際の値が入ります。IP アドレスは IpAddress(…) として表示されます。以前の rustls のリリースは、バリアント名だけを出力していました(「invalid peer certificate: NotValidForName」)。
rustls 0.23 (via reqwest, ureq, hyper-rustls) — CertificateError::NotValidForNameContext
このエラーの意味
チェーンは信頼されていますが、クライアントの接続先の名前が、証明書のサブジェクト代替名に含まれていません。rustls 0.23 は、期待される名前と、証明書が提示するすべての名前(DnsName、IpAddress のエントリ)の両方を一覧表示するため、不一致がすぐにわかります。
発生する理由
証明書にこの名前が含まれていない
よくある別のサブドメイン、apex ドメイン、名前が変わったサービスが SAN のリストに含まれていません。ワイルドカードが対象とするのは 1 つのラベルだけです。
IP アドレスや内部の別名で接続している
よくある一度も証明書の発行対象になっていない、サービス名(Kubernetes、docker-compose)や IP アドレスそのものです。
サーバーがデフォルトの証明書を送信した
ときどき要求された名前の設定がないプロキシは、別のサイトの証明書を返します。
修正方法
- 1.
提示された名前と URL を比較する
名前はメッセージにすでに列挙されています。サーバーが実際に送信しているものは openssl で確認できます。
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName - 2.
名前ではなくアドレスを上書きする
reqwest の ClientBuilder::resolve はホスト名をソケットアドレスに固定するため、検証には引き続き証明書の名前が使われます。
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.
使用中のすべての名前を含めて再発行する
不足している 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"