Remote host terminated the handshake ошибка

I’m running a local TCP server in C++ on Windows via OpenSSL and Windows sockets. I’m running the client in Java using SSL sockets. For most users this setup is working, however, some users run into the following Java exception upon attempting the SSL handshake:

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at sun.security.ssl.SSLSocketImpl.handleEOF(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.decode(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[?:1.8.0_321]
    ...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.SSLSocketInputRecord.read(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketInputRecord.readHeader(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLTransport.decode(Unknown Source) ~[?:1.8.0_321]
    ... 10 more

My client socket code in Java looks like this:

public static Socket getClientSocket() throws Exception
{
    InetSocketAddress socketAddress = new InetSocketAddress("localhost", 54321);
    SSLSocketFactory socketFactory = getSSLSocketFactory();
    Socket clientSocket = socketFactory.createSocket();
    clientSocket.connect(socketAddress, 1_000);
    ((SSLSocket) clientSocket).startHandshake(); // <-- Exception here for some users
    return clientSocket;
}

private static SSLSocketFactory getSSLSocketFactory() throws Exception
{
    // Create a trust manager that does not validate certificate chains
    X509TrustManager trustManager = new X509TrustManager()
    {
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            // TODO Returning null is not allowed but it still works
            return null;
        }

        @Override
        public void checkClientTrusted(final X509Certificate[] certificates, final String authType)
        {

        }

        @Override
        public void checkServerTrusted(final X509Certificate[] certificates, final String authType)
        {
            for (X509Certificate certificate : certificates)
            {
                String certificateString = certificate.toString();
                if (!certificateString.contains("blablabla"))
                {
                    throw new SSLException("Certificate not trusted");
                }
            }
        }
    };
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
    return sslContext.getSocketFactory();
}

Attempted solutions:

  • Calling System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2") before connecting did not work (reference)
  • I do not want to tell users to import any SSL certificates into their truststore (unless I can automate this easily)

Where does the inconsistent behavior come from and how to fix it cleanly for everyone who gets the exception? I have access to the server source code and certificates. Also any critical questions or suggestions are welcome. I can provide more information if necessary.

Not an answer yet, but too much for a comment. This is clearly not a server cert problem; the symptoms of that are quite different. From your system’s POV, the server appears to be closing during the handshake. There are two possibilities:

The server really is closing, which is a SSL/TLS protocol violation though a fairly minor one; there are quite a few reasons a server might fail to handshake with you but it should send a fatal alert first, which your JSSE or the
weblogic equivalent should indicate. In this case there may well be some useful information in the server log, if you are able (and permitted) to communicate with knowledgeable server admin(s). Or you can try putting a network monitor on your client machine, or one close enough it sees all your traffic; personally I like www.wireshark.org. But this usually shows only that the close came immediately after the ClientHello, which doesn’t narrow it down much. You don’t say if you are supposed to and
have configured a «client cert» (actually key&cert, in the form of a Java privateKeyEntry) for this server; if that is required by the server and not correct, some servers may perceive that as an attack and knowingly violate protocol by closing even though officially they should send an alert.

Or, some middlebox in the network, most often a firewall or purportedly-transparent proxy, is deciding it doesn’t like your connection and forcing a close. The Proxy you use is an
obvious suspect; when you say the «same code» works to other hosts, confirm if you mean through the same proxy (not just a proxy) and using HTTPS (not clear HTTP). If that isn’t so, try testing to other hosts with HTTPS through the proxy (you needn’t send a full SOAP request, just a GET / if enough). If you can, try connecting without the proxy, or possibly a different proxy, and connecting HTTP (not S) through the proxy to the host (if both support clear) and see if those work.

If
you don’t mind publishing the actual host (but definitely not any authentication credentials) others can try it. Or you can go to www.ssllabs.com and request they test the server (without publishing the results); this will try several common variations on SSL/TLS connection and report any errors it sees, as well as any security weaknesses.

With Java 11, I can’t connect to an LDAPS server using Jenkins LTS v2.164.3.

It works correctly with Java 8.

I tried with Java 11.0.3 and Java 11.0.4 (Azul JDK for Alpine).

I don’t know if the bug is directly related to Jenkins or if an upstream component is involved.

The only workaround I found it’s to disable TLS1.2 and TLS1.3 (-Djdk.tls.client.protocols=TLSv1.1,TLSv1 -Dhttps.protocols=TLSv1.1,TLSv1).

Unable to connect to ldaps:java.io.EOFException: SSL peer shut down incorrectly
 at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:167)
 at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)
 at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
Caused: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
 at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1322)
 at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1160)
 at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
 at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
 at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:716)
 at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:970)
 at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
 at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
 at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:398)
 at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:371)
 at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
 at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:192)
