Netty 4 client ssl для запроса всех https-сайтов

У меня есть веб-искатель, основанный на netty (4.1b7), где я массивно запрашиваю разные сайты как http, так и https, и я пытаюсь настроить netty-клиента на работу с https-сайтами с разными настройками аутентификации.

Когда у меня есть простая нетто-конфигурация без собственных сертификатов:

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

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

Приблизительная половина сайтов https запрашивается ОК, но другие не выполняются:

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

или

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)

Когда я попытался создать собственные локальные сертификаты и установить их как:

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

то все https-сайты потерпели неудачу с такими ошибками, как:

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)

Также я пробовал советовать из этого SO, но пока не повезло.

Что не так или кто-то может дать какое-то пошаговое руководство по настройке клиента netty 4+ для работы с https-сайтами со всеми возможными настройками auth.

Ответ 1

Наконец, я решил проблему, взломав TrustManager в коде (нашел этот метод на 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));

Теперь все https-сайты, которые в порядке в браузере (хром не показывает предупреждения, по крайней мере) - читаются Netty.

Ответ 2

попробуйте создать sslCtx, как показано ниже. SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

И добавьте в конвейер p.addLast(sslCtx.newHandler(ch.alloc()));