我有Nginx监听端口443作为一个SSL终结者,并代理到同一台服务器上的Varnish未encryption的stream量。 Varnish 3正在处理此stream量,并且stream量直接通过端口80进入。所有stream量都被传递(未encryption)到集群中其他服务器上的Apache实例。 Apache实例使用mod_rpaf将所logging的客户端IPreplace为X-Forwarded-For标头的内容。
我的问题是,如果stream量通过Nginx传递,而'正确的'客户端IP正在loginVarnishNCSA日志,看起来好像Varnish(可以理解)用127.0.0.1下游replaceNginx的X-Forwarded-For头,这是用Apachelogging的。 有没有一个简单的方法来停止Varnish重写X-Forwarded-For如果它已经填充?
绝对; X-Forwarded-For的Varnish处理实际上只是在默认的vcl_recv函数中定义的。
if (req.restarts == 0) { if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } }
一个函数的默认定义总是附加到你在活动VCL文件中定义的一个,但是如果你定义的函数总是处理一个请求,那么默认的逻辑将永远不会执行。
沿这些行设置一个vcl_recv :
sub vcl_recv { /* Your existing logic goes here */ /* After that, we'll insert the default logic, with the X-Forwarded-For handling removed */ /* The return (lookup); at the end ensures that the default append behavior won't have an impact */ if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } if (req.request != "GET" && req.request != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); } if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } return (lookup); }
编辑:
由于Varnish也直接处理一些连接,所以更好的方法是让它有select地设置标题。 您仍然需要包含完整的vcl_recv以便默认不应用自己的头,但是将其包含在顶部:
if (req.restarts == 0) { if (!req.http.x-forwarded-for) { set req.http.X-Forwarded-For = client.ip; } }