Caused: javax.naming.CommunicationException: anonymous bind failed: myserver.com:636 [Root exception is javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake]
 at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:198)
 at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2795)
 at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:320)
 at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
 at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
 at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
 at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
 at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
 at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
 at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
 at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
 at java.naming/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
 at jenkins.security.plugins.ldap.LDAPConfiguration$LDAPConfigurationDescriptor.doCheckServer(LDAPConfiguration.java:400)
 at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710)
 at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:396)
 at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:408)
 at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:212)
 at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:145)
 at org.kohsuke.stapler.MetaClass$11.doDispatch(MetaClass.java:537)
 at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
 at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:739)
 at org.kohsuke.stapler.Stapler.invoke(Stapler.java:870)
 at org.kohsuke.stapler.MetaClass$4.doDispatch(MetaClass.java:282)
 at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
 at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:739)
 at org.kohsuke.stapler.Stapler.invoke(Stapler.java:870)
 at org.kohsuke.stapler.Stapler.invoke(Stapler.java:668)
 at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
 at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1655)
 at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
 at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
 at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
 at net.bull.javamelody.PluginMonitoringFilter.doFilter(PluginMonitoringFilter.java:88)
 at org.jvnet.hudson.plugins.monitoring.HudsonMonitoringFilter.doFilter(HudsonMonitoringFilter.java:114)
 at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:151)
 at jenkins.metrics.impl.MetricsFilter.doFilter(MetricsFilter.java:125)
 at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:151)
 at hudson.plugins.audit_trail.AuditTrailFilter.doFilter(AuditTrailFilter.java:92)
 at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:151)
 at jenkins.telemetry.impl.UserLanguages$AcceptLanguageFilter.doFilter(UserLanguages.java:128)
 at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:151)
 at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:157)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:64)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
 at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:90)
 at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:82)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
 at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
 at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
 at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
 at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
 at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
 at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
 at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
 at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
 at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
 at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
 at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
 at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
 at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
 at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
 at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
 at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
 at org.eclipse.jetty.server.Server.handle(Server.java:503)
 at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
 at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
 at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
 at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
 at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
 at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
 at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
 at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
 at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
 at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
 at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
 at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
 at java.base/java.lang.Thread.run(Thread.java:834)
