Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

netty 4 client ssl configuration to request all https sites

I have some web crawler based on netty (4.1b7) where I massively request different sites both http and https ones and I'm trying to configure netty client to deal with https sites with different authentication settings.

When I have a simple netty configuration w/o own certificates:

 SslContext sslCtx = SslContextBuilder.forClient().build();

            SSLEngine sslEngine = sslCtx.newEngine(ch.alloc(), host, port);
            p.addLast("ssl", new SslHandler(sslEngine));

Approx half of https sites are requested OK but others failed as:

Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:304)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:919)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:916)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1369)
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1164)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1067)
... 19 moreCaused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:281)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1493)
... 27 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 33 more

or:

Caused by: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1138)

When I tried to generate own local certificates and set them as:

System.setProperty("javax.net.ssl.trustStore", "/etc/ssl/my/cacerts.jks");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
    System.setProperty("javax.net.ssl.keyStore", "/etc/ssl/my/keystore.jks");
    System.setProperty("javax.net.ssl.keyStorePassword", "changeit");

then all https sites failed with errors like:

Caused by: java.security.cert.CertificateException: found no certificates: /etc/ssl/my/cacerts.jks
at io.netty.handler.ssl.PemReader.readCertificates(PemReader.java:83) ~[netty-all-4.1.0.Beta7.jar:4.1.0.Beta7]
at io.netty.handler.ssl.SslContext.toX509Certificates(SslContext.java:967)
....
Caused by: java.security.KeyException: found no private key: /etc/ssl/my/keystore.jks
at io.netty.handler.ssl.PemReader.readPrivateKey(PemReader.java:99) ~[netty-all-4.1.0.Beta7.jar:4.1.0.Beta7]
at io.netty.handler.ssl.SslContext.toPrivateKey(SslContext.java:923)

Also I tried advises from that SO, but with no luck yet.

What's wrong or can anybody give some kind of step by step guide for configuring netty 4+ client to deal with https sites with all possible auth settings.

like image 465
yetanothercoder Avatar asked Oct 24 '15 15:10

yetanothercoder


2 Answers

Finally I solved issue by hacking TrustManager in code (found this technique on SO):

TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};

    // Ignore differences between given hostname and certificate hostname
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);

...
final SSLEngine sslEngine = sc.createSSLEngine(host, port);
            sslEngine.setUseClientMode(true);
            sslEngine.setNeedClientAuth(false);

            p.addLast("ssl", new SslHandler(sslEngine));

Now all https sites which are OK in browser (chrome doesn't show warning at least) - are read by Netty.

like image 178
yetanothercoder Avatar answered Nov 18 '22 06:11

yetanothercoder


try buidling the sslCtx like following SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

And add to the pipeline p.addLast(sslCtx.newHandler(ch.alloc()));

like image 21
Sudheera Avatar answered Nov 18 '22 06:11

Sudheera