Diese können aus Gründen der Klarheit als separate Fragen formuliert werden, beziehen sich jedoch alle auf dasselbe Thema.
Wie werden SSL-Zertifikatservernamen aufgelöst?
Warum scheinen Browser das CN-Feld des Zertifikats zu verwenden, aber der Java-Mechanismus scheint nur "alternative Betreffnamen" zu betrachten?
Ist es möglich, mit keytool alternative Namen zu einem SSL-Zertifikat hinzuzufügen? Wenn nicht, ist die Verwendung von openSSL stattdessen eine gute Option?
Nur ein kleiner Hintergrund: Ich brauche einen Hauptserver, um mit mehreren Servern über HTTPS zu kommunizieren. Natürlich möchten wir nicht für jeden Server SSL-Zertifikate kaufen (es können viele sein), daher möchte ich selbstsignierte Zertifikate verwenden (ich habe Keytool verwendet, um sie zu generieren). Nachdem ich die Zertifikate als vertrauenswürdig im Betriebssystem hinzugefügt habe, akzeptieren die Browser (IE und Chrome) die Verbindung gerne als vertrauenswürdig. Selbst nach dem Hinzufügen der Zertifikate zu Javas Cacerts akzeptiert Java die Verbindung nicht als vertrauenswürdig und löst die folgende Ausnahme aus:
Auslöser: java.security.cert.CertificateException: Bei sun.security.util.HostnameChecker.matchIP (HostnameChecker.java:142) bei sun.security.util.HostnameChecker.match (HostnameChecker.java:75) sind keine alternativen Betreffnamen vorhanden. at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity (X509T rustManagerImpl.java:264) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrustr. sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate (Clien tHandshaker.java:1185) ... 14 weitere
Ich habe festgestellt, dass ich Java das Zertifikat vertrauen lassen kann, das meinen eigenen HostNameVerifier implementiert, den ich von hier kopiert habe: com.sun.jbi.internal.security.https.DefaultHostnameVerifier, nur um zu testen (übrigens, der Hostname wurde als Argument an den übergeben HostnameVerifier ist korrekt, daher denke ich, dass es hätte akzeptiert werden sollen.
Ich habe das Zertifikatfeld CN als Hostnamen verwendet (normalerweise die IP-Adresse).
Kann mir bitte jemand sagen, ob ich etwas falsch mache und mich in die richtige Richtung weisen?
Antworten:
Wie die Überprüfung des Hostnamens durchgeführt werden sollte, ist in RFC 6125 definiert , das relativ neu ist und die Praxis auf alle Protokolle verallgemeinert und RFC 2818 ersetzt , das für HTTPS spezifisch war. (Ich bin mir nicht einmal sicher, ob Java 7 RFC 6125 verwendet, was möglicherweise zu aktuell ist.)
Aus RFC 2818 (Abschnitt 3.1) :
Das spezifische Problem besteht im Wesentlichen darin, dass Sie in Ihrem CN IP-Adressen und keinen Hostnamen verwenden. Einige Browser funktionieren möglicherweise, weil nicht alle Tools dieser Spezifikation genau folgen, insbesondere weil "am spezifischsten" in RFC 2818 nicht klar definiert ist (siehe Erläuterungen in RFC 6215).
Wenn Sie verwenden
keytool
, wie von Java 7,keytool
hat eine Option , einen Subject Alternative Namen enthält (siehe die Tabelle in der Dokumentation-ext
): Sie nutzen könnten-ext san=dns:www.example.com
oder-ext san=ip:10.0.0.1
.BEARBEITEN:
Sie können ein SAN in OpenSSL anfordern, indem Sie es ändern
openssl.cnf
(es wählt die Kopie im aktuellen Verzeichnis aus, wenn Sie die globale Konfiguration, soweit ich mich erinnere, nicht bearbeiten möchten, oder Sie können mithilfe derOPENSSL_CONF
Umgebungsvariablen einen expliziten Speicherort auswählen ).Stellen Sie die folgenden Optionen ein (suchen Sie zuerst die entsprechenden Abschnitte in Klammern):
[req] req_extensions = v3_req [ v3_req ] subjectAltName=IP:10.0.0.1 # or subjectAltName=DNS:www.example.com
Es gibt auch einen guten Trick, eine Umgebungsvariable dafür zu verwenden (anstatt sie in einer Konfigurationsdatei zu reparieren): http://www.crsr.net/Notes/SSL.html
quelle