Running from: /opt/deploy-box/jenkins/ear/jenkins.war
webroot: System.getProperty("JENKINS_HOME")
Jul 22, 2019 3:40:17 PM org.eclipse.jetty.util.log.Log initialized
INFO: Logging initialized @1194ms to org.eclipse.jetty.util.log.JavaUtilLog
Jul 22, 2019 3:40:17 PM winstone.Logger logInternal
INFO: Beginning extraction from war file
Jul 22, 2019 3:40:23 PM org.eclipse.jetty.server.handler.ContextHandler setContextPath
WARNING: Empty contextPath
Jul 22, 2019 3:40:23 PM org.eclipse.jetty.server.Server doStart
INFO: jetty-9.4.z-SNAPSHOT; built: 2018-08-30T13:59:14.071Z; git: 27208684755d94a92186989f695db2d7b21ebc51; jvm 11.0.4+11-LTS
Jul 22, 2019 3:40:24 PM org.eclipse.jetty.webapp.StandardDescriptorProcessor visitServlet
INFO: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
Jul 22, 2019 3:40:25 PM org.eclipse.jetty.server.session.DefaultSessionIdManager doStart
INFO: DefaultSessionIdManager workerName=node0
Jul 22, 2019 3:40:25 PM org.eclipse.jetty.server.session.DefaultSessionIdManager doStart
INFO: No SessionScavenger set, using defaults
Jul 22, 2019 3:40:25 PM org.eclipse.jetty.server.session.HouseKeeper startScavenging
INFO: node0 Scavenging every 660000ms
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file:/opt/deploy-box/jenkins/war/WEB-INF/lib/xstream-1.4.7-jenkins-1.jar) to field java.util.TreeMap.comparator
WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Jenkins home directory: /opt/deploy-box/jenkins found at: SystemProperties.getProperty("JENKINS_HOME")
Jul 22, 2019 3:40:26 PM org.eclipse.jetty.server.handler.ContextHandler doStart
INFO: Started w.@713064e8{Jenkins v2.164.3,/,file:Jul 22, 2019 3:40:26 PM org.eclipse.jetty.server.AbstractConnector doStart
INFO: Started ServerConnector@6ae3fb94{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
Jul 22, 2019 3:40:26 PM org.eclipse.jetty.server.Server doStart
INFO: Started @10315ms
Jul 22, 2019 3:40:26 PM winstone.Logger logInternal
INFO: Winstone Servlet Engine v4.0 running: controlPort=disabled
Jul 22, 2019 3:40:27 PM jenkins.security.ClassFilterImpl register
WARNING: All class filtering suppressed. Your Jenkins installation is at risk from known attacks. See https:Jul 22, 2019 3:40:27 PM jenkins.InitReactorRunner$1 onAttained
INFO: Started initialization
Jul 22, 2019 3:40:35 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/built-on-column/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:36 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/countjobs-viewstabbar/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:37 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/discard-old-build/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:38 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/dynamicparameter/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:40 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/flexible-publish/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:41 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/gradle/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:43 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/ivy/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:45 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/job-dsl/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:49 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/page-markup/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:49 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/permissive-script-security/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:49 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/pipeline-aggregator-view/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:51 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/postbuild-task/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:53 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/slave-setup/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:54 PM hudson.ClassicPluginStrategy createClassJarFromWebInfClasses
WARNING: Created /opt/deploy-box/jenkins/plugins/text-finder/WEB-INF/lib/classes.jar; update plugin to a version created with a newer harness
Jul 22, 2019 3:40:58 PM jenkins.InitReactorRunner$1 onAttained
INFO: Listed all plugins
Jul 22, 2019 3:40:59 PM hudson.plugins.ansicolor.PluginImpl start
INFO: AnsiColor: eliminating boring output (https:Jul 22, 2019 3:40:59 PM org.jenkinsci.plugins.scriptler.ScriptlerPluginImpl synchronizeConfig
INFO: initialize scriptler
Jul 22, 2019 3:41:14 PM org.jenkinsci.remoting.util.AnonymousClassWarnings warn
WARNING: Attempt to (de-)serialize anonymous class hudson.plugins.disk_usage.DiskUsageProjectActionFactory$DescriptorImpl$1 in file:/opt/deploy-box/jenkins/plugins/disk-usage/WEB-INF/lib/disk-usage.jar; see: https:Jul 22, 2019 3:41:14 PM org.jenkinsci.remoting.util.AnonymousClassWarnings warn
WARNING: Attempt to (de-)serialize anonymous class hudson.plugins.disk_usage.DiskUsageOvearallGraphGenerator$DiskUsageRecord$1 in file:/opt/deploy-box/jenkins/plugins/disk-usage/WEB-INF/lib/disk-usage.jar; see: https:Jul 22, 2019 3:41:15 PM jenkins.InitReactorRunner$1 onAttained
INFO: Prepared all plugins
Jul 22, 2019 3:41:15 PM jenkins.InitReactorRunner$1 onAttained
INFO: Started all plugins
Jul 22, 2019 3:41:20 PM jenkins.InitReactorRunner$1 onAttained
INFO: Augmented all extensions
Jul 22, 2019 3:41:20 PM hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1 error
WARNING: Failed to instantiate Key[type=jenkins.metrics.impl.VMMetricProviderImpl, annotation=[none]]; skipping this component
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.reflect.InaccessibleObjectException: Unable to make public long com.sun.management.internal.OperatingSystemImpl.getProcessCpuTime() accessible: module jdk.management does not "opens com.sun.management.internal" to unnamed module @62dbb0e9
 at jenkins.metrics.impl.VMMetricProviderImpl.<init>(VMMetricProviderImpl.java:61)
1 error
 at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:52)
 at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
 at hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1.get(ExtensionFinder.java:440)
 at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
 at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)
 at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
 at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)
 at hudson.ExtensionFinder$GuiceFinder._find(ExtensionFinder.java:402)
 at hudson.ExtensionFinder$GuiceFinder.find(ExtensionFinder.java:393)
 at hudson.ClassicPluginStrategy.findComponents(ClassicPluginStrategy.java:335)
 at hudson.ExtensionList.load(ExtensionList.java:380)
 at hudson.ExtensionList.ensureLoaded(ExtensionList.java:318)
 at hudson.ExtensionList.iterator(ExtensionList.java:172)
 at jenkins.metrics.api.Metrics.afterExtensionsAugmented(Metrics.java:335)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.base/java.lang.reflect.Method.invoke(Method.java:566)
 at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:104)
 at hudson.init.TaskMethodFinder$TaskImpl.run(TaskMethodFinder.java:175)
 at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
 at jenkins.model.Jenkins$5.runTask(Jenkins.java:1096)
 at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
 at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
 at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make public long com.sun.management.internal.OperatingSystemImpl.getProcessCpuTime() accessible: module jdk.management does not "opens com.sun.management.internal" to unnamed module @62dbb0e9
 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:340)
 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:280)
 at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:198)
 at java.base/java.lang.reflect.Method.setAccessible(Method.java:192)
 at jenkins.metrics.impl.VMMetricProviderImpl$CpuUsageGauge.<init>(VMMetricProviderImpl.java:226)
 at jenkins.metrics.impl.VMMetricProviderImpl.<init>(VMMetricProviderImpl.java:71)
 at jenkins.metrics.impl.VMMetricProviderImpl$$FastClassByGuice$$bd4f8b03.newInstance(<generated>)
 at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
 at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61)
 at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:105)
 at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)
 at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:89)
 at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)
 at hudson.ExtensionFinder$GuiceFinder$SezpozModule.onProvision(ExtensionFinder.java:567)
 at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:126)
 at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)
 at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:87)
 at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
 at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
 at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
 at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
 ... 26 more
