Apache-2.2

使用 Nginx/Varnish/Apache 記錄客戶端 IP

  • October 25, 2012

我讓 Nginx 監聽埠 443 作為 SSL 終結器,並將未加密的流量代理到同一伺服器上的 Varnish。Varnish 3 正在處理此流量,並且流量直接進入埠 80。所有流量都未經加密地傳遞到集群中其他伺服器上的 Apache 實例。Apache 實例使用 mod_rpaf 將記錄的客戶端 IP 替換為 X-Forwarded-For 標頭的內容。

我的問題是,如果流量來自 Nginx,而“正確”客戶端 IP 正在記錄在 VarnishNCSA 日誌中,看起來 Varnish (可以理解)用 127.0.0.1 下游替換 Nginx 的 X-Forwarded-For 標頭,這是用 Apache 記錄的。如果已經填充了 X-Forwarded-For,是否有一種很好的簡單方法來阻止 Varnish 重寫 X-Forwarded-For?

絕對地; Varnish 的處理X-Forwarded-For實際上只是在預設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沿著這些構想設置 a :

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 也直接處理一些連接,因此更好的方法可能是讓它有選擇地設置標頭。您仍然希望包含完整的vcl_recv,以便預設不應用其自己的標題,但在頂部包含此:

if (req.restarts == 0) {
   if (!req.http.x-forwarded-for) {
       set req.http.X-Forwarded-For = client.ip;
   }
}

引用自:https://serverfault.com/questions/442041