Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Curl has a feature for manually specifying which IP to resolve a host to. For example:

curl https://google.com --resolve "google.com:443:173.194.72.113"

This is particularly useful when using HTTPS. If it was just a HTTP request, I could have achieved the same by specifying the IP address directly, and adding a host header. But in HTTPS that would break the connection since the SSL certificate host would be compared to the IP address and not the host header.

My question is, how can I achieve the same thing in Java?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
259 views
Welcome To Ask or Share your Answers For Others

1 Answer

If using Apache's HttpClient, you can create a custom DNS resolver to detect the host you'd like to redirect, and then provide a substitute IP address.

Note: Just changing the Host header for HTTPS requests doesn't work. It will throw "javax.net.ssl.SSLPeerUnverifiedException", forcing you to trust bad certificates, stop SNI from working, etc., so really not an option. A custom DnsResolver is the only clean way I've found to get these requests to work with HTTPS in Java.

Example:

/* Custom DNS resolver */
DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
    @Override
    public InetAddress[] resolve(final String host) throws UnknownHostException {
        if (host.equalsIgnoreCase("my.host.com")) {
            /* If we match the host we're trying to talk to, 
               return the IP address we want, not what is in DNS */
            return new InetAddress[] { InetAddress.getByName("127.0.0.1") };
        } else {
            /* Else, resolve it as we would normally */
            return super.resolve(host);
        }
    }
};

/* HttpClientConnectionManager allows us to use custom DnsResolver */
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
    /* We're forced to create a SocketFactory Registry.  Passing null
       doesn't force a default Registry, so we re-invent the wheel. */
    RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", SSLConnectionSocketFactory.getSocketFactory())
        .build(), 
    null, /* Default ConnectionFactory */ 
    null, /* Default SchemePortResolver */ 
    dnsResolver  /* Our DnsResolver */
    );

/* build HttpClient that will use our DnsResolver */
HttpClient httpClient = HttpClientBuilder.create()
        .setConnectionManager(connManager)
        .build();

/* build our request */
HttpGet httpRequest = new HttpGet("https://my.host.com/page?and=stuff"); 

/* Executing our request should now hit 127.0.0.1, regardless of DNS */
HttpResponse httpResponse = httpClient.execute(httpRequest);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...