cacerts java ssl

cacerts - Alerta de protocolo de enlace SSL: error de nombre no reconocido desde la actualización a Java 1.7.0



add certificate to cacerts java (16)

Actualicé de Java 1.6 a Java 1.7 hoy. Desde entonces, se produce un error cuando intento establecer una conexión a 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 a https://google.com . donde es mi culpa

Gracias.


Debería ser útil. Para volver a intentarlo en un error de SNI en Apache HttpClient 4.4, la forma más fácil de HTTPCLIENT-1522 (ver 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; } } } }

y

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); } }

y

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


Desafortunadamente, no puede proporcionar las propiedades del sistema a la herramienta jarsigner.exe.

He enviado el defecto 7177232 , 7177232 referencia al defecto de bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374 y explicando por qué se cerró por error.

Mi defecto tiene que ver específicamente con 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 PUEDE suministrar propiedades del sistema a la herramienta Jarsigner, simplemente no está en el mensaje de ayuda. Utilice jarsigner -J-Djsse.enableSNIExtension=false


El nombre del VirtualHost mi VirtualHost fue comentado por defecto. Funcionó después de descomentar.


En lugar de confiar en el mecanismo de host virtual predeterminado en apache, puede definir un último host virtual global que use un ServerName arbitrario y un comodín ServerAlias, por ejemplo

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

De esa manera puede usar SNI y Apache no enviará de vuelta la advertencia de SSL.

Por supuesto, esto solo funciona si puede describir todos sus dominios fácilmente con una sintaxis de comodín.


Encontré el mismo problema y resultó que el DNS inverso no estaba configurado correctamente, apuntaba a un nombre de host incorrecto para la IP. Después de corregir el dns inverso y reiniciar httpd, la advertencia desaparece. (Si no corrijo dns inversos, agregar ServerName hizo el truco también para mí)


Hay una forma más sencilla de utilizar su propio HostnameVerifier para confiar de manera implícita en ciertas conexiones. El problema viene con Java 1.7, donde se agregaron extensiones SNI y su error se debe a una configuración incorrecta del servidor.

Puede usar "-Djsse.enableSNIExtension = false" para deshabilitar el SNI en toda la JVM o leer mi blog donde explico cómo implementar un verificador personalizado en la parte superior de una conexión URL.


Java 7 introdujo el soporte de SNI que está habilitado de forma predeterminada. Me he enterado de que ciertos servidores mal configurados envían una advertencia de "Nombre no reconocido" en el protocolo de enlace SSL que la mayoría de los clientes ignoran ... excepto Java. Como mencionó @Bob Kerns , los ingenieros de Oracle se niegan a "arreglar" este error / característica.

Como solución alternativa, sugieren establecer la propiedad jsse.enableSNIExtension . Para permitir que sus programas funcionen sin volver a compilar, ejecute su aplicación como:

java -Djsse.enableSNIExtension=false yourClass

La propiedad también puede establecerse en el código Java, pero debe establecerse antes de cualquier acción SSL . Una vez que la biblioteca de SSL se haya cargado, puede cambiar la propiedad, pero no tendrá ningún efecto en el estado de SNI . Para deshabilitar SNI en tiempo de ejecución (con las limitaciones mencionadas anteriormente), use:

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

La desventaja de establecer este indicador es que SNI está deshabilitado en todas partes de la aplicación. Para utilizar SNI y seguir admitiendo servidores mal configurados:

  1. Cree un SSLSocket con el nombre de host al que desea conectarse. Llamemos a este sslsock .
  2. Intente ejecutar sslsock.startHandshake() . Esto bloqueará hasta que se haga o lanzará una excepción en caso de error. Cuando startHandshake() un error en startHandshake() , obtenga el mensaje de excepción. Si es igual a una handshake alert: unrecognized_name de handshake alert: unrecognized_name , entonces ha encontrado un servidor mal configurado.
  3. Cuando haya recibido la advertencia de nombre unrecognized_name (fatal en Java), SSLSocket intentar abrir un SSLSocket , pero esta vez sin un nombre de host. Esto efectivamente desactiva SNI (después de todo, la extensión de SNI se trata de agregar un nombre de host al mensaje de ClientHello).

Para el proxy SSL de Webscarab, este compromiso implementa la configuración alternativa.


Puede deshabilitar el envío de registros SNI con la propiedad del sistema jsse.enableSNIExtension = false.

