I have an HTTPS proxy set up so that HTTP clients can send plain HTTP requests securely to the proxy. For example, a client can send an encrypted HTTP GET request to the proxy, which will remove the encryption and send the plain HTTP GET request to the end-site.
I learned that this is not a common set up and only Google Chrome has in-built features to support such a scenario. (Info here - http://wiki.squid-cache.org/Features/HTTPS#Encrypted_browser-Squid_connection). I have made Google Chrome work with my HTTPS proxy and hence there is no trouble on the proxy side.
I wish to write an HTTP Client that will encrypt all requests to my HTTPS Proxy. I tried setting an HTTPS proxy to DefaultHttpClient this way -
DefaultHttpClient dhc = new DefaultHttpClient();
HttpHost proxy = new HttpHost("192.168.2.3", 8181, "https"); //NOTE : https
dhc.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
Then trying to execute any request gives me an SSLPeerUnverifiedException. I do not understand the reason why.
During my exploration of the DefaultHttpClient API, I came across HttpRoutePlanner and HttpRoute with which we can specify whether the connection to proxies should be encrypted or not. However, I am unable to make this work.
Here is a diagram that explains my setup by differentiating it with a HTTP Proxy setup -
HTTP Proxy:
HTTP Client <------- Plain Text GET, POST Requests -------> HTTP Proxy <------- Plain Text GET, POST Requests -------> HTTP End-Site
HTTP Client <------- Plain Text CONNECT Requests -------> HTTP Proxy <------- Plain Text CONNECT Requests -------> HTTPS End-Site
NOTE: For HTTPS End-Sites, only the CONNECT Request is seen by the proxy. Then an SSL Tunnel is established between the Client and End-Site
HTTPS Proxy:
HTTP Client <------- Encrypted GET, POST Requests -------> HTTPS Proxy <-------- Plain Text GET, POST Requests --------> HTTP End-Site
HTTP Client <------- Encrypted CONNECT Requests -------> HTTPS Proxy <------- Plain Text CONNECT Requests -------> HTTPS End-Site
NOTE: For HTTPS End-Sites, only the initial CONNECT Request should be encrypted to the proxy. The subsequent request will anyway be tunnelled.
Can anybody please let me know how I can achieve this goal? I believe HttpRoutePlanner should help, but I don't know how.
I was able to make the Apache HttpClient 4.x work with the HTTPS proxy. The SSLPeerUnverifiedException that I mentioned in the question was thrown because I was not trusting the Proxy Server's certificate. Once this is taken care of, then connections to HTTPS End-Sites worked as expected.
For connections to HTTP end-sites, I had to use my own HttpRoutePlanner to make it work. Here's the code with the explanations -
DefaultHttpClient dhc = new DefaultHttpClient();
HttpHost proxy = new HttpHost("192.168.2.3", 8181, "https");
dhc.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
SchemeSocketFactory factory = null;
try {
factory = new SSLSocketFactory(new SimpleTrustStrategy()); //Trust All strategy
} catch (GeneralSecurityException e1) {
e1.printStackTrace();
}
Scheme https = new Scheme("https", 443, factory);
dhc.getConnectionManager().getSchemeRegistry().register(https);
HttpGet request = new HttpGet("http://en.wikipedia.org/wiki/Main_Page");
try {
HttpHost host = determineTarget(request);
if(host.getSchemeName().equalsIgnoreCase("http")){
dhc.setRoutePlanner(new MyRoutePlanner());
}
} catch (ClientProtocolException e1) {
e1.printStackTrace();
}
The implementation of MyRoutePlanner
is below -
public class MyRoutePlanner implements HttpRoutePlanner {
@Override
public HttpRoute determineRoute(HttpHost target, HttpRequest request,
HttpContext context) throws HttpException {
return new HttpRoute(target, null
, new HttpHost("192.168.2.3", 8181, "https")
, true, TunnelType.PLAIN, LayerType.PLAIN); //Note: true
}
}
To make the HttpClient talk to a HTTP End-site through an HTTPS Proxy, the route should be secure, but there should not be any Tunnelling or Layering.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With