Cloudflare started to support http/2.0 in production environment yesterday(HTTP/2 is here! Goodbye SPDY? Not quite yet), not like NGINX open source version(NGINX Open Source 1.9.5 Released with HTTP/2 Support), which dropped spdy support, Cloudflare supports them both like Google and Facebook does. Cloudflare is not the first CDN company to support http/2, KeyCDN launched there http/2.0 support from the early Oct 2015(KeyCDN Launches HTTP/2 Support), cdn77 started their http/2.0 support since Aug 2015(HTTP/2 Support for All Customers), but both of KeyCDN and cdn77 doesn’t support http/2 + spdy, now Cloudflare supports both, so maybe it’s just worthy(BTW, akamai also support them both), without a doubt it’s a good very good news to us, but how to test if a web server support http/2.0? Here we go.
Application-Layer Protocol Negotiation, on Wikipediais a Transport Layer Security (TLS) extension for application layer protocol negotiation. ALPN allows the application layer to negotiate which protocol should be performed over a secure connection in a manner which avoids additional round trips and which is independent of the application layer protocols. It is used by HTTP/2.
We can use TLS-ALPN to get the supported protocols by the server desired order, here we will use OpenSSL client as an example.
On OpenSSL man page:
enable Next Protocol Negotiation TLS extension and provide a list of comma-separated protocol names that the client should advertise support for. The list should contain most wanted protocols first. Protocol names are printable ASCII strings, for example “http/1.1” or “spdy/3”. Empty list of protocols is treated specially and will cause the client to advertise support for the TLS extension but disconnect just after receiving ServerHello with a list of server supported protocols.
The syntax should be like this:
openssl s_client -nextprotoneg NULL -servername host.domain.name -connect host.ip.or.domain:port
Because there may be many domains pointing to a same IP address, we should tell the server which domain we are going to connect by servername, and I don’t want to get a verify error, so I will also tell OpenSSL the path we store certificates by CApath, for example, on Ubuntu 14.04 LTS:
$ openssl s_client -CApath /etc/ssl/certs -nextprotoneg NULL -servername www.peterdavehello.org -connect www.peterdavehello.org:443 | grep 'Protocols advertised by server'
We will get this result:
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
depth=1 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Class 1 Primary Intermediate Server CA
depth=0 C = TW, CN = www.peterdavehello.org, emailAddress = hsu @peterdavehello.org
Protocols advertised by server: h2, http/1.1
Which means www.peterdavehello.org wanna use http/2.0 first, and then http/1.1, if you do this test on www.google.com, you’ll get another result like this:
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = www.google.com
Protocols advertised by server: h2, spdy/3.1, http/1.1
So we know that Google supports http/2.0, spdy/3.1 and http/1.1!
The funniest thing I noticed is that the result of Facebook is a little bit more complex and also unstable, test result 1:
depth=3 C = US, O = GTE Corporation, OU = “GTE CyberTrust Solutions, Inc.”, CN = GTE CyberTrust Global Root
depth=2 C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
depth=1 C = NL, L = Amsterdam, O = Verizon Enterprise Solutions, OU = Cybertrust, CN = Verizon Akamai SureServer CA G14-SHA2
depth=0 C = US, ST = CA, L = Santa Clara, O = Akamai Technologies Inc., CN = http2.akamai.com
Protocols advertised by server: h2, h2-14, spdy/3.1, spdy/3, http/1.1, http/1.0
Test result 2:
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
depth=0 C = US, ST = CA, L = Menlo Park, O = “Facebook, Inc.”, CN = *.facebook.com
Protocols advertised by server: spdy/3.1-fb-0.5, spdy/3.1, spdy/3, http/1.1
I guess Facebook is still testing their http/2.0 feature.