【问题标题】:Force Varnish to Use Proxy Protocol 1强制 Varnish 使用代理协议 1
【发布时间】:2016-12-10 04:20:52
【问题描述】:

我让 HaProxy 终止 SSL 并将请求传递回 Varnish,然后 Varnish 为缓存页面或来自 Nginx 的请求提供服务。但是,Varnish 似乎将来自 HaProxy 的请求视为 HTTP/1 而不是 HTTP/2 并且无法提供服务。

当我尝试点击一个页面时,我可以在 Nginx 日志中看到以下内容:

" while reading PROXY protocol, client: 127.0.0.1, server: 127.0.0.1:8181
2016/08/11 06:53:31 [error] 5682#0: *1 broken header: "GET / HTTP/1.1
Host: www.example.com
User-Agent: curl/7.50.2-DEV
Accept: */*
X-Forwarded-For: IP_Removed
Accept-Encoding: gzip
X-Varnish: 32777

我发现了一些与 here 相关的内容,其中指出原因是 Nginx 仅适用于 v2 代理 v1。因此,因此,我使用 send-proxy 而不是 send-proxy-v2 开关强制在 HaProxy 中使用协议 1。但是当涉及到 Varnish 时,我认为 Varnish 正在以某种方式将其转换为协议 2,这导致它无法与 Nginx 正确通信。

我已经从等式中删除了 Varnish,并将 HaProxy 直接连接到 Nginx,它通过 HTTP/2 完美运行。问题是 Varnish 堆栈中发生了一些事情,可能怀疑是 Varnish 使用的代理协议 v2。

那么,长话短说,我如何强制 Varnish 遵守 PROXY1 而不是 PROXY2 协议?我尝试将 PROXY1 添加到启动守护程序选项中,但 Varnish 不会接受。任何帮助表示赞赏。谢谢!

更新 - 我在 HaProxy 后端使用 send-proxy-v2 开关测试了 HaProxy > Nginx,它导致了与将 Varnish 引入堆栈时相同的问题。在 HaProxy 上切换回 send-proxy 可以解决此问题。所以,我确信问题在于 Varnish 使用协议 2 而不是协议 1。但是如何告诉它不要呢?

【问题讨论】:

  • 你确定你在谈论 HTTP/2 吗?这与 PROXY v2 协议无关。 Varnish 不支持 HTTP/2,它将在 Varnish 5.x 中引入。
  • 也许我自己很困惑,但我的理解是 HaProxy 在处理 HTTP/2 时作为 TCP 而不是 HTTP 运行,因此有必要在后端使用 send-proxy。 Nginx 设置为使用它的 proxy_protocol 开关接收这个。我知道 Varnish 不是 HTTP/2 或 SSL,但它应该将协议原样传回 Nginx 没有?

标签: nginx varnish haproxy


【解决方案1】:

我知道 Varnish 不是 HTTP/2 或 SSL,但它应该将协议原样传回 Nginx 否?

没有。

但首先,让我们澄清一下。 HTTP/2 和代理协议 V2 完全没有任何关系。从你的脑海中移除 HTTP/2,因为它在任何意义上都不适用于这里。

其实你的问题是这样的:

如果 HAProxy 正在向 Varnish 发送代理协议 V1,并且在 Varnish 后面配置了 Nginx 以期望代理协议 V1,为什么 Nginx 会抱怨标头损坏? Varnish 不会将代理协议 V1 转发到后端吗?它是否出于某种原因发送代理协议 V2?

这个问题的答案是 Varnish 没有发送任何一个。 V1 和 V2 都不是。

您需要代理协议的唯一目的是让 HTTP 感知组件可以从上游、非 HTTP 感知组件接收客户端 IP 地址(和端口),例如使用 mode tcp 或 Amazon 的 HAProxy带有 TCP 模式侦听器的 ELB,其中任何一个通常为您执行 SSL 卸载,而不是 HTTP 请求路由,因此它需要一种传递客户端地址的替代机制。

第一个支持 HTTP 的组件可以获取该地址并将其设置在 HTTP 标头中,通常是 X-Forwarded-For,以使堆栈中的其余组件受益。因此,Varnish 没有理由继续转发代理协议。在您的示例中并没有这样做,并且没有明显的理由说明 Varnish 甚至能够转发代理协议。¹

这给我们带来了错误。您误诊了 Nginx 报告的问题。损坏的标头错误意味着 Nginx 正在接收代理协议 V1 以外的内容。在循环中使用 Varnish 时,对 Nginx 的请求中根本不存在代理协议标头²——当侦听器被配置为期望代理协议标头时,该标头是强制

如果一个组件被配置为期望代理协议 V1 并且它不存在,那总是一个错误。但“不存在”正是这个意思。不存在 V1 标头。这并不意味着 V2 是。不是。

所以,我确信问题在于 Varnish 使用协议 2 而不是协议 1。

你错误地说服了自己。代理 V2 到 Nginx - 正如您使用 HAProxy 尝试过的那样 - 是一个错误,并且根本没有 Proxy 协议标头 - 正如您从 Varnish 看到的那样 - 是一个错误,如上所述。两者都是错误配置,尽管类型不同。您在这里所做的是重复了错误,但原因完全不同。

如果您通过 Varnish 发送所有请求,则配置 Varnish 以使用它从传入代理协议消息中学习的信息在转发的请求中设置 X-Forwarded-For。从 Nginx 配置中删除代理协议。

或者配置HAProxy运行在HTTP模式,让它使用option forwardfor插入头部。


¹ 很明显,从错误中,Varnish 只是发送普通的 HTTP 标头——看起来不像代理协议。我认为它甚至不支持将代理协议发送到源服务器的选项,但是如果我忽略了该功能,有人会说些什么。

² 考虑到这意味着什么,我会断言代理协议“标头”不正确地称为标头。它是序言,而不是标题,尽管不幸的是它在标准中被称为“标题”。它肯定不是 HTTP 标头。

【讨论】:

    【解决方案2】:

    如果您将 Varnish 升级到 5.0,它可以通过设置“.proxy_header = 1”将代理协议版本 1 发送到 NGINX

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-21
      • 2012-11-18
      • 1970-01-01
      • 2019-12-17
      • 2015-02-15
      • 2020-10-27
      • 2018-06-21
      • 2020-12-18
      相关资源
      最近更新 更多