Jul 22, 2019 3:41:21 PM jenkins.model.Jenkins setBuildsAndWorkspacesDir
INFO: Using non default workspaces directories: ${JENKINS_HOME}/workspace/${ITEM_FULLNAME}.
Jul 22, 2019 3:41:22 PM jenkins.InitReactorRunner$1 onAttained
INFO: Loaded all jobs
Jul 22, 2019 3:41:22 PM hudson.model.AsyncPeriodicWork$1 run
INFO: Started Download metadata
Jul 22, 2019 3:41:22 PM jenkins.util.groovy.GroovyHookScript execute
INFO: Executing /opt/deploy-box/jenkins/init.groovy.d/approve_scripts.groovy
Jul 22, 2019 3:41:22 PM hudson.model.AllView migrateLegacyPrimaryAllViewLocalizedName
INFO: JENKINS-38606 detected for AllView in hudson.model.Hudson@4ac99ffa; renaming view from All to all
Jul 22, 2019 3:41:22 PM jenkins.install.UpgradeWizard applyForcedChanges
INFO: New API token system configured with insecure options to keep legacy behavior
Jul 22, 2019 3:41:22 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
Jul 22, 2019 3:41:22 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.tasks.Ant.AntInstaller
Jul 22, 2019 3:41:23 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.plugins.gradle.GradleInstaller
Jul 22, 2019 3:41:23 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.plugins.groovy.GroovyInstaller
Jul 22, 2019 3:41:24 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for hudson.tools.JDKInstaller
Jul 22, 2019 3:41:24 PM hudson.model.DownloadService$Downloadable load
INFO: Obtained the updated data file for org.jenkinsci.plugins.scriptler.CentralScriptJsonCatalog
Jul 22, 2019 3:41:24 PM hudson.model.AsyncPeriodicWork$1 run
INFO: Finished Download metadata. 2,309 ms
Script Approval approve all
Set permissive-script-security.enabled=true and set level log for this plugin
Jul 22, 2019 3:41:24 PM jenkins.util.groovy.GroovyHookScript execute
INFO: Executing /opt/deploy-box/jenkins/init.groovy.d/set_global_variables.groovy
Jul 22, 2019 3:41:25 PM jenkins.InitReactorRunner$1 onAttained
INFO: Completed initialization
Jul 22, 2019 3:41:25 PM jenkins.plugins.mattermost.MattermostNotifier$Migrator onLoaded
INFO: Starting Settings Migration Process
Jul 22, 2019 3:41:25 PM hudson.WebAppMain$3 run
INFO: Jenkins is fully up and running
Jul 22, 2019 3:41:32 PM hudson.model.AsyncAperiodicWork$1 run
INFO: Started Update IdP Metadata from URL PeriodicWork
Jul 22, 2019 3:41:32 PM hudson.model.AsyncAperiodicWork$1 run
INFO: Finished Update IdP Metadata from URL PeriodicWork. 3 ms
javax.net.ssl|DEBUG|12|Handling GET / from 10.255.0.2 : qtp1256440269-18 View/index.jelly AdministrativeMonitorsDecorator/footer.jelly|2019-07-22 15:42:52.244 CEST|SSLCipher.java:437|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472
javax.net.ssl|WARNING|6A|Thread-22|2019-07-22 15:44:05.793 CEST|SignatureScheme.java:282|Signature algorithm, ed25519, is not supported by the underlying providers
javax.net.ssl|WARNING|6A|Thread-22|2019-07-22 15:44:05.794 CEST|SignatureScheme.java:282|Signature algorithm, ed448, is not supported by the underlying providers
javax.net.ssl|INFO|6A|Thread-22|2019-07-22 15:44:05.800 CEST|AlpnExtension.java:161|No available application protocols
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.800 CEST|SSLExtensions.java:257|Ignore, context unavailable extension: application_layer_protocol_negotiation
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.801 CEST|SSLExtensions.java:257|Ignore, context unavailable extension: cookie
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.827 CEST|SSLExtensions.java:257|Ignore, context unavailable extension: renegotiation_info
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.827 CEST|PreSharedKeyExtension.java:633|No session to resume.
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.827 CEST|SSLExtensions.java:257|Ignore, context unavailable extension: pre_shared_key
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.831 CEST|ClientHello.java:653|Produced ClientHello handshake message (
"ClientHello": {
 "client version" : "TLSv1.2",
 "random" : "5C 46 C8 E6 96 5A 9E DD E6 2A 17 06 8D A3 1E 36 48 22 51 6A 86 E8 28 D9 04 5B A7 69 77 91 52 8C",
 "session id" : "04 1E 46 4F 3E EF 62 E6 76 B8 1D A4 CA C1 37 F9 43 09 66 D8 90 8F 84 96 AE FF B5 BA F4 4D E3 22",
 "cipher suites" : "[TLS_AES_128_GCM_SHA256(0x1301), TLS_AES_256_GCM_SHA384(0x1302), TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xC02B), TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(0xC02E), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(0xC032), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(0xC02D), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(0xC031), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(0xC024), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(0xC028), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(0xC026), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(0xC02A), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xC00A), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xC014), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(0xC005), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(0xC00F), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(0xC023), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(0xC027), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(0xC025), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(0xC029), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xC009), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xC013), TLS_RSA_WITH_AES_128_CBC_SHA(0x002F), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(0xC004), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(0xC00E), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032), TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",
 "compression methods" : "00",
 "extensions" : [
 "status_request (5)": {
 "certificate status type": ocsp
 "OCSP status request": {
 "responder_id": <empty>
 "request extensions": {
 <empty>
 }
 }
 },
 "supported_groups (10)": {
 "versions": [secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1, ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144, ffdhe8192]
 },
 "ec_point_formats (11)": {
 "formats": [uncompressed]
 },
 "signature_algorithms (13)": {
 "signature schemes": [ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_secp512r1_sha512, rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, ecdsa_sha224, rsa_sha224, dsa_sha224, ecdsa_sha1, rsa_pkcs1_sha1, dsa_sha1]
 },
 "signature_algorithms_cert (50)": {
 "signature schemes": [ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_secp512r1_sha512, rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, ecdsa_sha224, rsa_sha224, dsa_sha224, ecdsa_sha1, rsa_pkcs1_sha1, dsa_sha1]
 },
 "status_request_v2 (17)": {
 "cert status request": {
 "certificate status type": ocsp_multi
 "OCSP status request": {
 "responder_id": <empty>
 "request extensions": {
 <empty>
 }
 }
 }
 },
 "extended_master_secret (23)": {
 <empty>
 },
 "supported_versions (43)": {
 "versions": [TLSv1.3, TLSv1.2, TLSv1.1, TLSv1]
 },
 "psk_key_exchange_modes (45)": {
 "ke_modes": [psk_dhe_ke]
 },
 "key_share (51)": {
 "client_shares": [
 {
 "named group": secp256r1
 "key_exchange": {
 0000: 04 83 84 8A F6 9C 23 D6 E0 D7 04 F6 AB 5E EA 3A ......#......^.:
 0010: 4A F5 68 3A EF 01 1B D1 C8 4C 98 E2 FE 38 91 3A J.h:.....L...8.:
 0020: FB 35 61 9D 0A 8B F9 6D A5 78 52 77 26 A6 4D A1 .5a....m.xRw&.M.
 0030: F8 1A 8F C8 68 0E 18 FF B1 AC 4B 5F A6 DD A7 73 ....h.....K_...s
 0040: 4E
 }
 },
 ]
 }
 ]
}
)
javax.net.ssl|ERROR|6A|Thread-22|2019-07-22 15:44:05.836 CEST|TransportContext.java:312|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
 javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
 at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1322)
 at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1160)
 at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
 at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
 at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:716)
 at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:799)
 at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
 at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:292)
 at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
 at java.naming/com.sun.jndi.ldap.Connection.run(Connection.java:832)
 at java.base/java.lang.Thread.run(Thread.java:834)
 Caused by: java.io.EOFException: SSL peer shut down incorrectly
 at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:167)
 at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)
 at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
 ... 9 more}
)
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.837 CEST|SSLSocketImpl.java:1362|close the underlying socket
javax.net.ssl|DEBUG|6A|Thread-22|2019-07-22 15:44:05.837 CEST|SSLSocketImpl.java:1381|close the SSL connection (initiative)

