Extended server_name (SNI Extension) not sent with jdk1.8.0 but send with jdk1.7.0

23,890

Solution 1

As mentioned, the cause is related to the JDK bug where using setHostnameVerifier() breaks SNI (Extension server_name). https://bugs.openjdk.java.net/browse/JDK-8144566

Our workaround: After testing we found that setting a connection's SSLSocketFactory to just about anything from the default seems to fix the issue.

This does not work: HttpsURLConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());

This does work: HttpsURLConnection.setSSLSocketFactory(new SSLSocketFactoryFacade());

So, to fix it for a JAX-WS client, you could do something like this: bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", new SSLSocketFactoryFacade());

Our SSLSocketFactory facade: (Note that it really doesn't do anything)

public class SSLSocketFactoryFacade extends SSLSocketFactory {

    SSLSocketFactory sslsf;

    public SSLSocketFactoryFacade() {
        sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return sslsf.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return sslsf.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
        return sslsf.createSocket(socket, s, i, b);
    }

    @Override
    public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
        return sslsf.createSocket(s, i);
    }

    @Override
    public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {
        return sslsf.createSocket(s, i, inetAddress, i1);
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
        return createSocket(inetAddress, i);
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
        return createSocket(inetAddress, i, inetAddress1, i1);
    }
}

Solution 2

Please use JDK version 8u141 and above where this issue has been fixed. Please review the JDK 8u141 Bugs Fixes page for more details

Solution 3

You, or the underlying libs (the WS lib does it) might be using setHostnameVerifier(..)

There is a bug in java8, where if setHostnameVerifier(..) is used the SNI is not done from the client side.

https://bugs.openjdk.java.net/browse/JDK-8072464

Share:
23,890

Related videos on Youtube

hints4dev
Author by

hints4dev

Updated on July 09, 2022

Comments

  • hints4dev
    hints4dev almost 2 years

    I have implemented a JAX-WS client by using ApacheCXF (v3.0.4) and everything works successfully but the problem comes when I want to use a secure connection (SSL/TLS) with java 8 (jdk1.8.0_25).

    I see the following exception in log (-Djavax.net.debug=all):

    main, handling exception: java.net.SocketException: Connection reset
    main, SEND TLSv1.2 ALERT:  fatal, description =    unexpected_message
    main, WRITE: TLSv1.2 Alert, length = 2
    main, Exception sending alert: java.net.SocketException: Connection reset by peer: socket write error
    

    After a depeer analysis I have observed the problem is caused because the with Java 8 the server_name (SNI) is not sent but with Java 7 it is sent and the web service invocation works successfully.

    Java 8 log (-Djavax.net.debug=all): Missing "Extension server_name"

    [...]
    Compression Methods:  { 0 }
    Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
    Extension ec_point_formats, formats: [uncompressed]
    Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
    ***
    [...]
    

    Java 7 log (-Djavax.net.debug=all) (works): "Extension server_name" is set

    [...]
    Compression Methods:  { 0 }
    Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
    Extension ec_point_formats, formats: [uncompressed]
    Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
    Extension server_name, server_name: [host_name: testeo.hostname.es]
    ***
    [...]
    

    It is observed that with Java 7 the Extension server_name, server_name: [host_name: testeo.hostname.es] is set and then the web service invocation works successfully.

    Why didn't Java 8 set the server_name as Java 7 did? Is it a Java configuration issue?

  • chrisinmtown
    chrisinmtown over 7 years
    Please explain what's a bindingProvider and/or add code to demonstrate. I would like to use your solution in trying to fix this bug in an existing system.
  • Whome
    Whome over 7 years
    This facade class trick fixed my application in JDK8 along with the customized HostnameVerifier. Without a facade trick I was not able to use a custom verifier.
  • Yuriy
    Yuriy about 7 years
    I had exception: "BuilderException: unable to find valid certification path to requested target" every time I restarted PC and started Tomcat with the client application. After restarting Tomcat everything worked. After looking into the logs I found out that for some reason the Extension server_name was not present in the ClientHello during first run. The custom SSLSocketFactoryFacade fixed the issue. BTW Lombok's @Delegate annotation will make the class super small.
  • lrxw
    lrxw almost 7 years
    Can you explain how this solves the problem? if the facade doesn't do anything, is there something, that relies on the class name?