Actualicé de Java 1.6 a Java 1.7 hoy. Desde entonces, se produce un error cuando intento establecer una conexión con mi servidor web a través de SSL:
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)
Aquí está el código:
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 solo un proyecto de prueba, por eso permito y uso certificados no confiables con el código:
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);
}
Intenté conectarme con éxito https://google.com . donde es mi culpa
Gracias.
Tuve lo que creo que es el mismo problema. Descubrí que necesitaba ajustar la configuración de Apache para incluir un ServerName o ServerAlias para el host.
Este código falló:
Y este código funcionó:
Wireshark reveló que durante el TSL / SSL Hola, la alerta de advertencia (Nivel: Advertencia, Descripción: Nombre no reconocido), el servidor Hola fue enviado desde el servidor al cliente. Fue solo una advertencia, sin embargo, Java 7.1 respondió inmediatamente con un "Fatal, Descripción: Mensaje inesperado", lo que supongo que significa que las bibliotecas Java SSL no quieren ver la advertencia de un nombre no reconocido.
Del Wiki sobre Seguridad de la capa de transporte (TLS):
112 Advertencia de nombre no reconocido solo TLS; El indicador de nombre del servidor del cliente especificó un nombre de host no admitido por el servidor
Esto me llevó a mirar mis archivos de configuración de Apache y descubrí que si agregaba un ServerName o ServerAlias para el nombre enviado desde el lado del cliente / Java, funcionaba correctamente sin ningún error.
fuente
ServerAlias
trabajado para mí. Había visto la misma alerta de TLS en Wireshark.ServerName
s, Apache responde con una alerta deunrecognized_name
advertencia (que también podría ser una alerta fatal ). RFC 6066 dice precisamente esto sobre este tema: " NO SE RECOMIENDA enviar una alerta de nivel de advertencia no reconocida_nombre (112), porque el comportamiento del cliente en respuesta a las alertas de nivel de advertencia es impredecible ". El único error cometido por este empleado es asumir que se trataba de una alerta fatal . Esto es tanto un error de JRE como uno de Apache.Puede deshabilitar el envío de registros SNI con la propiedad del sistema jsse.enableSNIExtension = false.
Si puede cambiar el código, es útil usarlo
SSLCocketFactory#createSocket()
(sin parámetro de host o con un socket conectado). En este caso, no enviará una indicación de nombre_servidor.fuente
System.setProperty ("jsse.enableSNIExtension", "false");
-Djsse.enableSNIExtension=false
. ¿Pero qué más hace? ¿Es perjudicial para el resto de la seguridad de Javas?También nos encontramos con este error en una nueva compilación del servidor Apache.
La solución en nuestro caso fue definir un
ServerAlias
en elhttpd.conf
que correspondía al nombre de host al que Java intentaba conectarse. NuestroServerName
se configuró con el nombre de host interno. Nuestro certificado SSL estaba usando el nombre de host externo, pero eso no fue suficiente para evitar la advertencia.Para ayudar a depurar, puede usar este comando ssl:
openssl s_client -servername <hostname> -connect <hostname>:443 -state
Si hay un problema con ese nombre de host, imprimirá este mensaje cerca de la parte superior de la salida:
SSL3 alert read: warning:unrecognized name
También debo tener en cuenta que no obtuvimos ese error al usar ese comando para conectarnos al nombre de host interno, aunque no coincidía con el certificado SSL.
fuente
openssl
. Es muy útilSSL3 alert read: warning:unrecognized name
? Veo la alerta impresa, pero el resultado no me ayuda a ver realmente esta diferencia de nombresOpenSSL 1.0.1e-fips 11 Feb 2013
,OpenSSL 1.0.2k-fips 26 Jan 2017
yLibreSSL 2.6.5
.En lugar de confiar en el mecanismo de host virtual predeterminado en apache, puede definir un último host virtual de catchall que use un ServerName arbitrario y un ServerAlias comodín, por ejemplo
De esa forma, puede usar SNI y Apache no enviará la advertencia SSL.
Por supuesto, esto solo funciona si puede describir todos sus dominios fácilmente utilizando una sintaxis comodín.
fuente
*.mydomain.com
sintaxis para ServerAlias. Tenga en cuenta que puede agregar múltiples alias usandoServerAlias
, por ejemploServerAlias *.mydomain.com mydomain.com *.myotherdomain.com
.Debería ser útil. Para volver a intentar un error SNI en Apache HttpClient 4.4, la forma más fácil que se nos ocurrió (ver HTTPCLIENT-1522 ):
y
y
fuente
verifyHostname(sslsock, target)
enSSLConnectionSocketFactory.createLayeredSocket
? Dado quetarget
se cambia a una cadena vacía,verifyHostname
no tendrá éxito. ¿Me estoy perdiendo algo obvio aquí?Utilizar:
fuente
Encontré este problema con spring boot y jvm 1.7 y 1.8. En AWS, no teníamos la opción de cambiar ServerName y ServerAlias para que coincidan (son diferentes), así que hicimos lo siguiente:
En build.gradle agregamos lo siguiente:
Eso nos permitió evitar el problema con el "Nombre no reconocido".
fuente
Lamentablemente, no puede proporcionar propiedades del sistema a la herramienta jarsigner.exe.
He enviado el defecto 7177232 , haciendo referencia al defecto 7127374 de @eckes y explicando por qué se cerró por error.
Mi defecto es específicamente sobre el impacto en la herramienta jarsigner, pero tal vez los lleve a reabrir el otro defecto y abordar el problema correctamente.
ACTUALIZACIÓN: En realidad, resulta que PUEDES suministrar propiedades del sistema a la herramienta Jarsigner, simplemente no está en el mensaje de ayuda. Utilizar
jarsigner -J-Djsse.enableSNIExtension=false
fuente
Llegué al mismo problema y resultó que dns inverso no estaba configurado correctamente, apuntaba a un nombre de host incorrecto para la IP. Después de corregir dns inverso y reiniciar httpd, la advertencia desaparece. (si no corrijo el DNS inverso, agregar ServerName también me ayudó)
fuente
Mi
VirtualHost
'sServerName
fue comentado por defecto. Funcionó después de descomentar.fuente
Si está creando un cliente con Resttemplate, solo puede establecer el punto final de esta manera: https: // IP / path_to_service y establecer requestFactory.
Con esta solución no necesita reiniciar su TOMCAT o Apache:
fuente
También me encontré con este problema al actualizar Java 1.6_29 a 1.7.
De manera alarmante, mi cliente ha descubierto una configuración en el panel de control de Java que resuelve esto.
En la pestaña Avanzado, puede marcar 'Usar el formato ClientHello compatible con SSL 2.0'.
Esto parece resolver el problema.
Estamos utilizando applets de Java en un navegador Internet Explorer.
Espero que esto ayude.
fuente
Tuve el mismo problema con un servidor Ubuntu Linux que ejecutaba subversion cuando se accedía a través de Eclipse.
Se ha demostrado que el problema tenía que ver con una advertencia cuando Apache (re) comenzó:
Esto se debe a una nueva entrada en
ports.conf
, dondeNameVirtualHost
se ingresó otra directiva junto con la directiva ensites-enabled/000-default
.Después de eliminar la directiva
ports.conf
, el problema había desaparecido (después de reiniciar Apache, naturalmente)fuente
Solo para agregar una solución aquí. Esto podría ayudar a los usuarios de LAMP
La línea mencionada anteriormente en la configuración del host virtual fue la culpable.
Configuración de host virtual cuando error
Configuración de trabajo
fuente
Aquí hay una solución para Appache httpclient 4.5.11. Tuve un problema con el certificado que tiene el tema comodín
*.hostname.com
. Me devolvió la misma excepción, pero no debo usar la desactivación por propiedadSystem.setProperty("jsse.enableSNIExtension", "false");
porque cometió un error en el cliente de ubicación de Google.Encontré una solución simple (solo modificando el socket):
fuente
Hay una manera más fácil en la que puede usar su propio HostnameVerifier para confiar implícitamente en ciertas conexiones. El problema viene con Java 1.7, donde se han agregado extensiones SNI y su error se debe a una configuración incorrecta del servidor.
Puede usar "-Djsse.enableSNIExtension = false" para deshabilitar SNI en toda la JVM o leer mi blog donde le explico cómo implementar un verificador personalizado en la parte superior de una conexión URL.
fuente