在一个或多个(!)反向代理后面,通过X-Forwarded-For检查Varnish ACL

我已经在反向代理(在localhost上运行,用于SSL卸载)后面运行Varnish。 代理设置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运行代理服务器的IP(127.0.0.1)并将其与我的ACL进行比较之前,我会从代理服务器的IP中std.ip IP(127.0.0.1)。 这工作正常,除…

当X-Forwarded-For头部已经在它到达我的代理之前已经被设置,这将失败。 在这种情况下,XFF标题包含三个或更多的IP地址。 修剪最后一个仍然留下了多个和std.ip扼stream圈,延迟了几秒钟的请求,当然无法检查ACL。

我需要确保XFF标题只包含一个IP(IPv4或IPv6)后,我已经closures了代理服务器。 这应该是客户的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中完成。

当我可以与头文件交互时,Varnishstream中的第一点是在vcl_recv()中,此时Varnish已经将client.ip添加到了列表的末尾。

我希望使用正则expression式来捕获最后两个项目(IPv4或IPv6)到一个编号的捕获组($ 1),并简单地用捕获组replace头。 喜欢这个:

 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"); } 

第三个参数(replace正则expression式匹配的字符的string)不起作用。 即使正则expression式只捕获最后两个IP地址,结果标题也与以前完全一样。

我怎样才能扔掉XFF头的最后两个IP地址?

你的正则expression式看起来不错。 我唯一看到的是你要求自己更换组。

它应该工作,如果你添加^(.*)在正则expression式的开始和第二个参数replace\2

 set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2"); 

}

这就是说,我不认为这是一个好主意,改变XFF头。 添加一个头部应该更加标准化,而不是改变由中间代理发送的删除信息。