Setting SSL Parameters on Apache http5 Client

1.8k Views Asked by At

I am upgrading from Apache httpcomponents 4 to version 5 in order to get http2/http1.1 support. I need to specify the ciphers my client offers. I assume that H2/1.1 ALPN is the default behavior for the AsyncHttpClient.

Here is my current code for the httpcomponents 4 client

    // TLS
    SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
            SSLContexts.createDefault(),
            new String[] { "TLSv1.2" },
            new String[] {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384",
                    "TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
                    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
                    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
                    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
                    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256",
                    "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA",
                    "TLS_RSA_WITH_AES_256_CBC_SHA"},
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());

    // Proxy
    HttpHost proxyhost = new HttpHost(proxyAddress, proxyPort);
    HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyhost);
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(
            new AuthScope(proxyAddress, proxyPort),
            new UsernamePasswordCredentials(proxyUsername, proxyPassword)
    );

    httpClient = HttpClients.custom()
            .setRoutePlanner(routePlanner)
            .setSSLSocketFactory(sslConnectionFactory)
            .setDefaultCredentialsProvider(credentialsProvider)
            .setRedirectStrategy(new LaxRedirectStrategy())
            .setDefaultCookieStore(cookieStore)
            .build();

Everything seems to be roughly the same for creating the asyc client except specifying the SSL factory. So setting the TLS parameters appears to take a different route. I've spent about an hour looking for examples and documentation with no luck. Some examples show a class called TLSConfig, but I can't find any documentation on it.

Any help is greatly appreciated.

1

There are 1 best solutions below

0
ok2c On BEST ANSWER

You need to build a custom TlsStrategy pretty much the same way as shown in the "Custom SSL context" example on the project website [1]

TLSConfig will be available as of 5.2 release which is going to go BETA soon.

final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
    .setTlsVersions(TLS.V_1_2)
    .setCiphers("TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384",
            "TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA",
            "TLS_RSA_WITH_AES_256_CBC_SHA")
    .build();

final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
    .setTlsStrategy(tlsStrategy)
    .build();
try (final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
    .setConnectionManager(cm)
    .build()) {

client.start();

final HttpHost target = new HttpHost("https", "httpbin.org");
final HttpClientContext clientContext = HttpClientContext.create();

final SimpleHttpRequest request = SimpleRequestBuilder.get()
        .setHttpHost(target)
        .setPath("/")
        .build();

System.out.println("Executing request " + request);
final Future<SimpleHttpResponse> future = client.execute(
        SimpleRequestProducer.create(request),
        SimpleResponseConsumer.create(),
        clientContext,
        new FutureCallback<SimpleHttpResponse>() {

            @Override
            public void completed(final SimpleHttpResponse response) {
                System.out.println(request + "->" + new StatusLine(response));
                final SSLSession sslSession = clientContext.getSSLSession();
                if (sslSession != null) {
                    System.out.println("SSL protocol " + sslSession.getProtocol());
                    System.out.println("SSL cipher suite " + sslSession.getCipherSuite());
                }
                System.out.println(response.getBody());
            }

            @Override
            public void failed(final Exception ex) {
                System.out.println(request + "->" + ex);
            }

            @Override
            public void cancelled() {
                System.out.println(request + " cancelled");
            }

        });
future.get();

System.out.println("Shutting down");
client.close(CloseMode.GRACEFUL);

[1] https://hc.apache.org/httpcomponents-client-5.1.x/examples-async.html