Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent unsolicited CONNECT method calls from HttpURLConnection

I am using HttpURLConnection along the lines of the following:

String strURL = "https://example.herokuapp.com";
Bitmap bmImage = null;
HttpURLConnection connection = null;
InputStream in = null;
showMessage(context.getString(R.string.message_preparing));
try {
    int timeoutMS = 15000;
    URL url = new URL(strURL);
    connection = (HttpURLConnection) url.openConnection();
    connection.setDoInput(true);
    connection.setConnectTimeout(timeoutMS);
    connection.setReadTimeout(timeoutMS);
    connection.connect();
    in = connection.getInputStream();
    BitmapFactory.Options options = new BitmapFactory.Options();
    bmImage = BitmapFactory.decodeStream(in, null, options);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (connection != null)
        connection.disconnect();
    if (in != null) {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

return bmImage;

This works just fine, with the url defined by strURL returning a bmp image, and this being decoded ready for use by the above code.

But for one user in particular, although the code works fine to fetch the bmp image, at the server (a node.js server at heroku) it is apparent that a CONNECT request is also being sent by their device. That request is rejected with a 503 response automatically, so it's not a problem as such, and the bmp is still sent to their device, but I'd like to know why those CONNECT requests are being sent at all, and how to stop them. Surely there should be nothing but GET requests?

I've tried this solution to what appears to be a similar problem, but it makes no difference for me.

Note that strURL is to an https server, and I'm using HttpURLConnection (not Https) -- not sure if there is any significance in that.

I'm also not 100% sure the CONNECT requests derive from the above calls, but they certainly happen around the same time as a GET request that delivers the bmp. Maybe it could be generated by the OS somehow, outside of my code? Not sure.

In case it helps, an example log message from heroku, in response to one of the CONNECT requests, is as follows:

Oct 27 14:14:25 example heroku/router: at=error code=H13 desc="Connection closed without response" method=CONNECT path="example.herokuapp.com:443" host=example.herokuapp.com request_id=353e623x-dec4-42x5-bcfb-452add02ecef fwd="111.22.333.4" dyno=web.1 connect=0ms service=1ms status=503 bytes=0

EDIT: it may also be of relevance that the device concerned actually makes two independent GET requests within a short time of each other (completely separate and legitimate requests), but there is only ever a single CONNECT request apparent (around the same time as the pair of GET requests). So it's not as if there is a CONNECT for each GET.

like image 930
drmrbrewer Avatar asked Oct 27 '15 14:10

drmrbrewer


People also ask

What is HttpURLConnection?

A URLConnection with support for HTTP-specific features. See the spec for details. Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances.

How do I turn off HttpsURLConnection in Java?

To answer your question, calling disconnect on the connection will disconnect the connection.

Can HttpURLConnection be used with https?

HttpsURLConnection extends HttpURLConnection with support for https-specific features. A URLConnection with support for HTTP-specific features.


Video Answer


1 Answers

The CONNECT method can preface a request to an HTTP server (either a proxy server or an origin server), and it basically means:

"By the way, old chap, you wouldn't mind relaying this stuff I say 'verbatim' to the host/port I happen to mention, would you? No need to actually pay attention to what I'm saying, really."

Usually this would be an instruction to a proxy, to 'get out of the way', and let the requestor (which could be the user-agent OR another proxy) to talk directly to the upstream server.

It's a nice facility to have if there is an otherwise-uncooperative (perhaps outdated) proxy between you and an origin server. It's also handy if you're a hacker and would like a mis-configured origin server to blithely facilitate your entry into the internal network.

However, unless you have perfect knowledge of the network and 'know' that the is only ONE proxy in your path, you'll need to 'stack' the CONNECT header until you get a refusal.

For example:

CONNECT site.example.com 80 HTTP/1.1
CONNECT site.example.com 80 HTTP/1.1
GET /foo HTTP/1.1
Host: site.example.com

.... will either get you through 2 interfering, good-for-nothing, upstream proxies; OR get you through just the 1 that's actually there, and earn you a 503 from the origin-server ... whereupon you'll have to repeat your request with ONE FEWER CONNECT preface-methods.

So that would account for the behaviour seen so far.

However, what isn't clear is WHO is ADDING THE CONNECT PREFACE?! And why don't they like proxies?

It could be:

  1. code on the User-Agent (your Android app on your client's smartphone using HttpUrlConnection or HttpsUrlConnection (used automatically by openConnection() if the URL has an https:// scheme);
  2. any Proxy between the User-Agent and the origin-server, which for some reason is distrustful of its upstream proxies or needs to tunnel HTTPS through a proxy which otherwise only supports HTTP (which is what CONNECT is for)
  3. a Proxy that's been hacked, and is looking for dumb origin-servers to exploit ... but why wait until someone actually needs stuff, to hassle the origin server?

The full content of the CONNECT method, and the source IP for the packet would be interesting. I'm betting on #2 though, and predict that you won't see the CONNECT if you accessed the site via a http:// URL.

There is nothing which you can do about it.

like image 103
David Bullock Avatar answered Oct 25 '22 03:10

David Bullock