如何通过代理转发 http 2 协议版本?

how to forward http 2 protocol version via proxy?

我有一个简单的 rails 应用程序

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

如何配置 nginx 以通知 rails nginx 通过不同的 header IE: my_"http_version = 2.0" 收到了 HTTP/2 请求? proxy_pass 通过 HTTP 1.1 与 rails 通信,我想知道原始请求是否为 http/2。

谢谢!

proxy_set_header X-Forwarded-ProtoVersion $server_protocol;

注:X-Forwarded-ProtoVersion是虚构的变量名。不知道标准的是什么

这类似于 X-Forwarded-ForX-Forwarded-Proto headers 的用途,但没有 standard header 用于将 HTTP 协议版本传达给后端.我推荐使用这个:

proxy_set_header X-Forwarded-Proto-Version $http2;

$http2 变量来自 ngx_http_v2_module,我假设您正在使用 Nginx 到服务器 HTTP/2。

$http2$server_protocol 之间的区别在于 $http2 更像一个布尔值,如果使用 HTTP/1 协议则显示为空白。 $server_protocol 将包含 "HTTP/1.1" 或 "HTTP/2.0" 等值,因此根据您的需要,它也是一个不错的选择。

我可以告诉你我们做了什么,但你可能会觉得很奇怪。 如果您不关心连续信任和查看多个代理,您可能可以像其他答案描述的那样使用更简单的方法。

首先,我们的应用程序必须支持查看 运行 并由客户维护的代理。在我们的应用服务器上,我们始终需要记住,请求可能会通过多个代理,对于某些客户,我们实际上必须支持该用例,以便应用可以看到多个代理以获取原始 headers.

为了在我们的应用程序中支持上游代理,我们有一个请求过滤器来分析 X-Forwarded-For header 值以及远程主机 IP。然后我们将所有 X-Forwarded-* 代理 header 值和 "unwind" 拆开,只有当我们确定它们是由 header 配置已按合同建立的受信任代理添加时(这些将是我们应用程序中的特定 pre-configured IP)。这个处理非常复杂,所以我就说这么多。但是,我们得到:

  1. 代表所有 "trustworthy" 远程 IP 的 IP 列表 在链中。
  2. 最"trustworthy"原始header值, 它将被应用程序用于 URL 生成等

在我们的应用程序中,我们专门为 HTTP/2 做的唯一工作是优化(例如,不要连接 JS 文件),但是代理链中的任何 HTTP/1.x 连接都会成为性能瓶颈. 所以我们只关心整个请求链是否从头到尾都是HTTP/2。因此,我们要求所有支持 HTTP/2 的上游代理实现我们发明的特殊 header,我们称之为 H2-IP.

如果任何上游代理收到 HTTP/2 请求,我们要求代理 将远程主机附加 H2-IP header。然后,在服务器端,我们将遍历由我们可信赖的配置代理(上面的#1)传递的可信赖远程 IP 列表,并确保每个 IP 也都列在 H2-IP header.

例如:

  • 受信任的代理 IP (pre-configured):11.22.33.44、9.8.7.6、10.20.30.40、127.0.0.1、45.235.235.200
  • 远程主机:10.20.30.40
  • 是HTTP/2吗?是
  • 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

在这个例子中,发现远程主机 (10.20.30.40) 是一个受信任的代理,我们通过合同知道这个代理将发送所有三个 X-Forwarded-(For|Host|Proto) header秒。因此,我们从每个 header 中提取最后一个值,使用这些未提取的值作为受信任的请求数据,然后我们对每个 X-Forwarded-For IP 重复该过程,直到我们得到一个不是受信任的代理。所以这是我们最终得到的数据:

  • 原远程主机:23.45.67.78
  • 原始主机header:app.customer.com (注意:我们丢弃了一个不受信任的值)
  • 原方案:https (注意:我们丢弃了一个不受信任的值)
  • 可信IP链:23.45.67.78 -> 11.22.33.44 -> 10.20.30.40 -> 应用
  • HTTP/2 远程 IP:23.45.67.78、11.22.33.44、10.20.30.40

因此,由于整个可信 IP 链是 HTTP/2 远程 IP 的子集,我们知道此请求从头到尾都是 HTTP/2。

如果您不关心连续信任和查看多个代理,您可能可以像其他答案描述的那样使用更简单的方法。