JPO
JPO

Reputation: 91

UnknownHostException behind Proxy

I have a java program, that connects to a website to retrieve some XML from it. This works fine on my computer, as well as others outside our company. One of our customers is now not able to connect to the website. I figured out, that they are behind a proxy. I have now found which settings I need to use, and in my test program it works (partially).

In the code below, the downloadFile() call works as expected, and the file can be downloaded without problems. The contactHost() fails on our client machines with an UnknownHostException:

java.net.UnknownHostException: No such host is known (api.myserver.de)
    at java.base/java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method)
    at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:925)
    at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1505)
    at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:844)
    at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1495)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1354)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1288)
    at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:111)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)

Background: Windows 10 machines, our program is shipped with an internal OpenJDK, version "10.0.2" 2018-07-17. The program is started with the following defines -Djdk.http.auth.tunneling.disabledSchemes="" -Djava.net.preferIPv4Stack=true in order to use IP4 only, and to enable BasicAuthentification for the Proxy. With these settings, the file can be downloaded, however the UnknownHostException is still there.

We have also tried to open the used URL in an browser, and this works as excepted, i.e. in the browser the website is opened.

Here is my code for testing:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class LFTProxyTest {

private static String uname = null;
private static String pass = null;

public static void main(String[] args) {
    System.setProperty("java.net.useSystemProxies", "true");
    // uname = "test"; // whatever that user provides
    // pass = "sectret"; // whatever that user provides
    Authenticator.setDefault(new ProxyAuth(uname, pass));

    contactHost();
    downloadFile();
}

private static boolean downloadFile() {
    System.out.println("CHECK connection");
    int cp = contactHost();
    if (cp == 200)
        return true;
    if (cp == 407)
        return false;
    else {
        try {
            System.out.println("Try loading file: ");
            URL url = new URL("https://www.google.de");
            URLConnection urlConnection = url.openConnection();
            InputStream in = new BufferedInputStream(urlConnection.getInputStream());
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            dBuilder.parse(in);
            System.out.println("    FILE DOWNLOAD successfull!");
        } catch (Exception e) {
            System.out.println("    FILE DOWNLOAD failed:");
            System.out.println("***EXCEPTION: " + e.getMessage());
            return false;
        }
    }
    System.out.println("CHECK done");
    return true;
}

private static int contactHost() {
    HttpClient client = HttpClientBuilder.create().build();// new DefaultHttpClient();
    String catalogURI = "https://api.myserver.de/query";
    HttpGet request = new HttpGet(catalogURI);
    try {
        int ret = 0;
        HttpResponse response = client.execute(request);
        ret = response.getStatusLine().getStatusCode();
        System.out.println("PROXY test: " + ret);
        ((CloseableHttpClient) client).close();
        return ret;
    } catch (IOException e) {
        e.printStackTrace();
        return -1;
    }
}

}

I don't know what do do know, I'm not even sure where the error could be. Any ideas are highly appreciated!

Upvotes: 2

Views: 16256

Answers (2)

JPO
JPO

Reputation: 91

Ok, so after some further digging, I found out that org.apache.http.client.HttpClient is not respecting java.net.useSystemProxies at all, be it set via System or via -D. And it is also ignoring http.proxyHost etc. Solution is to use a ProxySelector like this:

    ProxySelector.setDefault(new ProxySelector() {

        @Override
        public List<Proxy> select(URI uri) {
            ArrayList<Proxy> list = new ArrayList<Proxy>(); 
            list.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy1.de", 8000)));
            list.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy2.de", 8080)));
            return list;
        }

        @Override
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
            logger.error("Error in ProxySelector, connection Failed: ", ioe);
        }
    });

I'm getting another exception now, but I might open another thread for this.

Upvotes: 3

Adi Ohana
Adi Ohana

Reputation: 947

UnknownHostException designates a pretty straight forward problem. That the IP address of the remote host you are trying to reach cannot be resolved. So the solution to this is very simple. You should check the input of Socket (or any other method that throws an UnknownHostException), and validate that it is the intended one. If you are not whether you have the correct host name, you can launch a UNIX terminal and use the nslookup command (among others) to see if your DNS server can resolve the host name to an IP address successfully.

If you are on Windows you can use the host command. If that doesn’t work as expected then, you should check if the host name you have is correct and then try to refresh your DNS cache. If that doesn’t work either, try to use a different DNS server, eg Google Public DNS is a very good alternative.

Upvotes: 0

Related Questions