エラーメッセージ
No subject alternative DNS name matching api.example.com found.
別の表記
- javax.net.ssl.SSLHandshakeException: (certificate_unknown) No subject alternative DNS name matching api.example.com found.
- java.security.cert.CertificateException: No subject alternative DNS name matching api.example.com found.
ホストは URL に含まれていたものです。JDK 21 と 25 では TLS アラートが先頭に付き、「(certificate_unknown) No subject alternative DNS name matching … found.」となります。SAN 拡張がまったくない証明書や IP アドレスの URL では、代わりにそれぞれ「No subject alternative names present」と「No subject alternative names matching IP address … found」が出力されます。
Java (JSSE HostnameChecker) — java.security.cert.CertificateException inside SSLHandshakeException
このエラーの意味
証明書チェーンは信頼されていますが、Java のホスト名チェック(HTTPS エンドポイント識別)で、証明書のサブジェクト代替名拡張に URL のホストと一致する DNS エントリが見つかりませんでした。メッセージ中のホストは、Java が接続を求められたホストです。証明書に SAN 拡張があるため、コモンネームは考慮されません。
発生する理由
証明書がこのホスト名に対応していない
よくある証明書は別の名前(www.、ネイキッドドメイン、古いサービス名)に対して発行されています。ワイルドカードが対応するのは 1 つのラベルだけです。
クライアントが内部のエイリアスやサービス名を使っている
よくあるKubernetes のサービス名、docker-compose のエイリアス、ロードバランサーのホスト名は、正しいサーバーには到達しますが、公開用の名前に対して発行された証明書には含まれていません。
サーバーが別のサイトの証明書を返した
ときどき共有のエンドポイントでは、証明書は SNI によって決まります。設定されていない名前に対しては、デフォルトの証明書が返されます。
修正方法
- 1.
証明書の名前を一覧表示する
openssl または keytool -printcert -sslserver を使うと SubjectAlternativeName のエントリが表示されるので、URL と比較してください。
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName # or with Java's own tool keytool -printcert -sslserver api.example.com:443 | grep -A3 SubjectAlternativeName - 2.
不足している名前を含めて証明書を再発行する
クライアントが使うすべての DNS 名を要求してください。keytool の -ext SAN=dns:…,dns:… を使うと、それらを CSR に追加できます。
bash # Java keystores: request a certificate with every name in the SAN extension keytool -certreq -alias server -keystore server.p12 -ext "SAN=dns:api.example.com,dns:www.example.com" -file server.csr - 3.
証明書に記載された名前で接続する
ホスト名の検証は有効なままにして、代わりに URL(および名前解決)を変更してください。すべてを受け入れる HostnameVerifier は、TLS の存在意義である保護そのものを無効にします。
java // Use the name in the certificate in the URL; resolve it to the address you need // (DNS, /etc/hosts or a custom resolver), instead of connecting by IP or alias. HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.example.com/health")).build();
関連するエラー
No subject alternative names matching IP address 127.0.0.1 foundJava (JSSE HostnameChecker)No subject alternative names presentJava (JSSE HostnameChecker)x509: certificate is valid for example.com, not api.example.comGo crypto/x509curl: (60) SSL: no alternative certificate subject name matches target hostname…curl (OpenSSL backend)