#java #rest #ssl #jersey #jersey-client

#java #rest #ssl #джерси #джерси-клиент

Вопрос:

Я использую Jersey-client-2.27, через который вызывается вызов https get, как показано ниже:

 Client client = ClientBuilder.newClient();

return client.target(url)
        .request(MediaType.APPLICATION_JSON)
        .header("authorization", token)
        .get(String.class);
  

Получение исключения ниже один раз при каждых 10-15 обращениях к методу клиента get():

 "status":500,
"reason":"Internal Server Error",
"code":0,
"message":

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:284)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:767)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:765)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:428)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:324)
  

Что может быть причиной частого сбоя вызова API, особенно во время нагрузочного тестирования, и как я могу это устранить? Я уже пробовал игнорировать SSL-сертификат и добавлять сертификат x509 при отправке запроса

Комментарии:

1. Не похоже, что ваш клиент делает что-то не так. Вам нужно будет просмотреть журналы на сервере, чтобы выяснить, почему он прерывает соединение.

2. Я не видел никаких ошибок в журналах сервера. Похоже, что сам клиент потерпел неудачу при общении.

If you are working with Docker containers and facing the error javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake, don’t worry! This article will guide you through the steps to fix this error.

Understanding the Error

Before we dive into the solution, let’s try to understand what this error means. The javax.net.ssl.SSLHandshakeException error occurs when a secure connection fails during an SSL handshake. The Remote host terminated the handshake message indicates that the other end of the connection closed the connection unexpectedly, leading to the SSL handshake failure.

