Enable http2 in nginx only for some clients - http

I have two set of users using okhttp/2.7.0 and okhttp/3.12.0. I want to enable http2 in nginx only for those users who are using okhttp/3.12.0. The client ensures to send their identifier. Is there a way to use this information and enable http2 only for those users.
Note: Multiple ports is not an option for me.
My nginx and OS version
nginx version: nginx/1.14.2
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
built with OpenSSL 1.0.2h 3 May 2016
TLS SNI support enabled
My nginx conf goes like this
server {
listen 443 ssl http2;
...

This is not really possible. The client is only sent as part of a HTTP message, which is only sent after the version of HTTP to use is decided, obviously. The initially message to create the connection, and set up the SSL/TLS parameters won’t have the client (which is usually where the HTTP version is decided using the ALPN extension to TLS).
There are however other ways this might be possible, including:
Depending on the capabilities of the client. I’m not familiar with okhttp but from a quick Google it seems ALPN support was only added in v3, so you could disable the older NPN on your server and then, if that is correct, then in theory the older client will not be able to negotiate HTTP/2 so will fallback to HTTP/1.1. Unfortunately there appears to be no Nginx config option for that so you’d need to build a special version of OpenSSL without NPN support and then compile Nginx against that. Probably more hassle than it’s worth.
Use Apache instead of Nginx as it never supported NPN
Using Multiple IPs and somehow directing each version to a separate IP. Though I suspect as you cannot use separate ports you probably cannot do this either.
All in all it’s a bit of hack to be honest and so is not something that I would suggest you pursue. What you have not explained however is why you want to use HTTP/2 for one set of clients but not the other. Maybe there’s a better way to achieve what you want if you explain that.

Related

Possible to build Ocserv vpn project to use plain http

Is it possible to modify Ocserv on clients so that it runs on plain http instead of ssl and use a simple XOR or a custom encryption?
I know that it is insecure but in my case I don't care about security and TLS overhead (including handshaking time) and also SSL censorship are major concerns.

How to disable sni on nginx?

If I use the "--with-http_ssl_module" to buld nginx, it will always support sni and some old clients on windows xp will fail to connect.
How could i disable the use of sni on nginx?
SNI is an extension to TLS. This means that clients that don't support it will fall back to using the default mechanism. So no need to disable anything. If something works not as expected, it's simply because you haven't set a non-SNI configuration correctly.
In other words, an old non-SNI client is being presented with an invalid certificate.
To solve this, ensure that your default NGINX server block has the right TLS certificate.

Why do browsers not support gRPC?

gRPC is based on HTTP/2, which (assumption) is widely supported by browsers. Therefore, I feel there should be no problem with gRPC from a browser.
However, it is clear that there is a problem. The protocol, grpc web, is different, as exists "due to browser limitation". There are also numerous blog post describing complicated tech stacks deployed to get gRPC to work from a browser.
I'm missing the actual problem - why does gRPC not simply work from browsers?
I now understand that browsers only supports HTTP/2 in the sense that they use it to fetch resources from the server on behalf of your application (javascript) code.
Javascipt application code can still only use HTTP/1 (which may be handled under the hood by the browser in an HTTP/2 connection). Therefore it is not possible for application code to use grpc.
If anyone should find where this is explained in the docs, it would be good to add a link to it here.
Most browsers use HTTP1.1 whereas GRPC only works with HTTP2. You can use nginx, envoy or traefic to run it behind a reverse proxy, very similar to how web sockets are often used behind a reverse proxy(in that case the http1 is upgraded to a websockets connection). The reverse proxy will send the grpc request sent over http1 to an http2 backend and vice versa. You can use Envoy(suggested/currently used by grpc-web), traefik(am using this personally) and nginx.

What is an http upgrade?

This is one of the Node http events. Did the obvious Google Searches, didn't find much. What is it exactly?
HTTP Upgrade is used to indicate a preference or requirement to switch to a different version of HTTP or to another protocol, if possible:
The Upgrade general-header allows the client to specify what
additional communication protocols it supports and would like to use
if the server finds it appropriate to switch protocols. The server
MUST use the Upgrade header field within a 101 (Switching Protocols)
response to indicate which protocol(s) are being switched.
Upgrade = "Upgrade" ":" 1#product
For example,
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
The Upgrade header field is intended to provide a simple mechanism
for transition from HTTP/1.1 to some other, incompatible protocol.
According to the IANA register, there are only 3 registered mentions of it (including one in the HTTP specification itself).
The other two are for:
Upgrading to TLS Within HTTP/1.1 (almost never used, not to be confused with HTTP over TLS, which defines HTTPS as widely used). This upgrade allows for a similar mechanism to STARTTLS in other protocols (e.g. LDAP, SMTP, ...) so as to be able to switch to TLS on the same port as the plain connection, after exchanging some of the application protocol messages, as opposed to having the entire HTTP exchange on top of SSL/TLS without it needing to know it's on top of TLS (the way HTTPS works).
Upgrading to WebSockets (still a draft).

What is the benefit of using NginX for Node.js?

From what I understand Node.js doesnt need NginX to work as a http server (or a websockets server or any server for that matter), but I keep reading about how to use NginX instead of Node.js internal server and cant find of a good reason to go that way
Here http://developer.yahoo.com/yui/theater/video.php?v=dahl-node Node.js author says that Node.js is still in development and so there may be security issues that NginX simply hides.
On the other hand, in case of a heavy traffic NginX will be able to split the job between many Node.js running servers.
In addition to the previous answers, there’s another practical reason to use nginx in front of Node.js, and that’s simply because you might want to run more than one Node app on your server.
If a Node app is listening on port 80, you are limited to that one app. If nginx is listening on port 80 it can proxy the requests to multiple Node apps running on other ports.
It’s also convenient to delegate TLS/SSL/HTTPS to Nginx. Doing TLS directly in Node is possible, but it’s extra work and error-prone. With Nginx (or another proxy) in front of your app, you don’t have to worry about it and there are tools to help you securely configure it.
But be prepared: nginx don't support http 1.1 while talking to backend so features like keep-alive or websockets won't work if you put node behind the nginx.
UPD: see nginx 1.2.0 - socket.io - HTTP/1.1 - Proxy websocket connections for more up-to-date info.

Resources