Si puede cambiar el código, es SSLCocketFactory#createSocket() usar SSLCocketFactory#createSocket() (sin parámetro de host o con un socket conectado). En este caso no enviará una indicación de nombre de servidor.


Sólo para agregar una solución aquí. Esto podría ayudar a los usuarios de LAMP

Options +FollowSymLinks -SymLinksIfOwnerMatch

La línea mencionada anteriormente en la configuración del host virtual fue la culpable.

Configuración de host virtual cuando error

<VirtualHost *:80> DocumentRoot /var/www/html/load/web ServerName dev.load.com <Directory "/var/www/html/load/web"> Options +FollowSymLinks -SymLinksIfOwnerMatch AllowOverride All Require all granted Order Allow,Deny Allow from All </Directory> RewriteEngine on RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L] </VirtualHost>

Configuración de trabajo

<VirtualHost *:80> DocumentRoot /var/www/html/load/web ServerName dev.load.com <Directory "/var/www/html/load/web"> AllowOverride All Options All Order Allow,Deny Allow from All </Directory> # To allow authorization header RewriteEngine On RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] # RewriteCond %{SERVER_PORT} !^443$ # RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L] </VirtualHost>


Se encontró con 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:

System.setProperty("jsse.enableSNIExtension", "false") bootRun.systemProperties = System.properties

Eso nos permitió evitar el problema con el "Nombre no reconocido".


Si está creando un cliente con Resttemplate, solo puede establecer el punto final de esta manera: https: // IP / path_to_service y establecer el requestFactory.
Con esta solución no necesita REINICIAR su TOMCAT o Apache:

public static HttpComponentsClientHttpRequestFactory requestFactory(CloseableHttpClient httpClient) { TrustStrategy acceptingTrustStrategy = new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }; SSLContext sslContext = null; try { sslContext = org.apache.http.ssl.SSLContexts.custom() .loadTrustMaterial(null, acceptingTrustStrategy) .build(); } catch (Exception e) { logger.error(e.getMessage(), e); } HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; final SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,hostnameVerifier); final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", new PlainConnectionSocketFactory()) .register("https", csf) .build(); final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry); cm.setMaxTotal(100); httpClient = HttpClients.custom() .setSSLSocketFactory(csf) .setConnectionManager(cm) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); return requestFactory; }


También me he encontrado con este problema al actualizar de 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 formato ClientHello compatible con SSL 2.0''.

Esto parece resolver el problema.

Estamos utilizando applets de Java en un navegador de Internet Explorer.

Espero que esto ayude.


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 el httpd.conf que correspondía al nombre de host al que Java intentaba conectarse. Nuestro nombre de ServerName se estableció en 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 cuando usamos ese comando para conectarnos con el nombre del host interno, a pesar de que no coincidía con el certificado SSL.


Tenía 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ó:

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(); } }

Y este código funcionó:

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 reveló que durante la alerta de advertencia (nivel: advertencia, descripción: nombre no reconocido) de TSL / SSL Hello, el servidor Hello se estaba enviando desde el servidor al cliente. Sin embargo, solo fue una advertencia. Java 7.1 respondió inmediatamente con un "Mensaje fatal, Descripción: Mensaje inesperado", que supongo significa que a las bibliotecas SSL de Java no les gusta ver la advertencia de un nombre desconocido.

Desde la Wiki sobre Seguridad de la capa de transporte (TLS):

112 Advertencia de nombre no reconocido TLS solamente; 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 agregué ServerName o ServerAlias ​​para el nombre enviado desde el lado del cliente / java, funcionó correctamente sin ningún error.

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


Tuve el mismo problema con un servidor Ubuntu Linux ejecutando 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ó:

[Mon Jun 30 22:27:10 2014] [warn] NameVirtualHost *:80 has no VirtualHosts ... waiting [Mon Jun 30 22:27:11 2014] [warn] NameVirtualHost *:80 has no VirtualHosts

Esto se debe a una nueva entrada en ports.conf , donde se ingresó otra directiva NameVirtualHost junto con la directiva en sites-enabled/000-default .

Después de eliminar la directiva en ports.conf , el problema desapareció (después de reiniciar Apache, naturalmente)


Utilizar:

  • System.setProperty ("jsse.enableSNIExtension", "false");
  • Reinicie su Tomcat (importante)