Possible Causes

There are several reasons why this error might occur. Here are some of the most common causes:

  • Invalid SSL/TLS Certificate: If the SSL/TLS Certificate used by the remote host is not valid or expired, the SSL handshake will fail.

  • Firewall Restrictions: Sometimes, firewall restrictions can block SSL/TLS connections.

  • Client and Server Time Sync Issue: If the time on the client and server machines are not in sync, the SSL handshake might fail.

  • Outdated Java Version: Older versions of Java might not be compatible with the TLS/SSL version used by the remote host.

Solution

Now that we have identified the possible causes, here are some steps you can follow to fix the error:

Step 1: Check SSL/TLS Certificate

The first step is to check the SSL/TLS certificate of the remote host. Make sure that the certificate is valid and not expired. You can check the certificate details by using the openssl command.

openssl s_client -connect <remote_host>:<port>

Replace <remote_host> and <port> with the hostname and port number of the remote host, respectively. If the certificate is not valid, you need to get a new one.

Step 2: Check Firewall Restrictions

Make sure that your firewall is not blocking the SSL/TLS connection. You can temporarily disable the firewall and check if the error still persists. If the error goes away, then you need to allow SSL/TLS traffic through the firewall.

Step 3: Check Time Sync

Make sure that the time on both the client and server machines are in sync. You can synchronize the time by using the ntpdate command.

