本文へスキップ
ecdsa.com
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 のエントリ)の両方を一覧表示するため、不一致がすぐにわかります。

発生する理由

修正方法

  1. 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. 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. 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"

関連するエラー

署名エラーデータベースをすべて見る