SSL-Handshake-Warnung: Unrecognized_name-Fehler seit dem Upgrade auf Java 1.7.0

Lesezeit: 9 Minuten

SSL Handshake Warnung Unrecognized name Fehler seit dem Upgrade auf Java 170
pvomhoff

Ich habe heute von Java 1.6 auf Java 1.7 aktualisiert. Seitdem tritt ein Fehler auf, wenn ich versuche, eine Verbindung zu meinem Webserver über SSL herzustellen:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
    at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1288)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1904)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1027)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1035)

Hier ist der Code:

SAXBuilder builder = new SAXBuilder();
Document document = null;

try {
    url = new URL(https://some url);
    document = (Document) builder.build(url.openStream());
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(DownloadLoadiciousComputer.class.getName()).log(Level.SEVERE, null, ex);  
}

Es ist nur ein Testprojekt, deshalb erlaube und verwende ich nicht vertrauenswürdige Zertifikate mit dem Code:

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

try {

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {

    Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, e);
} 

Ich habe erfolgreich versucht, eine Verbindung herzustellen https://google.com. Wo ist meine Schuld?

Danke.

1646251030 708 SSL Handshake Warnung Unrecognized name Fehler seit dem Upgrade auf Java 170
Lekenstein

Java 7 hat die SNI-Unterstützung eingeführt, die standardmäßig aktiviert ist. Ich habe herausgefunden, dass bestimmte falsch konfigurierte Server im SSL-Handshake eine Warnung “Unrecognized Name” senden, die von den meisten Clients ignoriert wird … mit Ausnahme von Java. Wie @Bob Kerns erwähnte, weigern sich die Oracle-Ingenieure, diesen Fehler/diese Funktion zu „beheben“.

Als Problemumgehung schlagen sie vor, die jsse.enableSNIExtension Eigentum. Damit Ihre Programme ohne Neukompilierung funktionieren, führen Sie Ihre App wie folgt aus:

java -Djsse.enableSNIExtension=false yourClass

Die Eigenschaft kann auch im Java-Code gesetzt werden, muss aber gesetzt werden vor allen SSL-Aktionen. Nachdem die SSL-Bibliothek geladen wurde, können Sie die Eigenschaft ändern, aber it wird keine Wirkung haben über den SNI-Status. Verwenden Sie zum Deaktivieren von SNI zur Laufzeit (mit den oben genannten Einschränkungen):

System.setProperty("jsse.enableSNIExtension", "false");

Der Nachteil des Setzens dieses Flags besteht darin, dass SNI überall in der Anwendung deaktiviert ist. Um SNI zu nutzen und trotzdem falsch konfigurierte Server zu unterstützen:

  1. Ein … kreieren SSLSocket mit dem Hostnamen, mit dem Sie sich verbinden möchten. Nennen wir das sslsock.
  2. Versuche zu rennen sslsock.startHandshake(). Dies wird blockiert, bis es fertig ist, oder bei einem Fehler eine Ausnahme auslösen. Immer wenn ein Fehler aufgetreten ist startHandshake(), erhalten Sie die Ausnahmemeldung. Wenn es gleich ist handshake alert: unrecognized_namedann haben Sie einen falsch konfigurierten Server gefunden.
  3. Wenn Sie die erhalten haben unrecognized_name Warnung (fatal in Java), versuchen Sie erneut, a zu öffnen SSLSocket, aber diesmal ohne Hostnamen. Dadurch wird SNI effektiv deaktiviert (schließlich geht es bei der SNI-Erweiterung darum, der ClientHello-Nachricht einen Hostnamen hinzuzufügen).

Für den Webscarab-SSL-Proxy dieses Bekenntnis implementiert das Fallback-Setup.

  • es funktioniert, danke! Beim IntelliJ IDEA Subversion-Client trat derselbe Fehler auf, wenn eine Verbindung über HTTPS hergestellt wurde. Sie müssen nur die Datei idea.exe.vmoptions mit der Zeile aktualisieren: -Djsse.enableSNIExtension=false

    – Dmitri

    20. Juli 2013 um 23:15 Uhr


  • Verwenden Sie für Java-Webstart Folgendes: javaws -J-Djsse.enableSNIExtension=false yourClass

    – Thorsten

    7. Januar 2014 um 10:32 Uhr

  • Ich hatte genau das gleiche Problem mit meinem Jersey-Client mit https-Rest-Server. Es stellte sich heraus, dass ich deinen Trick benutzt habe und es funktioniert hat!! Danke!

    – schahschi15

    24. Januar 2014 um 0:27 Uhr

  • Für diejenigen, die sich über Java 8 wundern, Oracle hat das Verhalten immer noch nicht geändert und fordert den Programmierer immer noch auf, Server abzufangen, die SNI nicht (richtig) unterstützen: docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/…

    – Lekenstein

    1. Juli 2014 um 13:23 Uhr

  • @Blauhirn Wenden Sie sich an Ihren Webhost-Support, er sollte seine Konfiguration korrigieren. Wenn sie Apache verwenden, suchen Sie unten nach einigen Änderungen, die vorgenommen werden müssen.

    – Lekenstein

    8. April 2016 um 16:12 Uhr

Ich hatte, was ich glaube, das gleiche Problem ist. Ich habe festgestellt, dass ich die Apache-Konfiguration anpassen musste, um einen ServerName oder ServerAlias ​​für den Host einzuschließen.

Dieser Code ist fehlgeschlagen:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://mydomain.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

Und dieser Code hat funktioniert:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://google.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

Wireshark enthüllte, dass während des TSL/SSL-Hello die Warnung Alert (Level: Warning, Description: Unrecognized Name), Server Hello vom Server an den Client gesendet wurde. Es war nur eine Warnung, aber Java 7.1 antwortete dann sofort mit einer “Fatal, Description: Unexpected Message”, was meiner Meinung nach bedeutet, dass die Java-SSL-Bibliotheken die Warnung vor einem unbekannten Namen nicht sehen möchten.

Aus dem Wiki zu Transport Layer Security (TLS):

112 Unbekannter Name Warnung Nur TLS; Der Servernamensindikator des Clients hat einen Hostnamen angegeben, der vom Server nicht unterstützt wird

Dies veranlasste mich, mir meine Apache-Konfigurationsdateien anzusehen, und ich stellte fest, dass es ohne Fehler funktionierte, wenn ich einen ServerName oder ServerAlias ​​für den von der Client-/Java-Seite gesendeten Namen hinzufügte.

<VirtualHost mydomain.com:443>
  ServerName mydomain.com
  ServerAlias www.mydomain.com

  • Dies sieht nach einem Fehler in der TLS-Implementierung von Java aus.

    – Paulo Ebermann

    9. November 2011 um 0:18 Uhr

  • Ich habe tatsächlich einen Bug dafür geöffnet. Ich habe diese Nummer zugeteilt bekommen (noch nicht sichtbar): bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374

    – eckes

    5. Januar 2012 um 16:19 Uhr


  • Danke, füge ein hinzu ServerAlias hat bei mir funktioniert. Ich hatte die gleiche TLS-Warnung in Wireshark gesehen.

    – Jared Beck

    4. Dezember 2012 um 2:28 Uhr

  • Das hat bei mir auch funktioniert. (hätte besser funktioniert, wenn ich daran geglaubt und nicht einen anderen Weg gesucht hätte)

    – Endbenutzer

    31. Januar 2013 um 18:34 Uhr

  • @JosephShraibman, zu sagen, der Oracle-Mitarbeiter sei ein Idiot, ist unangemessen. Wenn Sie zwei verwenden ServerNames, Apache antwortet mit einem unrecognized_name Warnung Alarm (das könnte auch ein tödlich Alarm). RFC 6066 sagt genau das zu diesem Thema: “Es wird NICHT EMPFOHLEN, einen unrecognized_name(112)-Alert der Warnstufe zu senden, da das Verhalten des Clients als Reaktion auf Alerts der Warnstufe unvorhersehbar ist.“. Der einzige Fehler, den dieser Mitarbeiter gemacht hat, ist anzunehmen, dass dies ein war tödlich Alarm. Dies ist sowohl ein JRE-Fehler als auch ein Apache-Fehler.

    – Bruno

    24. Februar 2014 um 19:51 Uhr

Sie können das Senden von SNI-Einträgen mit der Systemeigenschaft jsse.enableSNIExtension=false deaktivieren.

Wenn Sie den Code ändern können, hilft es, ihn zu verwenden SSLCocketFactory#createSocket() (ohne Host-Parameter oder mit verbundenem Socket). In diesem Fall sendet er keine server_name-Anzeige.

  • Was so gemacht wird: System.setProperty ("jsse.enableSNIExtension", "false");

    – jn1kk

    9. April 2012 um 18:27 Uhr


  • Ich habe festgestellt, dass das nicht immer funktioniert. Ich weiß nicht, warum es in einigen Fällen funktioniert und in anderen nicht.

    – Joseph Shraibman

    9. Mai 2012 um 21:42 Uhr

  • Funktioniert bei mir mit -Djsse.enableSNIExtension=false. Aber was macht es sonst noch? Ist es schädlich für den Rest der Java-Sicherheit?

    – Ceving

    4. Februar 2013 um 10:33 Uhr

  • Nein, es bedeutet nur, dass einige Websites (insbesondere Webserver), die mehrere Hostnamen hinter einer gemeinsamen IP verwenden, nicht wissen, welches Zertifikat gesendet werden soll. Aber wenn Ihre Java-App keine Verbindung zu Millionen von Websites herstellen muss, benötigen Sie diese Funktion nicht. Wenn Sie auf einen solchen Server stoßen, schlägt Ihre Zertifikatsvalidierung möglicherweise fehl und die Verbindung wird abgebrochen. Es ist also kein Sicherheitsproblem zu erwarten.

    – eckes

    7. Februar 2013 um 23:17 Uhr

Wir sind auch bei einem neuen Apache-Server-Build auf diesen Fehler gestoßen.

Die Lösung in unserem Fall bestand darin, a zu definieren ServerAlias in dem httpd.conf das dem Hostnamen entsprach, zu dem Java versuchte, eine Verbindung herzustellen. Unsere ServerName wurde auf den internen Hostnamen gesetzt. Unser SSL-Zertifikat verwendete den externen Hostnamen, aber das reichte nicht aus, um die Warnung zu vermeiden.

Um beim Debuggen zu helfen, können Sie diesen SSL-Befehl verwenden:

openssl s_client -servername <hostname> -connect <hostname>:443 -state

Wenn es ein Problem mit diesem Hostnamen gibt, wird diese Meldung oben in der Ausgabe ausgegeben:

SSL3 alert read: warning:unrecognized name

Ich sollte auch beachten, dass wir diesen Fehler nicht erhalten haben, als wir diesen Befehl zum Herstellen einer Verbindung mit dem internen Hostnamen verwendet haben, obwohl er nicht mit dem SSL-Zertifikat übereinstimmte.

Anstatt sich auf den Standardmechanismus für virtuelle Hosts in Apache zu verlassen, können Sie einen letzten Catchall-Virtualhost definieren, der einen beliebigen ServerNamen und einen Wildcard-ServerAlias ​​verwendet, z

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com

Auf diese Weise können Sie SNI verwenden und Apache sendet die SSL-Warnung nicht zurück.

Das funktioniert natürlich nur, wenn Sie alle Ihre Domains einfach mit einer Wildcard-Syntax beschreiben können.

  • Soweit ich weiß, sendet Apache diese Warnung nur, wenn der Client einen Namen verwendet, der weder als ServerName noch als ServerAlias ​​konfiguriert ist. Wenn Sie also ein Wildcard-Zertifikat haben, geben Sie entweder alle verwendeten Subdomains an oder verwenden Sie die *.mydomain.com Syntax für ServerAlias. Notiz mit denen Sie mehrere Aliase hinzufügen können ServerAliasz.B ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com.

    – Michael Paesold

    20. April 2016 um 14:21 Uhr


Es sollte nützlich sein. Um einen SNI-Fehler in Apache HttpClient 4.4 erneut zu versuchen – der einfachste Weg, den wir gefunden haben (siehe HTTPCLIENT-1522):

public class SniHttpClientConnectionOperator extends DefaultHttpClientConnectionOperator {

    public SniHttpClientConnectionOperator(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
        super(socketFactoryRegistry, null, null);
    }

    @Override
    public void connect(
            final ManagedHttpClientConnection conn,
            final HttpHost host,
            final InetSocketAddress localAddress,
            final int connectTimeout,
            final SocketConfig socketConfig,
            final HttpContext context) throws IOException {
        try {
            super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
        } catch (SSLProtocolException e) {
            Boolean enableSniValue = (Boolean) context.getAttribute(SniSSLSocketFactory.ENABLE_SNI);
            boolean enableSni = enableSniValue == null || enableSniValue;
            if (enableSni && e.getMessage() != null && e.getMessage().equals("handshake alert:  unrecognized_name")) {
                TimesLoggers.httpworker.warn("Server received saw wrong SNI host, retrying without SNI");
                context.setAttribute(SniSSLSocketFactory.ENABLE_SNI, false);
                super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
            } else {
                throw e;
            }
        }
    }
}

und

public class SniSSLSocketFactory extends SSLConnectionSocketFactory {

    public static final String ENABLE_SNI = "__enable_sni__";

    /*
     * Implement any constructor you need for your particular application -
     * SSLConnectionSocketFactory has many variants
     */
    public SniSSLSocketFactory(final SSLContext sslContext, final HostnameVerifier verifier) {
        super(sslContext, verifier);
    }

    @Override
    public Socket createLayeredSocket(
            final Socket socket,
            final String target,
            final int port,
            final HttpContext context) throws IOException {
        Boolean enableSniValue = (Boolean) context.getAttribute(ENABLE_SNI);
        boolean enableSni = enableSniValue == null || enableSniValue;
        return super.createLayeredSocket(socket, enableSni ? target : "", port, context);
    }
}

und

cm = new PoolingHttpClientConnectionManager(new SniHttpClientConnectionOperator(socketFactoryRegistry), null, -1, TimeUnit.MILLISECONDS);

  • Soweit ich weiß, sendet Apache diese Warnung nur, wenn der Client einen Namen verwendet, der weder als ServerName noch als ServerAlias ​​konfiguriert ist. Wenn Sie also ein Wildcard-Zertifikat haben, geben Sie entweder alle verwendeten Subdomains an oder verwenden Sie die *.mydomain.com Syntax für ServerAlias. Notiz mit denen Sie mehrere Aliase hinzufügen können ServerAliasz.B ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com.

    – Michael Paesold

    20. April 2016 um 14:21 Uhr


SSL Handshake Warnung Unrecognized name Fehler seit dem Upgrade auf Java 170
Tomasz Janisiewicz

Verwenden:

  • System.setProperty(“jsse.enableSNIExtension”, “false”);
  • Starten Sie Ihren Tomcat neu (wichtig)

915590cookie-checkSSL-Handshake-Warnung: Unrecognized_name-Fehler seit dem Upgrade auf Java 1.7.0

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy