在以下设置中:
Client -> LB -> Varnish
我想配置 Varnish acls 以根据客户端的 IP 采取某些操作。LB 将客户端的 IP 发送到名为“ClientIP”的变量中,Varnish 可以通过该变量读取。req.httpd.ClientIP.
我尝试了以下方法:
acl admin_net {
"10.10.1.160"/27;
}
sub vcl_deliever {
if (req.http.ClientIP ~ admin_net) {
// do something ...
}
}
但 VCL 编译失败,提示“Expected CSTR got 'admin_net'”(C 字符串?)。我可以通过 解决这个问题req.http.ClientIP ~ "10.10.1.*")
,但我必须注释掉 ACL 行。
还有其他方法可以使其与 ACL 配合使用吗?我client.ip
也看过了,这是一个只读变量。在上述设置中,它包含 LB 的 IP,而不是客户端的 IP。
答案1
实际上,Varnish 将 client.ip 作为不同的数据类型处理,因此您可以针对此值使用 ACL。这不适用于 req.http.ClientIP(或所有 req.http.* 参数)等文本值。因此,使用此文本值的正则表达式似乎是一个很好的解决方案。
或者,您可以使用特定模块来设置客户端 IP。例如,我发现了这个:http://lassekarstensen.wordpress.com/2013/07/22/setting-client-ip-in-varnish-vcl-with-libvmod-ipcast/
答案2
这可以使用标准网,假设 ClientIP 标头已在 vcl_recv() 中设置。例如:
vcl 4.0;
import std;
acl admin_net {
"10.10.1.160/27";
}
sub vcl_deliver {
if (std.ip(req.http.ClientIP,"0.0.0.0") ~ admin_net) {
// do something ...
}
}
答案3
如果您的负载均衡器支持此处概述的“PROXY”协议,那么 alexus 的答案实际上就是正确答案:https://info.varnish-software.com/blog/topic/proxy-protocol
使用 PROXY 协议,您的负载均衡器将会告知 Varnish 真实的客户端 IP 地址并相应地设置 client.ip。
Alexus 的代码工作原理:
acl e410 {
"5.9.0.0"/16;
}
sub vcl_recv {
...
if (client.ip ~ e410) {
error 410;
}
...
}
上述代码示例将完全按照您的要求执行。支持 PROXY 协议的负载均衡器包括:
- HA代理
- NginX
- Apache HTTPD
- 亚马逊的弹性负载均衡器
.. 仅举几个例子。下面是更完整的列表:https://www.haproxy.com/blog/haproxy/proxy-protocol/
答案4
以下是我在 varnish 中实现 acl 的方法:
acl e410 {
"5.9.0.0"/16;
}
sub vcl_recv {
...
if (client.ip ~ e410) {
error 410;
}
...
}
尝试查看内部varnishlog
并发布输出,这样会更容易找出问题所在......