本文へスキップ
ecdsa.com
.NET SslStream / HttpClient.NET

エラーメッセージ

The remote certificate was rejected by the provided RemoteCertificateValidationCallback.

.NET Core および .NET 5〜10 で共通の文言です。HttpClient はこれを「The SSL connection could not be established, see inner exception.」でラップします。コールバックに渡される SslPolicyErrors の値を見れば、.NET 自体も問題を検出していたかどうかがわかります。

.NET SslStream / HttpClient — a custom validation callback returned false

このエラーの意味

アプリケーションが独自の証明書検証コールバック(ServerCertificateCustomValidationCallback または RemoteCertificateValidationCallback)を設定しており、そのコールバックが false を返しました。.NET の組み込みのチェックは通過していた可能性があり、証明書を拒否すると判断したのはアプリケーションのコードです。サーバーの証明書が更新またはローテーションされた後に、証明書や鍵のピンニングで起こりがちです。

発生する理由

修正方法

  1. 1.

    コールバックが受け取る内容をログに記録する

    コールバックの中で SslPolicyErrors、サブジェクト、SHA-256 サムプリント、有効期限を記録し、そのうえでピンのリストを更新するか、証明書を修正してください。

    csharp
    ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
    {
        var thumbprint = cert!.GetCertHashString(HashAlgorithmName.SHA256);
        logger.LogWarning("TLS {Host}: errors={Errors} subject={Subject} sha256={Thumb} notAfter={NotAfter:u}",
            request.RequestUri?.Host, errors, cert.Subject, thumbprint, cert.NotAfter);
        return errors == SslPolicyErrors.None && pinnedThumbprints.Contains(thumbprint);
    },
  2. 2.

    公開鍵をピンニングし、バックアップのピンも用意する

    SPKI のピンは、鍵を再利用する更新であれば有効なままです。ローテーションでクライアントが接続できなくならないよう、必ず少なくとも 1 つのバックアップ鍵もピンニングしてください。

    bash
    # Pin the public key (SPKI) rather than the certificate: it survives renewals with the same key
    openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null \
      | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

関連するエラー

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