清漆取消設置除最後一個 x-forwarded-for IP 地址之外的所有…錯誤?
在試圖弄清楚為什麼我們的 Varnish 4.1 安裝(通過 varnish-cache.org 儲存庫在 CentOS7 上)沒有遵循 vcl 規則,這些規則設置為在 X-Forwarded-For 標頭中記錄客戶端 IP 地址(請參閱:Varnish 4 logging proxy /load balancer 而不是客戶端 IP 地址)我在查看 varnishlog 文件時碰巧注意到了一些奇怪的事情:
- Begin req 9353447 rxreq - Timestamp Start: 1488771709.337974 0.000000 0.000000 - Timestamp Req: 1488771709.337974 0.000000 0.000000 - ReqStart 172.25.20.65 19903 - ReqMethod GET - ReqURL /about-us/ - ReqProtocol HTTP/1.1 - ReqHeader host: www.<notreallythishost>.com - ReqHeader Accept: */* - ReqHeader Accept-Encoding: gzip, deflate - ReqHeader Cache-Control: no-cache - ReqHeader From: bingbot(at)microsoft.com - ReqHeader Pragma: no-cache - ReqHeader User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) - ReqHeader X-Forwarded-For: 40.77.167.41 - ReqHeader X-Forwarded-Port: 80 - ReqHeader X-Forwarded-Proto: http - ReqHeader Connection: keep-alive - ReqUnset X-Forwarded-For: 40.77.167.41 - ReqHeader X-Forwarded-For: 40.77.167.41, 172.25.20.65 - VCL_call RECV - ReqUnset X-Forwarded-For: 40.77.167.41, 172.25.20.65 - ReqHeader X-Forwarded-For: 172.25.20.65 - ReqUnset Accept-Encoding: gzip, deflate - ReqHeader Accept-Encoding: gzip - ReqUnset User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) - VCL_return hash - VCL_call HASH - VCL_return lookup - VCL_call MISS - VCL_return fetch - Link bereq 9353449 fetch - Timestamp Fetch: 1488771709.338395 0.000421 0.000421 - RespProtocol HTTP/1.1
這完全解釋了為什麼無論我們使用何種日誌記錄技術,我們在任何時候都無法獲得通過 varnishncsa 記錄的負載平衡器 IP 地址以外的任何內容。
看起來好像在請求處理中,它通過將 AWS 負載均衡器 IP 地址添加到標頭來建構 X-Forwarded-For 標頭,但由於呼叫 vc_call 會再次對其進行解構並刪除原始客戶端 IP 地址。那麼我該如何保持 X-Forwarded-For 的完整性,為什麼 Varnish 將 IP 從左側移開,而不是像應該的那樣將它們添加到 X-Forwarded-For 標頭中?漏洞?
所以解決這個問題(4.1.3-1.el7.x86_64 中的可能錯誤)是我在瀏覽其他清漆日誌記錄問題時發現的一個線索,特別是關於完全禁用 x-forwarded-for 標頭的問題。
雖然這不是我想要做的,但它提供了關於防止 varnish 將其自己的 vcl_recv 內容附加到我的 vcl_recv 函式定義的按鈕的提示。具體提供您自己的返回(查找)(儘管那是 varnish <= 3)或返回(雜湊)(varnish 4.x)。
所以現在我在 vcl_recv() 的頂部有這個:
# ensure proper logging of x-forwarded-for IP addresses std.collect(req.http.x-forwarded-for); set req.http.x-forwarded-for = regsub ( req.http.x-forwarded-for, "^(([0-9]{1,3}\.){3}[0-9]{1,3})(.*)", "\1" ); if (req.http.x-forwarded-for) { std.log("ip:" + req.http.x-forwarded-for); } else { std.log("ip:" + client.ip); }
然後在函式的最後,我當然提到了:
return (hash);
因此,它現在成功地僅記錄客戶端 IP 地址,因為它應該添加以下 varnishncsa 選項:
-F "%%{VCL_Log:ip}x %%l %%u %%t \"%%r\" %%s %%b \"%%{Referer}i\" \"%%{User-agent}i\""
希望其他人發現此資訊有用。
更新:正如我在這個 nginx 答案中發現關於欺騙的文章一樣,在清漆中也有一種real_ip_from或trusted_ip_from標頭會很好,但目前它似乎不是本機的。在這種情況下,我最初的解決方案將挑選出欺騙地址。因此,最好刪除已知 IP 的正則表達式,然後選擇第一個未處理的客戶端 IP。像這樣的東西會起作用:
set req.http.x-forwarded-for = regsub ( req.http.x-forwarded-for, "(([0-9]{1,3}\.){3}[0-9]{1,3})(, (172.25.20.65|172.25.10.228),?)+$", "\1" );
其中 172.25.20.65 和 172.25.10.228 是我信任的 IP(代理或負載均衡器拾取並添加到 X-Forwarded-For 等)。根據您是否希望在其前面看到代理/LB,如果您希望在您的標頭中始終至少有一個負載均衡器/代理,您的正則表達式可以是這樣的:
(([0-9]{1,3}\.){3}[0-9]{1,3})(, (<trustedip1>|<trustedip2>|...),?)+$
或者如果允許在您的清漆伺服器之前沒有任何東西:
(([0-9]{1,3}\.){3}[0-9]{1,3})(, (<trustedip1>|<trustedip2>|...),?)*$
儘管如果是後者,您為什麼要查看 x-forwarded-for 標頭…