在一個或多個(!)反向代理之後通過 X-Forwarded-For 檢查 Varnish ACL
我讓 Varnish 在反向代理後面執行(在 localhost 上執行,用於 SSL 解除安裝)。代理設置 X-Forwarded-For 標頭,如果標頭已存在,則將其自身添加到其中。
當我進行 ACL 檢查時,我當然想檢查原始客戶端的 IP,而不是我的代理的 IP,所以我不能使用該
client.ip
欄位。使用std
vmod 我可以執行以下操作:vcl 4.0; import std; sub vcl_recv { if (std.ip(regsub(req.http.X-Forwarded-For, ", 127.0.0.1$", ""), "0.0.0.0") ~ my_acl) { ...do stuff... } }
換句話說,在執行它
std.ip
並將其與我的 ACL 進行比較之前,我從標頭中修剪了代理的 IP (127.0.0.1)。這工作正常,除了…當 X-Forwarded-For 標頭在到達我的代理之前已經設置時,這將失敗。在這種情況下,XFF 標頭包含三個或更多 IP 地址。修剪最後一個仍然會留下不止一個並
std.ip
對此感到窒息,將請求延遲幾秒鐘,當然也無法檢查 ACL。在我關閉代理後,我需要確保 XFF 標頭僅包含一個 IP(IPv4 或 IPv6)。這應該是客戶端的 IP。
例如:
X-Forwarded-For: 10.10.1.1, 10.10.2.2, 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1
應該成為
X-Forwarded-For: 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1
由於我不能信任從外部傳入的任何 XFF 標頭,因此我想丟棄除代理看到的客戶端 IP 之外的任何內容。我的代理不支持修改 XFF 標頭,所以我需要在 Varnish 中進行。
當我可以與標題互動時,Varnish 流程中的第一個點是 in
vcl_recv()
,此時 Varnish 已經將 添加client.ip
到列表的末尾。我希望使用正則表達式將最後兩項(IPv4 或 IPv6)擷取到帶編號的擷取組($1)中,並簡單地將標頭替換為擷取組。像這樣:
vcl 4.0; import std; sub vcl_recv { set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "([a-f0-9:.]+, [a-f0-9:.]+)$", "\1"); }
第三個參數(替換正則表達式匹配的字元的字元串)不起作用。生成的標頭與以前完全相同,即使正則表達式僅擷取最後兩個 IP 地址。
除了 XFF 標頭中的最後兩個 IP 地址之外,我如何丟棄其他任何內容?
你的正則表達式似乎很好。我看到的唯一一件事是您要求自行替換該組。
如果您
^(.*)
在正則表達式的開頭添加並將第二個參數替換為\2
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2");
}
話雖如此,我認為更改 XFF 標頭不是一個好主意。添加標頭而不是更改已由中間代理傳輸的刪除資訊應該更標準。