sudo ntpdate <ntp_server>

Replace <ntp_server> with the NTP server of your choice.

Step 4: Update Java

If you are using an older version of Java, update it to the latest version. The latest version of Java should be compatible with the TLS/SSL version used by the remote host.

Conclusion

In conclusion, the javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake error can be fixed by checking the SSL/TLS certificate, firewall restrictions, time sync, and updating Java. Follow these steps, and you should be able to resolve the error and continue working with Docker containers without any issues!

I’m running a local TCP server in C++ on Windows via OpenSSL and Windows sockets. I’m running the client in Java using SSL sockets. For most users this setup is working, however, some users run into the following Java exception upon attempting the SSL handshake:

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at sun.security.ssl.SSLSocketImpl.handleEOF(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.decode(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[?:1.8.0_321]
    ...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.SSLSocketInputRecord.read(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketInputRecord.readHeader(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source) ~[?:1.8.0_321]
    at sun.security.ssl.SSLTransport.decode(Unknown Source) ~[?:1.8.0_321]
    ... 10 more

My client socket code in Java looks like this:

public static Socket getClientSocket() throws Exception
{
    InetSocketAddress socketAddress = new InetSocketAddress("localhost", 54321);
    SSLSocketFactory socketFactory = getSSLSocketFactory();
    Socket clientSocket = socketFactory.createSocket();
    clientSocket.connect(socketAddress, 1_000);
    ((SSLSocket) clientSocket).startHandshake(); // <-- Exception here for some users
    return clientSocket;
}

private static SSLSocketFactory getSSLSocketFactory() throws Exception
{
    // Create a trust manager that does not validate certificate chains
    X509TrustManager trustManager = new X509TrustManager()
    {
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            // TODO Returning null is not allowed but it still works
            return null;
        }

        @Override
        public void checkClientTrusted(final X509Certificate[] certificates, final String authType)
        {

        }

        @Override
        public void checkServerTrusted(final X509Certificate[] certificates, final String authType)
        {
            for (X509Certificate certificate : certificates)
            {
                String certificateString = certificate.toString();
                if (!certificateString.contains("blablabla"))
                {
                    throw new SSLException("Certificate not trusted");
                }
            }
        }
    };
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
    return sslContext.getSocketFactory();
}

Attempted solutions:

  • Calling System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2") before connecting did not work (reference)
  • I do not want to tell users to import any SSL certificates into their truststore (unless I can automate this easily)

Where does the inconsistent behavior come from and how to fix it cleanly for everyone who gets the exception? I have access to the server source code and certificates. Also any critical questions or suggestions are welcome. I can provide more information if necessary.

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
	at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1616)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1434)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1336)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:450)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:421)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at com.tabnine.logging.TabnineLogDispatcher$dispatchLog$1.run(TabnineLogDispatcher.kt:40)
	at com.intellij.openapi.application.impl.ApplicationImpl$1.run(ApplicationImpl.java:263)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
	at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:483)
	at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:472)
	at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:160)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1426)
	... 26 more

When I perform a load testing to my website over HTTPS, I received multiples errors related with SSL Handshake when I simulate a high amount of concurrent users (>500 / sec).

Here are the errors that I received:

Error #1

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake

