web-dev-qa-db-ja.com

SSL証明書サーバー名の解決方法/ keytoolを使用して代替名を追加できますか?

これらは明確にするために個別の質問として表現される場合がありますが、すべて同じ問題に関連しています。

SSL証明書サーバー名はどのように解決されますか?

ブラウザが証明書のCNフィールドを使用しているように見えるのに、Javaのメカニズムは「サブジェクトの別名」のみを見るように見えるのはなぜですか?

Keytoolを使用してSSL証明書に代替名を追加することはできますか?そうでない場合は、代わりにopenSSLを使用するのが適切なオプションですか??

ちょっとした背景:メインサーバーがHTTPSを使用して複数のサーバーと通信できるようにする必要があります。当然、すべてのサーバーにSSL証明書を購入する必要はありません(多くの場合があります)ので、自己署名証明書を使用します(キーツールを使用して証明書を生成しています)。 OSで信頼できる証明書を追加した後、ブラウザー(IEおよびChrome)は接続を信頼できるものとして喜んで受け入れます。ただし、証明書をJavaのcacertsに追加した後でも、Javaは接続を信頼済みとして受け入れず、次の例外をスローします。

原因:Java.security.cert.CertificateException:Sun.security.util.HostnameChecker.match(HostnameChecker.Java:75)のSun.security.util.HostnameChecker.matchIP(HostnameChecker.Java:142)にサブジェクトの別名が存在しないcom.Sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.Java:264)at com.Sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.Java:250)at com。 Sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien tHandshaker.Java:1185)... 14その他

ここからコピーした、独自のHostNameVerifierを実装する証明書をJava信頼できるようにしたことがわかりました。 com.Sun.jbi.internal.security.https.DefaultHostnameVerifier (ところで、HostnameVerifierへの引数として渡されたホスト名は正しいので、受け入れられるべきだったと思います)。

証明書フィールドCNをホスト名(通常はIPアドレス)として使用しています。

誰かが私が何か間違ったことをしていて正しい方向に私を向けているかどうかを教えてもらえますか?

71
Renato

ホスト名の検証方法は RFC 6125 で定義されています。これはごく最近のことであり、すべてのプロトコルの慣行を一般化し、HTTPSに固有の RFC 2818 を置き換えます。 (Java 7がRFC 6125を使用しているかどうかはわかりませんが、RFC 6125はこれには遅すぎるかもしれません。)

RFC 2818(セクション3.1) から:

DNSName型のsubjectAltName拡張が存在する場合、それをIDとして使用する必要があります。そうでない場合は、証明書のSubjectフィールドの(最も具体的な)Common Nameフィールドを使用する必要があります。共通名の使用は既存の慣習ですが、廃止されており、代わりにdNSNameを使用することを証明機関に推奨します。

[...]

場合によっては、URIはホスト名ではなくIPアドレスとして指定されます。この場合、iPAddress subjectAltNameは証明書に存在する必要があり、URIのIPと正確に一致する必要があります。

基本的に、特定の問題は、ホスト名ではなくCNでIPアドレスを使用しているという事実に起因しています。すべてのツールがこの仕様に厳密に準拠しているわけではないため、特にRFC 2818の「最も具体的な」が明確に定義されていないため、一部のブラウザーは機能します(RFC 6215の説明を参照)。

keytoolを使用している場合、 Java 7、現在、keytool にはサブジェクトの別名を含めるオプションがあります(ドキュメントの表を参照してください) -ext):-ext san=dns:www.example.comまたは-ext san=ip:10.0.0.1を使用できます。

編集:

OpenSSLでSANを要求するには、openssl.cnfを変更します(覚えている限り、グローバル構成を編集したくない場合は、現在のディレクトリでコピーを選択します。 OPENSSL_CONF環境変数を使用して明示的な場所を選択できます)。

以下のオプションを設定します(最初に括弧内の適切なセクションを見つけます)。

[req]
req_extensions = v3_req

[ v3_req ]
subjectAltName=IP:10.0.0.1
# or subjectAltName=DNS:www.example.com

環境変数を使用するための素敵なトリックもあります(構成ファイルで環境変数を修正するのではなく): http://www.crsr.net/Notes/SSL.html

91
Bruno