【问题标题】:how to forward http 2 protocol version via proxy?如何通过代理转发 http 2 协议版本?
【发布时间】:2016-04-22 17:06:37
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

    标签: http nginx configuration


    【解决方案1】:

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

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

    为了在我们的应用程序中支持上游代理,我们有一个请求过滤器来分析 X-Forwarded-For 标头值以及远程主机 IP。然后,我们将所有 X-Forwarded-* 代理标头值拆开并“展开”它们,前提是我们确定它们是由已按合同建立标头配置的受信任代理添加的(这些将是我们应用程序中特定的预配置 IP)。这个处理是非常复杂的,所以这就是我要说的。但是,从中我们得到:

    1. 代表所有“可信赖”远程 IP 的 IP 列表 在链中。
    2. 最“值得信赖”的原始标头值, 应用程序将使用它来生成 URL 等。

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

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

    例如:

    • 可信代理 IP(预配置):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 标头:23.45.67.78、11.22.33.44
    • X-Forwarded-Host 标头:malicious.user.injected.value、app.customer.com、internalproxy.mycompany.com
    • X-Forwarded-Proto 标头:http、https、https
    • H2-IP 标头:23.45.67.78、11.22.33.44

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

    • 原远程主机:23.45.67.78
    • 原始主机标头: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。

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

    【讨论】:

    • 对于我正在寻找的东西来说太过分了,我发现 HTTP/2 往往是“人类”用户而不是机器人。不过我真的很喜欢阅读这篇文章,我通常认为一切都是从浏览器到服务器的,这很有趣,因为我没有想到有人来自不受信任的连接,尽管到了会伪造东西的 http2 代理。
    • 今天 HTTP/2 的第一批实现者是浏览器,但代理和其他客户端很快就会支持它。例如,Apache HTTP 服务器已经有一个 mod_proxy_http2 正在进行中。没错,代理可以伪造东西,但大多数问题是恶意用户伪装成代理,这样他们就可以欺骗您的应用程序,以规避与 IP 相关的安全措施、获得提升的访问权限、毒化缓存等。
    【解决方案2】:

    这类似于 X-Forwarded-ForX-Forwarded-Proto 标头的用途,但没有 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”之类的值,因此根据您的需要,它也可能是一个不错的选择。

    【讨论】:

      【解决方案3】:

      proxy_set_header X-Forwarded-ProtoVersion $server_protocol;

      注意:X-Forwarded-ProtoVersion 是一个组成的变量名。我不知道标准是什么。

      【讨论】:

        猜你喜欢
        • 2016-04-15
        • 1970-01-01
        • 2016-08-22
        • 1970-01-01
        • 2020-03-22
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多