Error #2

javax.net.ssl.SSLException: Socket closed

Error #3

javax.net.ssl.SSLException: Read timed out

The thing is, everything is managed by the GCP, especially with the Load Balancer where my front-end is HTTPS associated with a valid certificate.

Also, the capacity of my back-end seems high enough to support everything. It is like the bottleneck is my Load Balancer.

The tests are made directly from my computer using JMeter.

So, what cause this problem and how can I fix it?

SSLHandshakeException appear in logs when there is some error occurred while validating the certificate installed in the client machine with a certificate on the server machine. In this post, we will learn about fixing this if you are using the Apache HttpClient library to create HttpClient to connect to SSL/TLS-secured URLs.

1. Problem

The exception logs will look like this.

Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
...
...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
  at sun.security.ssl.InputRecord.read(InputRecord.java:505)
...
...

I have already posted a code fix to bypass SSL matching in an earlier post.

Unfortunately, that fix works in TLS and TLS 1.1 protocols. It doesn’t work in TLS 1.2 protocol. So ultimately, you need to fix the certificate issue anyway. There is a ‘no code only’ fix for this.

2. Solution

Now there are two ways, you can utilize the imported certificate from the server. Either add the certificate to the JDK cacerts store; or pass certificate information in JVM arguments.

2.1. Import certificate to JDK cacert Store

Import the certificate from the server.

Use the given command to add the certificate to JDK store. (Remove new line characters).

keytool -import
  -noprompt 
  -trustcacerts 
  -alias MAVEN-ROOT 
  -file C:/Users/Lokesh/keys/cert/maven.cer 
  -keystore "C:/Program Files (x86)/Java/jdk8/jre/lib/security/cacerts"
  -storepass changeit

Now create the HttpClient as given:

public HttpClient createTlsV2HttpClient() throws KeyManagementException, 
        UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
 
      SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
 
      SSLConnectionSocketFactory f = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1.2" }, null,
                              SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
 
      Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                      .register("http", PlainConnectionSocketFactory.getSocketFactory())
                      .register("https", f)
                      .build();
 
      PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
 
      CloseableHttpClient client = HttpClients
                .custom()
                .setSSLSocketFactory(f)
                      .setConnectionManager(cm)
                      .build();
      return client;
}

Notice the code : SSLContext.getInstance("TLSv1.2"). This code picks up the certificates added to JDK cacert store. So make a note of it.

2.2. Pass certificate information in JVM aruguments

Import the certificate from the server.

Add JVM arguments while starting the server. Change the parameter values as per your application.

-Djavax.net.ssl.keyStore="C:/Users/Lokeshkeysmaven.jks"
-Djavax.net.ssl.keyStorePassword="test"
-Djavax.net.ssl.trustStore="C:/Users/Lokeshkeysmaven.jks"
-Djavax.net.ssl.trustStorePassword="test"

Now create an HTTP client as given:

public HttpClient createTlsV2HttpClient() throws KeyManagementException, 
        UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
 
      SSLContext sslContext = SSLContexts.createSystemDefault();
 
      SSLConnectionSocketFactory f = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1.2" }, null,
                              SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
 
      Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                      .register("http", PlainConnectionSocketFactory.getSocketFactory())
                      .register("https", f)
                      .build();
 
      PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
 
      CloseableHttpClient client = HttpClients
                .custom()
                .setSSLSocketFactory(f)
                      .setConnectionManager(cm)
                      .build();
      return client;
}

Notice the code : SSLContext.createSystemDefault(). This code picks up the certificates passed as JVM arguments. Again, make a note of it.

3. Conclusion

  • Use SSLContext.getInstance("TLSv1.2") when the certificate is added to JDK cacert store.
  • Use SSLContext.createSystemDefault() when SSL info is passed as JVM argument.

Drop me your questions in the comments section.

Happy Learning !!

[WEBINAR] Clean Code Principles and Practices — JUNE 21ST
Register Now

Понравилась статья? Поделить с друзьями:
  • Resident evil 5 ошибка xlive dll
  • Remote desktop произошла внутренняя ошибка
  • Rest api статусы ошибок
  • Regedit ошибка при изменении параметра
  • Rest api выдал ошибку вордпресс