After reading both HTTP/2 RFC (#7540) and TLS-ALPN RFC (#7301), I'm still unable
to figure out the expected behavior when ALPN is lacking in one end.
Assuming I have a client that uses HTTP/2 "h2" (over TLS) that talks to a server that support HTTP/2 but does not send the ALPN extension in the "server hello".
What is the expected behavior from the client?
Most clients I've seen so far consider that HTTP/2 is not supported by the server and downgrade the connection to http/1.1, but few ignore (go-gRPC) continue with HTTP/2.
This scenario can be more practical if using AWS classic LB that does SSL termination between a client ("h2") to the server ("h2c"). In this example, the client sends the ALPN extension with value of "h2", the LB performs SSL handshake without ALPN (as expected from his part), and eventually the JAVA gRPC fails due to HTTP/1.1 downgrade.
To answer the question, without alpn, but using npn, still can support grpc.
Two clarification,
http2 negotiation for grpc can happen either thru alpn or npn.
If alpn is supported in client, it sends alpn extension as well as npn extension in Client Hello.
If alpn is supported in server, server only responds with alpn with h2. If alpn not supported and npn is configuration in 'server LB config' it will send npn and h2.
What i noticed in haproxy and nginx if you dont configure alpn, it does not default to npn unless configured.
grpc client insists on h2. If neither alpn, nor npn with h2 happed, client will disconnect as it assumes h2 is not suppored, and h2 is mandatory for grpc
It depends entirely on the client and server. Many still support the older NPN TLS extension for SPDY and HTTP/2 Support, though officially the spec says to use ALPN only.
On the browser side, for example, Chrome, Firefox and Opera now only support HTTP/2 over ALPN though they all used to support it over NPN. At the time of writing Safari, IE and Edge still allow either NPN or ALPN to be used.
On the server side some (e.g. Nginx) Support both, while some (e.g. Apache) only Support ALPN.
I would also question the terminology of “downgrade”. The ALPN extension is a request to use h2 and happens as part of the TLS negotiation before a single HTTP message has been sent. So it’s not really a downgrade anymore than an unsuccessful upgrade request.
Related
Here is the situation:
Our client wants to back support some old ios mac systems, which the network lib it used does not support ALPN. Our Server is set up only to accept gRPC requests, so there is no need for the server to accept HTTP1.1 requests.
So how do I disable Nginx to accept HTTP1.1 request and only enable HTTP2 support and skip the ALPN?
I tried to make Nginx defaults to support http2 but it still involves the ALPN process.
it seems nginx is do http2 based on ALPN so there is no walkaround for that.
Our customer request http2 only service because other product they use are using gRPC with envoy proxy. Envoy seems to have the ability to provide http2 only service without alpn, but it is subject to find out why ( as the document does not specify it clearly)
https://en.m.wikipedia.org/wiki/HTTP/1.1_Upgrade_header
Given the following:
Connect on port 80
Request Upgrade: TLS/1.x
Request Upgrade: h2c or Upgrade: websocket
Will the resulting connection/protocol still be using TLS or will it be replaced by an unsecure one?
Note: I'm not primarily looking for the current status of popular clients/servers, but rather any hints in the specification(s) which may lead to a more desirable implementation.
I'm not sure if your request makes sense and, even if it did, if any implementation would support it - or if you could rely on what support that might be.
Connect on port 80
Request Upgrade: TLS/1.x
Ok this bits fine. It would basically ask to speak TLS over port 80 and over http and is defined by RFC-2817. It's highly unusual as standard would be to speak TLS only over https scheme and on port 443 (or a non-standard port like 8443), but in theory this would work. Note also the Connection header must also be set to Upgrade.
Connect on port 80
Request Upgrade: TLS/1.x
Request Upgrade: h2c
This is where it starts to get tricky. The h2c protocol is an unsecured HTTP/2 connection (i.e. without TLS) but, combined with your first header, you are asking this to be over TLS (multiple headers are permitted over HTTP btw). I guess, in theory, this could work, similar to how it would work under HTTP/1.1 above, except that the HTTP/2 spec clearly states:
the "h2c" protocol identifier describes a protocol that does not use TLS.
and
implementations that support HTTP/2 over TLS MUST use protocol negotiation in TLS [TLS-ALPN].
I would therefore consider above connection a violation of spec and not confirm that upgrade.
Connect on port 80
Request Upgrade: TLS/1.x
Request Upgrade: websocket
The websocket spec is less clear on this. It does state:
By default, the WebSocket Protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket connections tunneled over Transport Layer Security (TLS) [RFC2818].
and also:
A |wss| URI identifies a WebSocket server and resource name and indicates that traffic over that connection is to be protected via TLS (including standard benefits of TLS such as data confidentiality and integrity and endpoint authentication).
However there is nothing that I can see that forbids a TLS connection over the |ws| URI, or even using the |wss| URI over port 80. However I would imagine that, since this is not explicitly defined, there would be no guarantees as to whether this would work, or if the connection would be secure or not.
I followed the simple instructions in this Wildfly 10.1 news that enables HTTP/2 and TLS protocol on port 8443 and everything went perfectly.
But I would like to enable HTTP/2 protocol also in pages HTTP, getting this protocol in both HTTPS as in the HTTP.
It is possible?
And how I can make this change directly in the standalone-full.xml configuration file?
Thank you.
HTTP2 works only with SSL/TLS
Browsers do not support HTTP2 without encryption
HTTP/2 is is enabled by default on both the HTTP and HTTPS ports, however most browsers (with the exception of internet explorer) do not support HTTP/2 without encryption.
How does a website behave on a client that does not support the HTTP/2 protocol?Is there a backward compatibility of the server that the server falls back on HTTP/1?
Standard webservers will handle HTTP 1.x requests just fine and reply with HTTP 1.x responses. There are just too many browsers out there that don't speak HTTP/2 yet to completely drop HTTP 1.x support from a server.
Question
If 2 HTTP requests are made to the same server at the same time from fresh, e.g. GET /image1.png HTTP/1.1 & GET /image2.png HTTP/1.1 with no previous connection to the server. Then should 1 TCP connection be made or 2?
Info
Persistent connections supported by default in HTTP 1.1. HTTP 1.0 uses the Connection: Keep-Alive.
It seems pretty clear from reading the RFC that if the above requests are made one after each other then the second request should reuse the connection.
HTTP Pipelining is sending multiple requests down the same connection without first waiting for a response. I am not sure where this fit into the answer tho.
If 2 HTTP requests are made to the same server at the same time from fresh, e.g. GET /image1.png
If the requests are made by the browser simultaneously (and there is no HTTP proxy server), then there will be two connections made to the server (unless http pipelining is enabled). Per the wikipedia article on pipelining,
Out of all the major browsers, only Opera based on Presto layout engine had a fully working implementation that was enabled by default. In all other browsers HTTP pipelining is disabled or not implemented.
Internet Explorer 8 does not pipeline requests, due to concerns regarding buggy proxies and head-of-line blocking.
Mozilla browsers (such as Mozilla Firefox, SeaMonkey and Camino) support pipelining, however it is disabled by default. Pipelining is disabled by default to avoid issues with misbehaving servers. When pipelining is enabled, Mozilla browsers use some heuristics, especially to turn pipelining off for older IIS servers.
Konqueror 2.0 supports pipelining, but it's disabled by default.
Google Chrome supports pipelining for HTTP in the stable release as a non-default option (starting with version 18). There is no support for pipelining HTTPS yet.[11] As of version 26, the flag to enable HTTP pipelining in Chrome has been disabled.
So, probably two connections.