简体   繁体   中英

how to forward http 2 protocol version via proxy?

I have a simple rails application

(browser) -> (nginx latest; proxy_pass) -> rails (latest)

How do I configure nginx to notify rails that nginx received an HTTP/2 request via a different header IE: my_"http_version = 2.0"? proxy_pass communicates with rails via HTTP 1.1 and I want to know if the original request was http/2.

Thank you!

This is similar to what the X-Forwarded-For and X-Forwarded-Proto headers are used for, but there not a standard header used to communicate the HTTP protocol version to the backend. I recommend using this:

proxy_set_header X-Forwarded-Proto-Version $http2;

The $http2 variables comes from ngx_http_v2_module which I presume you are using with Nginx to server HTTP/2.

The difference between $http2 and $server_protocol is that $http2 works more like a boolean, appearing blank if the HTTP/1 protocol was used. $server_protocol will contain values like "HTTP/1.1" or "HTTP/2.0", so it could also be a good choice depending on your needs.

I can tell you what we've done, but you might find it pretty odd. If you don't care about trusting and looking through multiple proxies in a row, you can probably get away with a simpler approach like the other answers describe.

First of all, our application has to support seeing through proxies that are run and maintained by customers. On our app server, we always need to keep in mind that requests may travel through multiple proxies, and for some customers, we actually have to support that use case so that the app can see through multiple proxies to get the original headers.

To support upstream proxies in our app, we have a request filter to analyze the X-Forwarded-For header values as well as the remote host IP. Then we take apart all the X-Forwarded-* proxy header values and "unwind" them only if we we are sure they were added by trusted proxies whose header configuration has been established contractually (these will be specific pre-configured IPs in our application). This processing is very complicated so that's all I will say about it. But, out of that we get:

  1. a list of IPs that represents all the "trustworthy" remote IPs in the chain.
  2. the most "trustworthy" original header values, which will be used by the application for URL generation, etc.

In our app, the only work we do specifically for HTTP/2 is optimization (eg, do not concatenate JS files), but any HTTP/1.x connections in the proxy chain will bottleneck performance. So we only care about whether the entire request chain was HTTP/2 from start to finish . Therefore, we have asked all upstream proxies that support HTTP/2 to implement a special header that we invented, let's call it H2-IP .

If any upstream proxy receives an HTTP/2 request, we ask that the proxy appends the remote host to the H2-IP header. Then, on the server side, we will iterate over the list of trustable remote IPs as passed by our trustworthy configured proxies (#1 above) and make sure that each one is also listed in the H2-IP header.

So for example:

  • Trusted proxy IPs (pre-configured): 11.22.33.44, 9.8.7.6, 10.20.30.40, 127.0.0.1, 45.235.235.200
  • Remote host: 10.20.30.40
  • Is HTTP/2? Yes
  • X-Forwarded-For header: 23.45.67.78, 11.22.33.44
  • X-Forwarded-Host header: malicious.user.injected.value, app.customer.com, internalproxy.mycompany.com
  • X-Forwarded-Proto header: http, https, https
  • H2-IP header: 23.45.67.78, 11.22.33.44

In this example, the remote host (10.20.30.40) is found to be a trusted proxy, and we know via contract that this proxy will send all three X-Forwarded-(For|Host|Proto) headers. So we unpeel the last value from each header, use those unpeeled values as the trusted request data, then we repeat the process for each X-Forwarded-For IP until we get to one that isn't a trusted proxy. So here is the data we wind up with:

  • Original remote host: 23.45.67.78
  • Original host header: app.customer.com (note: we threw away an untrusted value)
  • Original scheme: https (note: we threw away an untrusted value)
  • Trustworthy IP chain: 23.45.67.78 -> 11.22.33.44 -> 10.20.30.40 -> application
  • HTTP/2 remote IPs: 23.45.67.78, 11.22.33.44, 10.20.30.40

Therefore, since the whole trustworthy IP chain is a subset of the HTTP/2 remote IPs, we know this request was fully HTTP/2 from start to finish.

If you don't care about trusting and looking through multiple proxies in a row, you can probably get away with a simpler approach like the other answers describe.

proxy_set_header X-Forwarded-ProtoVersion $server_protocol;

Note: X-Forwarded-ProtoVersion is a made up variable name. I don't know what the standard one is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM