5

I am writing an analytics server that is going to be used by web users. One of the parameters that I want to test is their browser support. Please tell me if I can obtain the fallowing information and how:

  • Test if the client (user browser) supports http/2
  • Test if the client (user browser) supports http/2 pushes, some how detect when the server sends a push, does the client able to use it, this one is probably some js test, or not you tell me.
  • Test if the client (user browser) supports QUIC, the UDP version of http/2
Flimzy
  • 60,850
  • 13
  • 104
  • 147
Ilya Gazman
  • 27,805
  • 19
  • 119
  • 190

2 Answers2

1

This depends on the web server used and the details it provides on the connection made to it.

Apache for instance, provides the following variables: https://httpd.apache.org/docs/2.4/mod/mod_http2.html#envvars

Including these variables:

Variable Name:  Value Type:   Description:
HTTP2           flag          HTTP/2 is being used.
H2PUSH          flag          HTTP/2 Server Push is enabled for this connection and also supported by the client.
H2_PUSHED       string        empty or PUSHED for a request being pushed by the server.

So you can easily add this to your log files using a LogFormat like this:

LogFormat "%h %l %u %t %{ms}T \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{SSL_PROTOCOL}x %{SSL_CIPHER}x %{Content-Encoding}o %{H2_PUSHED}e" combined

And then see from the log files whether it was served over HTTP/2.0 and whether it was PUSHED or not. For example:

86.1.2.3 - - [11/Jul/2017:22:14:56 +0100] 2 "GET / HTTP/2.0" 200 1700 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 br
86.1.2.3 - - [11/Jul/2017:22:14:56 +0100] 3 "GET /assets/css/common.css HTTP/2.0" 200 5381 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 br PUSHED

These variables are also available to CGI scripts and the like. Note these variables will only be set if HTTP/2 is actually used.

Not all web servers expose this level of detail as easily as Apache and many don't support HTTP/2 push so probably can't detect that given that they don't support it themselves!

I'm not aware of any web browsers that give these details from the HTTPS client hello message (when HTTP/2 would be negotiated) as most only provide details of the current connection, rather than every protocol support, and only after the HTTPS session is set up. For example Apache's HTTPS variables are given here: http://httpd.apache.org/docs/current/mod/mod_ssl.html#envvars

QUIC is less supported by web servers so not as easy to detect because of that.

To actually detect all this from the client side is more difficult as these are not exposed to JavaScript as far as I am aware. Easiest option would be to call a CGI script over HTTP/2 which returns the result of those values provided by the web server.

Note that pushed resources would only be used if needed. And if needed and not pushed, then it will be fetched anyway. So your idea of a js test, presumably detecting whether a pushed resource is being used will not definitively say whether the client supports push because the resource might have been fetched.

Barry Pollard
  • 30,554
  • 4
  • 60
  • 77
  • I am not sure yet what server the back end will use, so I just want to know what the client is sending to the back end that will allow the back end to understand what protocol the client support. – Ilya Gazman Jul 11 '17 at 21:45
  • Regardless the push, in case the resource was pushed, how can you test from js that you used the pushed resource and did not refetch it – Ilya Gazman Jul 11 '17 at 21:46
  • That depends entirely what details the back end you choose exposes, as I said. And you cannot differentiate between a pushed resource that was used, and the same resource that was fetched without push, again as I mentioned in the answer. Unless you change the contents of that resource based on whether you know from the back end whether push is supported. – Barry Pollard Jul 11 '17 at 21:49
  • Ok, got you about the pushes – Ilya Gazman Jul 11 '17 at 21:53
  • I checked and found that the protocol information is negotiated together with the ssl handshake and the client is the one who starts it. So theoretically when the ssl negotiation is started with client hello, it should already send the information on whether it support http/2 or and if it's going to use QUIC or not, this is regardless the server that you are using and regardless it's support of http/2 – Ilya Gazman Jul 11 '17 at 21:56
  • Correct. And if you find a server that exposes that information from the client hello then your problem is solved. But as far as I know none do, so you only get details for that connection AFTER the connection is established. You could of course write your own TLS server but that's not a small task. Easier to set up a HTTP/2 server and see if the connection works, and then detect from server side which protocol it's using for that established connection. As I stated. – Barry Pollard Jul 11 '17 at 21:59
  • Added an extra sentence to the answer to make this point. Though see you've already accepted my answer anyway so thanks for that. – Barry Pollard Jul 11 '17 at 22:22
0

The best you'll be able to do is determine their browser, via their user agent, and then cross-reference that with some database of browsers and features.

Of course, a user-agent can lie, but the majority of them will announce themselves appropriately.

samanime
  • 21,211
  • 7
  • 69
  • 122
  • User Agent does not tell you the protocol – Ilya Gazman Jul 11 '17 at 18:26
  • 2
    That would be correct. If you read what I actually said, that's why I said you need to cross-reference the user agent with a database that says for this user agent, it supports these features. There isn't anything in the browser that tells its protocol. – samanime Jul 11 '17 at 18:34
  • The server must be able to tell if the client support http/2 or not, other wise how it knows what protocol to use in communication with that client. – Ilya Gazman Jul 11 '17 at 20:27
  • You are not wrong but the user agent string can be forged or there might be another reason why HTTP/2 isn't supported in the current connection such as HTTPS not being used. – PHP Guru Jun 17 '20 at 01:34