强制清漆使用代理协议1

时间:2016-08-11 14:40:07

标签: nginx varnish haproxy

我让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 PROXY一起使用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> Nginx在HaProxy后端使用send-proxy-v2开关,当Varnish引入堆栈时会导致相同的问题。在HaProxy上切换回send-proxy解决了这个问题。因此,我确信问题是使用协议2而不是协议1的Varnish。但是如何告诉它不要?

2 个答案:

答案 0 :(得分:1)

  

据我所知,Varnish不是HTTP / 2或SSL,但它应该将协议传回Nginx no?

没有

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

事实上,你的问题是:

  

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

这个问题的答案是Varnish没有发送任何一个。无论是V1还是V2。

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

第一个支持HTTP的组件可以获取该地址,并将其设置在HTTP头中,通常为X-Forwarded-For,以利于堆栈中的其余组件。因此,Varnish没有理由向前转发代理协议。在你的例子中没有这样做,并且没有明显的理由为什么Varnish甚至能够转发代理协议.¹

这就把我们带到了错误。您误解了Nginx报告的问题。断页错误意味着Nginx正在接收除代理协议V1之外的其他内容。在循环中使用Varnish时,在对Nginx的请求中根本没有代理协议头2 - 当侦听器配置为期望代理协议头时,该头是强制

如果组件配置为期望代理协议V1且不存在,则始终错误。但“不存在”就是这个意思。 V1标头不存在。这并不意味着V2。事实并非如此。

  

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

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

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

或者将HAProxy配置为在HTTP模式下运行,并让它使用option forwardfor插入标题。

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

²我认为代理协议“标题”没有被正确地称为标题,这意味着它意味着什么。这是一个序言,而不是标题,但不幸的是它被称为标准中的“标题”。它肯定不是 HTTP 标头。

答案 1 :(得分:0)

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