Problem with DNS resolution using Java and Apache HttpClient

61 views Asked by At

I have a Java client that uses Apache HttpClient to make an HTTPS REST request to a Service installed on OpenShift.

The Service is an NginX that handles Mutual Authentication, and performs a proxy-pass to other services.

The Service is exposed on the route https://myhost; the route has a Termination Type of "Passthrough", so that the SSL handshake is handled directly by the service.

The company's DNS does not resolve "myhost", so I have configured a mapping between myhost and the IP address of the OpenShift server in the etc/hosts file on my operating system (Windows).

From a browser and from Postman, everything works correctly: the OpenShift server is reached, and the hostname in the URL is preserved, so the service is reached through the configured route.

Using the Java application, however, OpenShift returns an error 503 Service Unavailable; from the error message, and from the CN of the server certificate, it is clear that the URL does not match the route, because the hostname has been replaced by the IP address.

The error is exactly the same as I get if I configure the URL in the client by entering the IP address instead of the hostname.

Here is the code I used for the test, and the response I get:

    public static void main(String[] args) throws Exception {
        InputStream io = HttpConfig.class.getClassLoader().getResourceAsStream("keystore.jks");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(io, null);
        final SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(keyStore, TrustAllStrategy.INSTANCE)
                //.loadKeyMaterial(keyStore, new char[0])
                .build();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        
        CloseableHttpClient httpClient = HttpClients.custom()
                    .useSystemProperties()
                    .setSSLSocketFactory(sslConnectionSocketFactory).build();
        
        HttpGet httpRequest =  new HttpGet("https://myhost/api/probe");
        CloseableHttpResponse response = httpClient.execute(httpRequest);
    }
org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {s}->https://myhost:443][total available: 0; route allocated: 0 of 5; total allocated: 0 of 10]
org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {s}->https://myhost:443][total available: 0; route allocated: 1 of 5; total allocated: 1 of 10]
org.apache.http.impl.execchain.MainClientExec - Opening connection {s}->https://myhost:443
org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to myhost/1.2.3.4:443
org.apache.http.conn.ssl.SSLConnectionSocketFactory - Connecting socket to myhost/1.2.3.4:443 with timeout 0
org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled protocols: [TLSv1, TLSv1.1, TLSv1.2]
org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled cipher suites:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256]
org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
org.apache.http.conn.ssl.SSLConnectionSocketFactory - Secure session established
org.apache.http.conn.ssl.SSLConnectionSocketFactory -  negotiated protocol: TLSv1.2
org.apache.http.conn.ssl.SSLConnectionSocketFactory -  negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
org.apache.http.conn.ssl.SSLConnectionSocketFactory -  peer principal: CN=*.router.default.svc.cluster.local
org.apache.http.conn.ssl.SSLConnectionSocketFactory -  peer alternative names: [*.router.default.svc.cluster.local, router.default.svc.cluster.local]
org.apache.http.conn.ssl.SSLConnectionSocketFactory -  issuer principal: CN=openshift-signer@1683642812
org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connection established 5.6.7.8:51968<->1.2.3.4:443
org.apache.http.impl.execchain.MainClientExec - Executing request GET /tt2-dsx-forfe/api/probe HTTP/1.1
org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
org.apache.http.headers - http-outgoing-0 >> GET /tt2-dsx-forfe/api/probe HTTP/1.1
org.apache.http.headers - http-outgoing-0 >> Host: myhost
org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.14 (Java/1.8.0_202)
org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
org.apache.http.wire - http-outgoing-0 >> "GET /tt2-dsx-forfe/api/probe HTTP/1.1[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Host: myhost[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.14 (Java/1.8.0_202)[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "HTTP/1.0 503 Service Unavailable[\n]"
org.apache.http.wire - http-outgoing-0 << "Pragma: no-cache[\n]"
org.apache.http.wire - http-outgoing-0 << "Cache-Control: private, max-age=0, no-cache, no-store[\n]"
org.apache.http.wire - http-outgoing-0 << "Connection: close[\n]"
org.apache.http.wire - http-outgoing-0 << "Content-Type: text/html[\n]"
org.apache.http.wire - http-outgoing-0 << "[\n]"
org.apache.http.wire - http-outgoing-0 << "<html>[\n]"
...
org.apache.http.wire - http-outgoing-0 << "</html>[\n]"
org.apache.http.headers - http-outgoing-0 << HTTP/1.0 503 Service Unavailable
org.apache.http.headers - http-outgoing-0 << Pragma: no-cache
org.apache.http.headers - http-outgoing-0 << Cache-Control: private, max-age=0, no-cache, no-store
org.apache.http.headers - http-outgoing-0 << Connection: close
org.apache.http.headers - http-outgoing-0 << Content-Type: text/html

In this example I commented out the line where I pass the keystore, so I would have expected a 400 - Bed request error, caused by the absence of the client key, and not a 503.

0

There are 0 answers